3

ダイレクトカラーモデル画像をビット調のインデックス付き画像(1ピクセルあたり1ビット)に変換し、インデックス付き画像をBMPとして保存しようとしています。

Java Advanced Imaging APIホームページに記載されているように:

エンコードされた出力のビット深度は、ソース画像のビット深度によって決まります。

のソースコードをBMPImageWriter見ると、このメカニズムはColorModel#getPixelSize()の戻り値です。

ウィキメディアコモンズの画像の縮小コピーを使用して、最初に色の量子化を実行してカラールックアップテーブルを取得し、次に誤差拡散を実行してフロイド-スタインバーグディザリングを適用します。

PlanarImage surrogateImage = PlanarImage.wrapRenderedImage(image);

PlanarImage op = ColorQuantizerDescriptor.create(surrogateImage, ColorQuantizerDescriptor.OCTTREE, 2, null, null, null, null, null);
LookupTableJAI lut = (LookupTableJAI)op.getProperty("LUT");
IndexColorModel cm = new IndexColorModel(1, lut.getByteData()[0].length, lut.getByteData()[0], lut.getByteData()[1], lut.getByteData()[2]);

op = ErrorDiffusionDescriptor.create(surrogateImage, lut, KernelJAI.ERROR_FILTER_FLOYD_STEINBERG, null);

image = op.getAsBufferedImage();

問題は、image.getColorModel().getPixelSize()8を返すため、画像が8bppビットマップとして保存されることです。

サンプル画像での色の量子化と誤差拡散の結果。

この画像のサイズは167KiBです。

カラーモデルを誤差拡散に渡す1つの方法は、JAI.KEY_IMAGE_LAYOUTレンダリングヒントを設定することです。

ImageLayout layout = new ImageLayout();
layout.setTileWidth(image.getWidth());
layout.setTileHeight(image.getHeight());
layout.setColorModel(cm);
layout.setSampleModel(op.getSampleModel());
RenderingHints rh = new RenderingHints(JAI.KEY_IMAGE_LAYOUT, layout);
op = ErrorDiffusionDescriptor.create(surrogateImage, lut, KernelJAI.ERROR_FILTER_FLOYD_STEINBERG, rh);

image.getColorModel().getPixelSize()現在は1を返しますが、結果の画像は大幅に変更されます。

ImageLayoutを通過するサンプル画像での色の量子化と誤差拡散の結果。

ただし、この画像のサイズは21 KiBで、MSペイントを使用してサンプル画像をモノクロビットマップに変換した場合とほぼ同じです。したがって、JAIBMPImageWriterは正しいエンコーディングを使用しているように見えますが、2番目の画像をよく見ると、隣接するピクセルの列は8ピクセル離れています。実際、最初の画像を見ることができます。最初の画像のピクセルの各列のみが8列のピクセルに展開されます。

これはJAIのバグですか?これらの8幅のピクセル列を単一列のピクセルに折りたたむためにできることはありますか?

4

1 に答える 1

2

これは24BPPpngで機能するはずです。

    String filename = "jEEDL.png";

    PlanarImage image = PlanarImage.wrapRenderedImage(JAI.create("fileload", filename));

    LookupTableJAI lut = new LookupTableJAI(new byte[][] {{(byte)0x00, (byte)0xff}, {(byte)0x00, (byte)0xff}, {(byte)0x00, (byte)0xff}});
    ImageLayout layout = new ImageLayout();
    byte[] map = new byte[] {(byte)0x00, (byte)0xff};
    ColorModel cm = new IndexColorModel(1, 2, map, map, map);
    layout.setColorModel(cm);
    SampleModel sm = new MultiPixelPackedSampleModel(DataBuffer.TYPE_BYTE,
            image.getWidth(),
            image.getHeight(),
            1);
    layout.setSampleModel(sm);
    RenderingHints hints = new RenderingHints(JAI.KEY_IMAGE_LAYOUT, layout);
    PlanarImage op = ErrorDiffusionDescriptor.create(image, lut, KernelJAI.ERROR_FILTER_FLOYD_STEINBERG, hints);

    BufferedImage dst  = op.getAsBufferedImage();

    JAI.create("filestore", dst, "jEEDL.bmp", "BMP");
于 2013-03-19T20:45:55.027 に答える