Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Fastest method to calculate difference between two ARGB ints in Java?

Tags:

java

colors

Given an int from a DataBuffer which has ARGB data packed in it with the masks

A = 0xFF000000 R = 0xFF0000 G = 0xFF00 B = 0xFF

I'm doing the following but wonder if there isn't a faster method in Java?

        DataBuffer db1 = img1.getData().getDataBuffer();
        DataBuffer db2 = img2.getData().getDataBuffer();

        int x, y;
        int totalDiff = 0;
        for (int i = 0; i < WIDTH * HEIGHT; ++i) {
            x = db1.getElem(i);
            y = db2.getElem(i);

            totalDiff += Math.abs((x & 0xFF) - (y & 0xFF))
                       + Math.abs(((x & 0xFF00) >> 8) - ((y & 0xFF00) >> 8))
                       + Math.abs(((x & 0xFF0000) >> 16) - ((y & 0xFF0000) >> 16 ));
        }
like image 680
Johnny Avatar asked Jun 07 '26 04:06

Johnny


2 Answers

If you really need the speed up you might to check the type of DataBuffer and provide optimized code for the concrete type such that you save the calls to getElem(i). This will speed up your code a little bit.

Something like this:

    DataBuffer db1 = img1.getData().getDataBuffer();
    DataBuffer db2 = img2.getData().getDataBuffer();

    int totalDiff = 0;
    int x, y;
    if (db1 instanceof DataBufferInt && db2 instanceof DataBufferInt) {
        int[] data1 = ((DataBufferInt) db1).getData();
        int[] data2 = ((DataBufferInt) db2).getData();
        for (int i = 0; i < WIDTH * HEIGHT; ++i) {
            x = data1[i];
            y = data2[i];

            totalDiff += Math.abs((x & 0xFF) - (y & 0xFF))
                + Math.abs(((x & 0xFF00) >> 8) - ((y & 0xFF00) >> 8))
                + Math.abs(((x & 0xFF0000) >> 16) - ((y & 0xFF0000) >> 16));
        }
    } else {
        for (int i = 0; i < WIDTH * HEIGHT; ++i) {
            x = db1.getElem(i);
            y = db2.getElem(i);

            totalDiff += Math.abs((x & 0xFF) - (y & 0xFF))
                    + Math.abs(((x & 0xFF00) >> 8) - ((y & 0xFF00) >> 8))
                    + Math.abs(((x & 0xFF0000) >> 16) - ((y & 0xFF0000) >> 16));
        }
    }

Edit: Another idea that would bring you a MUCH higher speed up. If this is just a heuristic it might be enough to calculate the difference of a somewhat "downsampled" version of your images. Replace ++i through i+=10 and gain a speed up by factor 10. Of course if this makes sense depends on the types of your images.

Edit: In one comment you mentioned it's a fitness function for a GA ... in this case it might be enough to grab 100 (or just 10?) random locations from your images and compare the pixels at that locations. The gained speed up will most probably outdo the loss in accuracy.

like image 90
Arne Deutsch Avatar answered Jun 10 '26 17:06

Arne Deutsch


Agree with @Arne.

You could also remove the shift rights

(x & 0xFF0000) >> 16) - ((y & 0xFF0000) >> 16 ). 

You know that abs(XX0000 - YY0000) is only going to be in the range 0-255.

It would help if you could suggest what it is you are trying to determine?

That is, can the pixel information be store more conducively to what you are trying to acheive, for example as chrominance (YUV, YCrCb)?

like image 33
Adrian Regan Avatar answered Jun 10 '26 17:06

Adrian Regan