-package charactermanaj.graphics.filters;\r
-\r
-import java.awt.Color;\r
-\r
-import charactermanaj.graphics.colormodel.HSYColorModel;\r
-\r
-public class BackgroundColorFilter extends AbstractFilter {\r
-\r
- /**\r
- * 背景モード.\r
- * @author seraphy\r
- */\r
- public enum BackgroundColorMode {\r
- \r
- ALPHABREND(false, false, 1) {\r
- @Override\r
- public void filter(BackgroundColorFilter me, int[] pixcels) {\r
- me.alphabrend(pixcels);\r
- }\r
- },\r
- \r
- OPAQUE(false, true, 2) {\r
- @Override\r
- public void filter(BackgroundColorFilter me, int[] pixcels) {\r
- me.opaque(pixcels);\r
- }\r
- },\r
- \r
- GRAYSCALE(true, false, 4) {\r
- @Override\r
- public void filter(BackgroundColorFilter me, int[] pixcels) {\r
- me.grayscale(pixcels);\r
- }\r
- },\r
- \r
- DRAW_ALPHA(true, true, 8) {\r
- @Override\r
- public void filter(BackgroundColorFilter me, int[] pixcels) {\r
- me.drawAlpha(pixcels);\r
- }\r
- };\r
- \r
- private final boolean grayscale;\r
- \r
- private final boolean noAlphachanel;\r
- \r
- private final int mask;\r
-\r
- public abstract void filter(BackgroundColorFilter me, int[] pixcels);\r
- \r
- BackgroundColorMode(boolean grayscale, boolean noAlphachanel, int mask) {\r
- this.grayscale = grayscale;\r
- this.noAlphachanel = noAlphachanel;\r
- this.mask = mask;\r
- }\r
- \r
- public boolean isNoAlphaChannel() {\r
- return this.noAlphachanel;\r
- }\r
- \r
- public boolean isGrayscale() {\r
- return this.grayscale;\r
- }\r
- \r
- public int mask() {\r
- return mask;\r
- }\r
-\r
- public static BackgroundColorMode valueOf(boolean noAlphachanel, boolean grayscale) {\r
- for (BackgroundColorMode mode : values()) {\r
- if (mode.isNoAlphaChannel() == noAlphachanel && mode.isGrayscale() == grayscale) {\r
- return mode;\r
- }\r
- }\r
- throw new RuntimeException("構成に誤りがあります.");\r
- }\r
- \r
- }\r
- \r
- /**\r
- * 背景モード\r
- */\r
- private BackgroundColorMode mode;\r
- \r
- /**\r
- * 背景色、グレースケールまたはアルファ表示モードでは不要\r
- */\r
- private Color bgColor;\r
-\r
-\r
- /**\r
- * 背景モードと背景色を指定して背景色描画フィルタを構築する.\r
- * @param mode モード\r
- * @param bgColor 背景色、(グレースケールまたはアルファではnull化)\r
- */\r
- public BackgroundColorFilter(BackgroundColorMode mode, Color bgColor) {\r
- if (mode == null) {\r
- // モードは必須.\r
- throw new IllegalArgumentException();\r
- }\r
- if (!mode.isGrayscale() && bgColor == null) {\r
- // グレースケールもしくはアルファ表示モード以外は背景色は必須.\r
- throw new IllegalArgumentException();\r
- }\r
- \r
- this.mode = mode;\r
- this.bgColor = bgColor;\r
- }\r
- \r
- @Override\r
- protected void filter(int[] pixcels) {\r
- mode.filter(this, pixcels);\r
- }\r
- \r
- /**\r
- * 普通のアルファブレンドします.\r
- * @param pixcels\r
- */\r
- public void alphabrend(int[] pixcels) {\r
- int br = bgColor.getRed();\r
- int bg = bgColor.getGreen();\r
- int bb = bgColor.getBlue();\r
-\r
- final int mx = pixcels.length;\r
- for (int idx = 0; idx < mx; idx++) {\r
- int argb = pixcels[idx];\r
-\r
- int b = argb & 0xff;\r
- int g = (argb >>>= 8) & 0xff;\r
- int r = (argb >>>= 8) & 0xff;\r
- int a = (argb >>>= 8) & 0xff;\r
- \r
- if (a == 0) {\r
- // 完全透過ならば背景色まま\r
- b = bb;\r
- g = bg;\r
- r = br;\r
-\r
- } else if (a != 0xff) {\r
- // 完全非透過でなければアルファブレンド\r
- b = ((b * a) / 0xff + (bb * (0xff - a) / 0xff)) & 0xff;\r
- g = ((g * a) / 0xff + (bg * (0xff - a) / 0xff)) & 0xff;\r
- r = ((r * a) / 0xff + (br * (0xff - a) / 0xff)) & 0xff;\r
- }\r
-\r
- argb = 0xff000000 | (r << 16) | (g << 8) | b;\r
- pixcels[idx] = argb;\r
- }\r
- }\r
-\r
- /**\r
- * 完全透過の部分のみ背景色を設定し、それ以外は元の色のままアルファを取り除く.<br>\r
- * @param pixcels ピクセルデータ\r
- */\r
- public void opaque(int[] pixcels) {\r
- int bgRgb = bgColor.getRGB();\r
-\r
- final int mx = pixcels.length;\r
- for (int idx = 0; idx < mx; idx++) {\r
- int argb = pixcels[idx];\r
- int a = (argb >>> 24) & 0xff;\r
- int rgb = (argb & 0xffffff);\r
- \r
- if (a == 0) {\r
- rgb = bgRgb;\r
- }\r
- \r
- argb = 0xff000000 | rgb;\r
- pixcels[idx] = argb;\r
- }\r
- }\r
-\r
- /**\r
- * アルファを取り除き、グレスケールで表現する.<br>\r
- * RGBチャネルのうち、RBはアルファ適用されたグレースケールで、\r
- * Gチャネルはアルファ未適用のグレースケールで表現される.<br>\r
- * @param pixcels ピクセルデータ\r
- */\r
- public void grayscale(int[] pixcels) {\r
- final int mx = pixcels.length;\r
- for (int idx = 0; idx < mx; idx++) {\r
- int argb = pixcels[idx];\r
- \r
- int b = argb & 0xff;\r
- int g = (argb >>>= 8) & 0xff;\r
- int r = (argb >>>= 8) & 0xff;\r
- int a = (argb >>>= 8) & 0xff;\r
-\r
- int gray_brend = 0;\r
- int gray_plain = 0;\r
- if (a != 0) {\r
- // 輝度の算定(グレースケール化)\r
- gray_brend = HSYColorModel.getGrayscale(r, g, b);\r
- gray_plain = gray_brend;\r
- \r
- if (a != 0xff) {\r
- // アルファによる調整\r
- gray_brend = ((gray_brend * a) / 0xff) & 0xff;\r
- }\r
- }\r
- \r
- argb = 0xff000000 | (gray_brend << 16) | (gray_plain << 8) | gray_brend;\r
- pixcels[idx] = argb;\r
- }\r
- }\r
-\r
- /**\r
- * アルファチャネルとグレースケールを重ねて表示する.<br>\r
- * アルファ未適用のグレースケールをRチャネル、\r
- * アルファを無し・半透明・透明の3段階にしたものをGチャネル、\r
- * アルファをBチャネルで表現する.<br>\r
- * Gチャネルは、完全透過は濃緑(0x80)、完全非透過は黒(0xff)、半透明は明緑(0xff)となる.<br>\r
- * @param pixcels ピクセルデータ\r
- */\r
- public void drawAlpha(int[] pixcels) {\r
- final int mx = pixcels.length;\r
- for (int idx = 0; idx < mx; idx++) {\r
- int argb = pixcels[idx];\r
- \r
- int b = argb & 0xff;\r
- int g = (argb >>>= 8) & 0xff;\r
- int r = (argb >>>= 8) & 0xff;\r
- int a = (argb >>>= 8) & 0xff;\r
-\r
- int gray_plain = (r + g + b) / 3;\r
- int alpha_off = (a == 0) ? 0x80 : (a == 0xff) ? 0x00 : 0xff;\r
-\r
- argb = 0xff000000 | (gray_plain << 16) | (alpha_off << 8) | a;\r
- pixcels[idx] = argb;\r
- }\r
- }\r
-}\r
+package charactermanaj.graphics.filters;
+
+import java.awt.Color;
+
+import charactermanaj.graphics.colormodel.HSYColorModel;
+
+public class BackgroundColorFilter extends AbstractFilter {
+
+ /**
+ * 背景モード.
+ * @author seraphy
+ */
+ public enum BackgroundColorMode {
+
+ ALPHABREND(false, false, 1) {
+ @Override
+ public void filter(BackgroundColorFilter me, int[] pixcels) {
+ me.alphabrend(pixcels);
+ }
+ },
+
+ OPAQUE(false, true, 2) {
+ @Override
+ public void filter(BackgroundColorFilter me, int[] pixcels) {
+ me.opaque(pixcels);
+ }
+ },
+
+ GRAYSCALE(true, false, 4) {
+ @Override
+ public void filter(BackgroundColorFilter me, int[] pixcels) {
+ me.grayscale(pixcels);
+ }
+ },
+
+ DRAW_ALPHA(true, true, 8) {
+ @Override
+ public void filter(BackgroundColorFilter me, int[] pixcels) {
+ me.drawAlpha(pixcels);
+ }
+ };
+
+ private final boolean grayscale;
+
+ private final boolean noAlphachanel;
+
+ private final int mask;
+
+ public abstract void filter(BackgroundColorFilter me, int[] pixcels);
+
+ BackgroundColorMode(boolean grayscale, boolean noAlphachanel, int mask) {
+ this.grayscale = grayscale;
+ this.noAlphachanel = noAlphachanel;
+ this.mask = mask;
+ }
+
+ public boolean isNoAlphaChannel() {
+ return this.noAlphachanel;
+ }
+
+ public boolean isGrayscale() {
+ return this.grayscale;
+ }
+
+ public int mask() {
+ return mask;
+ }
+
+ public static BackgroundColorMode valueOf(boolean noAlphachanel, boolean grayscale) {
+ for (BackgroundColorMode mode : values()) {
+ if (mode.isNoAlphaChannel() == noAlphachanel && mode.isGrayscale() == grayscale) {
+ return mode;
+ }
+ }
+ throw new RuntimeException("構成に誤りがあります.");
+ }
+
+ }
+
+ /**
+ * 背景モード
+ */
+ private BackgroundColorMode mode;
+
+ /**
+ * 背景色、グレースケールまたはアルファ表示モードでは不要
+ */
+ private Color bgColor;
+
+
+ /**
+ * 背景モードと背景色を指定して背景色描画フィルタを構築する.
+ * @param mode モード
+ * @param bgColor 背景色、(グレースケールまたはアルファではnull化)
+ */
+ public BackgroundColorFilter(BackgroundColorMode mode, Color bgColor) {
+ if (mode == null) {
+ // モードは必須.
+ throw new IllegalArgumentException();
+ }
+ if (!mode.isGrayscale() && bgColor == null) {
+ // グレースケールもしくはアルファ表示モード以外は背景色は必須.
+ throw new IllegalArgumentException();
+ }
+
+ this.mode = mode;
+ this.bgColor = bgColor;
+ }
+
+ @Override
+ protected void filter(int[] pixcels) {
+ mode.filter(this, pixcels);
+ }
+
+ /**
+ * 普通のアルファブレンドします.
+ * @param pixcels
+ */
+ public void alphabrend(int[] pixcels) {
+ int br = bgColor.getRed();
+ int bg = bgColor.getGreen();
+ int bb = bgColor.getBlue();
+
+ final int mx = pixcels.length;
+ for (int idx = 0; idx < mx; idx++) {
+ int argb = pixcels[idx];
+
+ int b = argb & 0xff;
+ int g = (argb >>>= 8) & 0xff;
+ int r = (argb >>>= 8) & 0xff;
+ int a = (argb >>>= 8) & 0xff;
+
+ if (a == 0) {
+ // 完全透過ならば背景色まま
+ b = bb;
+ g = bg;
+ r = br;
+
+ } else if (a != 0xff) {
+ // 完全非透過でなければアルファブレンド
+ b = ((b * a) / 0xff + (bb * (0xff - a) / 0xff)) & 0xff;
+ g = ((g * a) / 0xff + (bg * (0xff - a) / 0xff)) & 0xff;
+ r = ((r * a) / 0xff + (br * (0xff - a) / 0xff)) & 0xff;
+ }
+
+ argb = 0xff000000 | (r << 16) | (g << 8) | b;
+ pixcels[idx] = argb;
+ }
+ }
+
+ /**
+ * 完全透過の部分のみ背景色を設定し、それ以外は元の色のままアルファを取り除く.<br>
+ * @param pixcels ピクセルデータ
+ */
+ public void opaque(int[] pixcels) {
+ int bgRgb = bgColor.getRGB();
+
+ final int mx = pixcels.length;
+ for (int idx = 0; idx < mx; idx++) {
+ int argb = pixcels[idx];
+ int a = (argb >>> 24) & 0xff;
+ int rgb = (argb & 0xffffff);
+
+ if (a == 0) {
+ rgb = bgRgb;
+ }
+
+ argb = 0xff000000 | rgb;
+ pixcels[idx] = argb;
+ }
+ }
+
+ /**
+ * アルファを取り除き、グレスケールで表現する.<br>
+ * RGBチャネルのうち、RBはアルファ適用されたグレースケールで、
+ * Gチャネルはアルファ未適用のグレースケールで表現される.<br>
+ * @param pixcels ピクセルデータ
+ */
+ public void grayscale(int[] pixcels) {
+ final int mx = pixcels.length;
+ for (int idx = 0; idx < mx; idx++) {
+ int argb = pixcels[idx];
+
+ int b = argb & 0xff;
+ int g = (argb >>>= 8) & 0xff;
+ int r = (argb >>>= 8) & 0xff;
+ int a = (argb >>>= 8) & 0xff;
+
+ int gray_brend = 0;
+ int gray_plain = 0;
+ if (a != 0) {
+ // 輝度の算定(グレースケール化)
+ gray_brend = HSYColorModel.getGrayscale(r, g, b);
+ gray_plain = gray_brend;
+
+ if (a != 0xff) {
+ // アルファによる調整
+ gray_brend = ((gray_brend * a) / 0xff) & 0xff;
+ }
+ }
+
+ argb = 0xff000000 | (gray_brend << 16) | (gray_plain << 8) | gray_brend;
+ pixcels[idx] = argb;
+ }
+ }
+
+ /**
+ * アルファチャネルとグレースケールを重ねて表示する.<br>
+ * アルファ未適用のグレースケールをRチャネル、
+ * アルファを無し・半透明・透明の3段階にしたものをGチャネル、
+ * アルファをBチャネルで表現する.<br>
+ * Gチャネルは、完全透過は濃緑(0x80)、完全非透過は黒(0xff)、半透明は明緑(0xff)となる.<br>
+ * @param pixcels ピクセルデータ
+ */
+ public void drawAlpha(int[] pixcels) {
+ final int mx = pixcels.length;
+ for (int idx = 0; idx < mx; idx++) {
+ int argb = pixcels[idx];
+
+ int b = argb & 0xff;
+ int g = (argb >>>= 8) & 0xff;
+ int r = (argb >>>= 8) & 0xff;
+ int a = (argb >>>= 8) & 0xff;
+
+ int gray_plain = (r + g + b) / 3;
+ int alpha_off = (a == 0) ? 0x80 : (a == 0xff) ? 0x00 : 0xff;
+
+ argb = 0xff000000 | (gray_plain << 16) | (alpha_off << 8) | a;
+ pixcels[idx] = argb;
+ }
+ }
+}