1 package charactermanaj.graphics.filters;
\r
3 import java.awt.Rectangle;
\r
4 import java.awt.RenderingHints;
\r
5 import java.awt.geom.Point2D;
\r
6 import java.awt.geom.Rectangle2D;
\r
7 import java.awt.image.BufferedImage;
\r
8 import java.awt.image.BufferedImageOp;
\r
9 import java.awt.image.ColorModel;
\r
10 import java.awt.image.DataBufferInt;
\r
11 import java.awt.image.WritableRaster;
\r
17 public abstract class AbstractFilter implements BufferedImageOp {
\r
21 * 派生クラスでオーバーライドする.<br>
\r
22 * @param pixcels ARGB形式のピクセルデータ
\r
24 protected abstract void filter(int[] pixcels);
\r
26 public BufferedImage createCompatibleDestImage(BufferedImage src, ColorModel destCM) {
\r
27 if (destCM == null) {
\r
28 destCM = src.getColorModel();
\r
30 int w = src.getWidth();
\r
31 int h = src.getHeight();
\r
32 return new BufferedImage(destCM,
\r
33 destCM.createCompatibleWritableRaster(w, h),
\r
34 destCM.isAlphaPremultiplied(), null);
\r
37 public BufferedImage filter(BufferedImage src, BufferedImage dest) {
\r
39 dest = createCompatibleDestImage(src, null);
\r
41 int w = src.getWidth();
\r
42 int h = src.getHeight();
\r
44 int imageType = src.getType();
\r
46 boolean shared = false;
\r
47 if (src == dest && (imageType == BufferedImage.TYPE_INT_ARGB || imageType == BufferedImage.TYPE_INT_RGB)) {
\r
48 // 元イメージと出力先イメージが同一であり、且つ、
\r
49 // イメージがARGB/RGB形式であればピクセルデータはイメージが持つバッファそのものを共有アクセスする.
\r
50 // したがって、setPixcelsの呼び出しは不要.
\r
54 // 元イメージと出力先イメージが異なるか、もしくは、
\r
55 // イメージがARGB/RGB形式以外であれば、RGB形式のint配列に変換して処理する.
\r
56 // イメージに書き戻すためにsetPixcelsの呼び出しが必要となる.
\r
58 pixcels = new int[len];
\r
60 pixcels = getPixcels(src, 0, 0, w, h, pixcels);
\r
65 setPixcels(dest, 0, 0, w, h, pixcels);
\r
72 public Rectangle2D getBounds2D(BufferedImage src) {
\r
73 int w = src.getWidth();
\r
74 int h = src.getHeight();
\r
75 return new Rectangle(0, 0, w, h);
\r
78 public Point2D getPoint2D(Point2D srcPt, Point2D dstPt) {
\r
79 return (Point2D) srcPt.clone();
\r
82 public RenderingHints getRenderingHints() {
\r
88 * 画像のタイプがARGBもしくはRGBの場合はpixcelsにnullを指定して格納先を指定しない場合は
\r
90 * そうでない場合はピクセルデータはイメージのピクセルバッファを、そのまま返す.(つまり、変更は即イメージの変更になる.)<br>
\r
91 * ARGB,RGB以外のイメージは常に幅x高さ分のRGB(もしくはARGB)を格納できるだけのバッファを指定しなければならない.<br>
\r
92 * @param img 対象のイメージ
\r
97 * @param pixcels 格納先バッファ、もしくはnull
\r
100 protected int[] getPixcels(BufferedImage img, int x, int y, int w, int h, int[] pixcels) {
\r
101 if (w <= 0 || h <= 0) {
\r
105 if (pixcels != null && pixcels.length < len) {
\r
106 throw new IllegalArgumentException("array too short.");
\r
109 int imageType = img.getType();
\r
110 if (imageType == BufferedImage.TYPE_INT_ARGB || imageType == BufferedImage.TYPE_INT_RGB) {
\r
111 WritableRaster raster = img.getRaster();
\r
112 if (pixcels == null) {
\r
113 DataBufferInt buf = (DataBufferInt) raster.getDataBuffer();
\r
114 return buf.getData();
\r
116 return (int[]) raster.getDataElements(x, y, w, h, pixcels);
\r
119 if (pixcels == null) {
\r
120 throw new IllegalArgumentException("image type error.");
\r
122 return img.getRGB(x, y, w, h, pixcels, 0, w);
\r
126 * ピクセルデータをイメージに書き戻す.<br>
\r
127 * ピクセルデータがnullであるか幅または高さが0であれば何もしない.<br>
\r
128 * @param img 対象のイメージ
\r
133 * @param pixcels ピクセルデータ、nullの場合は何もしない.
\r
135 protected void setPixcels(BufferedImage img, int x, int y, int w, int h, int[] pixcels) {
\r
137 if (pixcels == null || w == 0 || h == 0) {
\r
140 if (pixcels.length < len) {
\r
141 throw new IllegalArgumentException("array too short.");
\r
143 int imageType = img.getType();
\r
144 if (imageType == BufferedImage.TYPE_INT_ARGB || imageType == BufferedImage.TYPE_INT_RGB) {
\r
145 WritableRaster raster = img.getRaster();
\r
146 raster.setDataElements(x, y, w, h, pixcels);
\r
149 img.setRGB(x, y, w, h, pixcels, 0, w);
\r