Java: comment faire une copie rapide d'un pixel de BufferedImage? (Test unitaire inclus)

StackOverflow https://stackoverflow.com/questions/2825837

  •  26-09-2019
  •  | 
  •  

Question

Je veux faire une copie (d'une zone rectangulaire) des valeurs ARVB d'une BufferedImage source dans un BufferedImage de destination. Non compositing doit être fait. Si je copie un pixel avec une valeur ARGB de 0x8000BE50 (alpha valeur à 128), le pixel de destination doit être exactement 0x8000BE50, remplaçant totalement le pixel de destination

J'ai une question très précise et j'ai fait un test unitaire pour montrer ce que je dois. Le test unitaire est entièrement fonctionnelle et autonome et passe très bien et fait exactement ce que je veux.

Cependant, je veux un plus rapide et plus efficace de la mémoire méthode pour remplacer copySrcIntoDstAt (...).

C'est tout le point de ma question: je ne suis pas après comment « remplir » l'image d'une manière plus rapide (ce que je faisais est juste un exemple pour un test unitaire). Tout ce que je veux est de savoir ce qui serait un rapide et efficace de la mémoire façon de le faire (par exemple rapide et ne pas créer des objets inutiles).

La preuve de concept mise en œuvre, je l'ai fait est évidemment très efficace de la mémoire, mais il est lent (faire un getRGB et un setRGB pour chaque pixel).

Schématiquement, j'ai ceci: (où A indique pixels correspondant de l'image de destination avant la copie)

AAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAA

Et je veux avoir ceci:

AAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAABBBBAAA
AAAAAAAAAAAAABBBBAAA
AAAAAAAAAAAAAAAAAAAA

où 'B' représente les pixels dans src image.

Notez que je suis à la recherche d'un remplacement exact de la copySrcIntoDstAt (...) méthode, pas un lien API / citation.

import org.junit.Test;

import java.awt.image.BufferedImage;

import static org.junit.Assert.*;

public class TestCopy {

    private static final int COL1 = 0x8000BE50;  // alpha at 128
    private static final int COL2 = 0x1732FE87;  // alpha at  23 

    @Test
    public void testPixelsCopy() {
        final BufferedImage src = new BufferedImage(  5,  5, BufferedImage.TYPE_INT_ARGB );
        final BufferedImage dst = new BufferedImage( 20, 20, BufferedImage.TYPE_INT_ARGB );
        convenienceFill( src, COL1 );
        convenienceFill( dst, COL2 );
        copySrcIntoDstAt( src, dst, 3, 4 );
        for (int x = 0; x < dst.getWidth(); x++) {
            for (int y = 0; y < dst.getHeight(); y++) {
                if ( x >= 3 && x <= 7 && y >= 4 && y <= 8 ) {
                    assertEquals( COL1, dst.getRGB(x,y) );
                } else {
                    assertEquals( COL2, dst.getRGB(x,y) );
                }
            }
        }
    }

    // clipping is unnecessary
    private static void copySrcIntoDstAt(
            final BufferedImage src,
            final BufferedImage dst,
            final int dx,
            final int dy
    ) {
        // TODO: replace this by a much more efficient method
        for (int x = 0; x < src.getWidth(); x++) {
            for (int y = 0; y < src.getHeight(); y++) {
                dst.setRGB( dx + x, dy + y, src.getRGB(x,y) );
            }
        }
    }

    // This method is just a convenience method, there's
    // no point in optimizing this method, this is not what
    // this question is about
    private static void convenienceFill(
            final BufferedImage bi,
            final int color
    ) {
        for (int x = 0; x < bi.getWidth(); x++) {
            for (int y = 0; y < bi.getHeight(); y++) {
                bi.setRGB( x, y, color );
            }
        }
    }

}
Était-ce utile?

La solution

private static void copySrcIntoDstAt(final BufferedImage src,
        final BufferedImage dst, final int dx, final int dy) {
    int[] srcbuf = ((DataBufferInt) src.getRaster().getDataBuffer()).getData();
    int[] dstbuf = ((DataBufferInt) dst.getRaster().getDataBuffer()).getData();
    int width = src.getWidth();
    int height = src.getHeight();
    int dstoffs = dx + dy * dst.getWidth();
    int srcoffs = 0;
    for (int y = 0 ; y < height ; y++ , dstoffs+= dst.getWidth(), srcoffs += width ) {
        System.arraycopy(srcbuf, srcoffs , dstbuf, dstoffs, width);
    }
}
Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top