3 votes

Comment contrôler la taille des pixels du modèle de couleur d'un ErrorDiffusionDescriptor ?

J'essaie de convertir une image en modèle de couleur directe en une image indexée bitonale (1 bit par pixel) et d'enregistrer l'image indexée au format BMP.

Comme indiqué sur le Page d'accueil de l'API Java Advanced Imaging :

La profondeur binaire de la sortie codée est déterminée par celle de l'image source.

En regardant à travers le code source de BMPImageWriter le mécanisme est la valeur de retour de la fonction ColorModel#getPixelSize() .

En utilisant une copie réduite de une image de Wikimedia Commons Je procède d'abord à la quantification des couleurs pour obtenir une table de conversion des couleurs, puis à la diffusion d'erreurs pour appliquer le tramage de Floyd-Steinberg :

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();

Le problème est que, image.getColorModel().getPixelSize() renvoie 8, l'image est donc enregistrée comme un bitmap 8bpp :

Result of color quantization and error diffusion on the sample image.

La taille de cette image est de 167 KiB.

J'ai vu quelque part qu'une façon de transmettre un modèle de couleur à la diffusion par erreur est de définir un indice de rendu 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() renvoie maintenant 1, mais l'image résultante est altérée de manière significative :

Result of color quantization and error diffusion on the sample image passing an ImageLayout.

Cependant, la taille de cette image est de 21 KiB, soit à peu près ce qu'elle est lorsque j'utilise MS Paint pour convertir l'image d'exemple en bitmap monochrome. Donc, il semble que la JAI BMPImageWriter utilise le codage correct, mais si vous regardez de près la deuxième image, les colonnes de pixels adjacentes sont séparées de huit pixels. En fait, vous pouvez plus ou moins voir la première image, mais chaque colonne de pixels de la première image est étendue à 8 colonnes de pixels.

Est-ce un bogue dans l'IMA ? Y a-t-il quelque chose que je puisse faire pour réduire ces colonnes de pixels de 8 largeurs à une seule colonne de pixels ?

2voto

drorb Points 5210

Cela devrait fonctionner avec un png de 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");

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X