Search code examples
javaimage-processingbufferedimageargb

get average image of a set of images in java


I have a set of meteorological RGB type BufferedImages. I want to get average image of them. By that, I mean get average value of each pixel and make a new image out of those values. What I tried is this:

public void getWaveImage(BufferedImage input1, BufferedImage input2){
   // images are of same size that's why i'll use first one's width and height
   int width = input1.getWidth(), height = input1.getHeight();

   BufferedImage output = new BufferedImage(width, height, BufferedImage.TYPE_INT_ARGB);

   int[] rgb1 = input1.getRGB(0, 0, width, height, new int[width * height], 0, width);
   int[] rgb2 = input2.getRGB(0, 0, width, height, new int[width * height], 0, width);
   for(int i=0; i<width; i++){
      for(int j=0; j<height; j++){
         int rgbIndex = i * width + j;
         rgb1[rgbIndex] = (rgb1[rgbIndex] + rgb2[rgbIndex]) / 2;
      }
   }

   output.setRGB(0, 0, width, height, rgb1, 0, width);
   return output;
}

What am I doing wrong? Thank you in advance.

input1:

enter image description here

input2:

enter image description here

output:

enter image description here


Solution

  • You want the average of each component of the colour, average red, average green, average blue.

    Instead you are averaging the whole int.

    Color c1 = new Color(rgb1[rgbIndex]);
    Color c2 = new Color(rgb2[rgbIndex]);
    Color cA = new Color((c1.getRed()   + c2.getRed())/2,
                         (c1.getGreen() + c2.getGreen())/2,
                         (c1.getBlue()  + c2.getBlue())/2);
    rgb1[rgbIndex] = cA.getRGB();
    

    This may not be the most efficient due to creating so many objects, so a more direct approach is like so:

    public static int average(int argb1, int argb2){
       return (((argb1       & 0xFF) + (argb2       & 0xFF)) >> 1)       | //b
              (((argb1 >>  8 & 0xFF) + (argb2 >>  8 & 0xFF)) >> 1) << 8  | //g
              (((argb1 >> 16 & 0xFF) + (argb2 >> 16 & 0xFF)) >> 1) << 16 | //r
              (((argb1 >> 24 & 0xFF) + (argb2 >> 24 & 0xFF)) >> 1) << 24;  //a
    }
    

    Usage:

    rgb1[rgbIndex] = average(rgb1[rgbIndex], rgb2[rgbIndex]);