Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Java - Is there a fast way to replace all instances in a bitmap of certain colors with other colors?

Is there a fast way in Java to replace all instances in a bitmap of certain colors with other colors?

The image I am working with is a single very large 5616 x 2160 24bit non-transparent unindexed bitmap, although the pixel values of this bitmap will vary.

This is the code I am using at the moment, but it is much too slow: http://pastebin.com/UjgwgB0V

public class DisplayImage extends JFrame {

public DisplayImage(boolean resize, boolean mapCountries) throws IOException {
super("Province Map");
File mapProvinceFile = new File("map\\provinces.bmp");
BufferedImage mapProvinceImage = ImageIO.read(mapProvinceFile);

byte[] pixels = (byte[])mapProvinceImage.getRaster().getDataElements(0, 0, mapProvinceImage.getWidth(), mapProvinceImage.getHeight(), null);

if (mapCountries) {
    for (int i = 0; i < Victoria2Stats.provinceDefinitionArray.size(); i++) {
        for (int p = 0; p < pixels.length-3; p = p + 3) {
           if ((byte)Victoria2Stats.provinceDefinitionArray.get(i).rgb[0] == pixels[p]) {
               if ((byte)Victoria2Stats.provinceDefinitionArray.get(i).rgb[1] == pixels[p+1]) {
                   if ((byte)Victoria2Stats.provinceDefinitionArray.get(i).rgb[2] == pixels[p+2]) {
                       try {
                           if ((Victoria2Stats.provinceDataTable[i].ownerColor == null) && !(Victoria2Stats.provinceDataTable[i].lifeRating == 0)) {
                                pixels[p] = (byte)255;
                                pixels[p+1] = (byte)255;
                                pixels[p+2] = (byte)255;
                           } else {
                                pixels[p] = (byte)(Victoria2Stats.provinceDataTable[i].ownerColor.getRed());
                                pixels[p+1] = (byte)(Victoria2Stats.provinceDataTable[i].ownerColor.getBlue());
                                pixels[p+2] = (byte)(Victoria2Stats.provinceDataTable[i].ownerColor.getGreen());
                           }
                       } catch (NullPointerException e) {
                       // I realise this is a bad practice, but it is unrelated to the question and will be fixed later
                       }
                   }
               }
           }
      }
  }
}

BufferedImage buffer = new BufferedImage(mapProvinceImage.getWidth(), mapProvinceImage.getHeight(), mapProvinceImage.getType());
DataBuffer dataBuffer = new DataBufferByte(pixels, pixels.length);

SampleModel sampleModel = new ComponentSampleModel(DataBuffer.TYPE_BYTE, mapProvinceImage.getWidth(), mapProvinceImage.getHeight(), 3, mapProvinceImage.getWidth()*3, new int[]{0,1,2});
Raster raster = Raster.createRaster(sampleModel, dataBuffer, null);
buffer.setData(raster);

BufferedImage fixedImage = ImageUtils.verticalflip(buffer);
ImageIcon ii = new ImageIcon(fixedImage);
JScrollPane jsp = new JScrollPane(new JLabel(ii));
getContentPane().add(jsp);
setSize(800, 600);
setVisible(true);
}

}

Here is an example image: http://www.mediafire.com/?rttpk4o33b3oj74

I was thinking of somehow converting it to an indexed bitmap and then swapping the color indexes, but I couldn't figure out any way to successful assign it/recreate it with a color index with Java.

like image 806
Kalelovil Avatar asked Oct 20 '12 01:10

Kalelovil


1 Answers

An instance of java.awt.image.LookupOp with a suitable LookupTable may be faster. An example is cited here.

ColorConvertOp, illustrated here, would require a suitable ColorSpace.

ImageJ, mentioned here, can be used for batch processing.

like image 161
trashgod Avatar answered Sep 18 '22 01:09

trashgod