Как контролировать размер пикселя цветовой модели ErrorDiffusionDescriptor?

Я пытаюсь преобразовать изображение прямой цветовой модели в битональное индексированное изображение (1 бит на пиксель) и сохранить индексированное изображение как BMP.

Как указано на домашней странице Java Advanced Imaging API:

Битовая глубина закодированного вывода определяется битовой глубиной исходного изображения.

При просмотре исходного кода BMPImageWriter механизмом этого является возврат значение ColorModel # getPixelSize ().

Используя уменьшенную копию изображения из Wikimedia Commons, я сначала выполняю квантование цвета для получения таблицы поиска цветов, а затем распространение ошибок для применения дизеринга Флойда – Стейнберга:

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:

Результат квантования цвета и распространения ошибок на образце изображения.

Размер этого изображения - 167 Кбайт.

Я где-то видел, что один из способов передачи цветовой модели для распространения ошибок - это установить подсказку рендеринга 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 КиБ, примерно что, когда я использую MS Paint для преобразования образца изображения в монохромное растровое изображение. Итак, похоже, что BMPImageWriter JAI использует правильную кодировку, но если вы внимательно посмотрите на второе изображение, соседние столбцы пикселей разделены на восемь пикселей. Фактически, вы можете видеть первое изображение, только каждый столбец пикселей из первого изображения расширяется до 8 столбцов пикселей.

Это ошибка в JAI? Могу ли я что-то сделать, чтобы свернуть эти столбцы пикселей шириной 8 в пиксели в один столбец?


person Daniel Trebbien    schedule 10.03.2013    source источник


Ответы (1)


Это должно работать с PNG 24 BPP:

    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");
person Dror Bereznitsky    schedule 19.03.2013
comment
Эй, сработало! Я просто изменил его, чтобы использовать таблицу поиска, вычисленную с помощью квантователя цвета op и вуаля. Большое спасибо! - person Daniel Trebbien; 20.03.2013