JAVA Couleur[] pour BufferedImage de Couleur[] blanchi de sortie


Je manipule le code d'un moteur de rendu d'image qui crée une image de sortie à partir du tableau Color [] et mon code le met simplement à jour avec des éléments supplémentaires juste avant de l'enregistrer, c'est-à-dire lorsque l'image d'origine est réellement préparée (toutes les positions de pixels préparées pour être remplies avec

La raison pour laquelle je fais cela est d'avoir la capacité d'insérer du texte décrivant mon rendu sans avoir besoin d'un autre programme graphique externe qui le ferait (je veux avoir tout en un-aller! action sans avoir besoin d'une autre application externe).

Pour cette cause - comme je n'ai pas de portée / accès pour le BufferedImage préparé d'origine (mais j'ai accès à la couleur réelle [] à partir de laquelle il est créé), j'ai dû créer ma propre méthode de classe qui:

  1. convertir cette couleur d'origine [] en ma propre BufferedImage temporaire
  2. mettez à jour cette temp. BufferedImage avec mes trucs via Graphics2D (ajout de texte à l'image)
  3. convertir mon résultat (temp. BufferedImage avec Graphics2D) retour à la couleur []
  4. renvoyer cette couleur finale [] à la méthode de rendu de l'image d'origine cela en ferait en fait l'image finale qui est rendue et enregistré au format png

Maintenant, tout fonctionne très bien comme prévu, sauf une chose vraiment ennuyeuse que je ne peux pas me débarrasser: mon image mise à jour a l'air très bleached-like/pale (presque pas de profondeur ou d'ombres présentées) par rapport à la version originale non filigranée...

Pour moi, il ressemble simplement comme après la conversion image2color [] (en utilisant la solution de @stacker à partir d'ici Conversion de l'image en tableau de couleurs) quelque chose ne va pas/n'est pas correct, donc les couleurs deviennent pâles et je n'ai aucune idée pourquoi.

Voici la partie principale de mon code qui est en cause:

            BufferedImage sourceImage = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB);

            // Color[] to BufferedImage
            for (int k = 0; k < multiArrayList.size(); k++) {

                // PREPARE...
                int x = (int) multiArrayList.get(k)[0];
                int y = (int) multiArrayList.get(k)[1];
                int w = (int) multiArrayList.get(k)[2];
                int h = (int) multiArrayList.get(k)[3];
                Color[] data = (Color[]) multiArrayList.get(k)[4];
                int border = BORDERS[k % BORDERS.length];

                for (int by = 0; by < h; by++) {
                    for (int bx = 0; bx < w; bx++) {
                        if (bx == 0 || bx == w - 1) {
                            if (5 * by < h || 5 * (h - by - 1) < h) {
                                sourceImage.setRGB(x + bx, y + by, border);
                            }
                        } else if (by == 0 || by == h - 1) {
                            if (5 * bx < w || 5 * (w - bx - 1) < w) {
                                sourceImage.setRGB(x + bx, y + by, border);
                            }
                        }
                    }
                }
                // UPDATE...
                for (int j = 0, index = 0; j < h; j++) {
                    for (int i = 0; i < w; i++, index++) {
                        sourceImage.setRGB(x + i, y + j, data[index].copy().toNonLinear().toRGB());
                    }
                }
            }

            Graphics2D g2d = (Graphics2D) sourceImage.getGraphics();

            // paints the textual watermark
            drawString(g2d, text, centerX, centerY, sourceImage.getWidth());

            // when saved to png at this point ALL IS JUST FINE
            ImageIO.write(sourceImage, "png", new File(imageSavePath));
            g2d.dispose();

            // BufferedImage to Color array
            int[] dt = ((DataBufferInt) sourceImage.getRaster().getDataBuffer()).getData();

            bucketFull = new Color[dt.length];
            for (int i = 0; i < dt.length; i++) {
                bucketFull[i] = new Color(dt[i]);
            }

            // update and repaint output image - THIS OUTPUT IS ALREADY BLEACHED/PALE
            d.ip(0, 0, width, height, renderThreads.length + 1);
            d.iu(0, 0, width, height, bucketFull);

            // reset objects
            g2d = null;
            sourceImage = null;
            bucketFull = null;
            multiArrayList = new ArrayList<>();

J'ai testé (en l'enregistrant dans un autre .fichier png juste après l'ajout Graphics2D) qu'avant d'obtenir cette 2ème conversion, il semble absolument OK 1: 1 à l'image d'origine incl. mon texte image.

Mais comme je l'ai dit quand il est envoyé pour le rendu, il devient blanchi/pâle, c'est un problème que j'essaie de résoudre.

BTW j'ai d'abord pensé qu'il pourrait être que Graphics2D plus alors j'ai essayé sans, mais le résultat était le même, c'est blanchie/pâle version.

Bien que mon processus et mon code soient complètement différents, l'image de sortie souffre exactement de la même manière que dans ce sujet (toujours pas résolu) BufferedImage color la saturation

Voici mes 2 exemples-1er ORIGINAL, 2e MIS À JOUR (blanchi/pâle)

entrez la description de l'image ici entrez la description de l'image ici

Author: Community, 2016-06-25

1 answers

Comme suspecté, le problème est que vous convertissez les valeurs de couleur du RVB linéaire en valeurs corrigées gamma/sRGB lors de la définition des valeurs RVB sur le BufferedImage, mais la transformation inverse (retour au RVB linéaire) n'est pas effectuée lorsque vous remettez les valeurs dans le tableau Color.

Soit changer la ligne (à l'intérieur de la boucle double for):

sourceImage.setRGB(x + i, y + j, data[index].copy().toNonLinear().toRGB());

À

sourceImage.setRGB(x + i, y + j, data[index].toRGB());

(vous n'avez plus besoin du copy(), car vous ne mutez plus les valeurs, en utilisant toNonLinear()).

Cela évite le conversion tout à fait.


... ou vous pourriez probablement aussi changer la ligne en définissant les valeurs, à partir de:

bucketFull[i] = new Color(dt[i]);

À

bucketFull[i] = new Color(dt[i]).toLinear();

Sans doute, c'est plus "correct" (car AWT traite les valeurs comme étant dans l'espace colorimétrique sRGB, indépendamment), mais je crois que la première version est plus rapide et que la différence de couleur est négligeable. Donc, j'essaierais probablement le premier correctif suggéré en premier, et l'utiliserais à moins que vous ne rencontriez des couleurs qui sont désactivées.

 0
Author: haraldK, 2016-06-26 17:34:48