Java - 有没有一种快速的方法来替换某些颜色的位图中的所有实例与其他颜色?

Kal*_*vil 5 java swing colors javax.imageio

在Java中是否有一种快速的方法来替换某些颜色的位图中的所有实例与其他颜色?

我正在使用的图像是一个非常大的5616 x 2160 24位非透明无索引位图,尽管此位图的像素值会有所不同.

这是我目前正在使用的代码,但它太慢了: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);
}

}
Run Code Online (Sandbox Code Playgroud)

以下是一个示例图片:http://www.mediafire.com/?rttpk4o33b3oj74

我想以某种方式将其转换为索引位图,然后交换颜色索引,但我无法找到任何方法成功分配/使用Java的颜色索引重新创建它.

Ste*_*n C 2

普通的留言:

  • 您转换为索引位图的想法不太可能有帮助,因为(我认为您会发现)转换成本超过了节省的成本。

  • 使用外部应用程序或本机代码库可以更好地解决问题。

我认为还有微观优化的余地。例如:

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) {
      int len = Victoria2Stats.provinceDefinitionArray.size();
      for (int i = 0; i < len; i++) {
        int[] rgb = Victoria2Stats.provinceDefinitionArray.get(i);
        ProvinceDataTable pdt = Victoria2Stats.provinceDataTable[i];
        for (int p = 0; p < pixels.length-3; p = p + 3) {
          if ((byte) rgb[0] == pixels[p] &&
              (byte) rgb[1] == pixels[p+1] &&
              (byte) rgb[2] == pixels[p+2]) {
            if (pdt.ownerColor == null && pdt.lifeRating != 0) {  // HERE
              pixels[p] = (byte)255;
              pixels[p+1] = (byte)255;
              pixels[p+2] = (byte)255;
            } else {
              pixels[p] = (byte)(pdt.ownerColor.getRed());
              pixels[p+1] = (byte)(pdt.ownerColor.getBlue());
              pixels[p+2] = (byte)(pdt.ownerColor.getGreen());
            }
          }
        }
      }
    }

    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);
  }
}
Run Code Online (Sandbox Code Playgroud)

IMO,可读性的提高使得即使它不会提高性能也是值得的。修复缩进也有帮助!

顺便说一句,一旦我删除了所有的废话,您的 NPE 问题的可能根源就变得更加明显了。看看我标记为“这里”的那一行。请注意,条件是仅当 is ownerColorAND nullthelifeRating非零时才采用“then”分支。如果ownerColoris nullAND thelifeRating为零,您将采用“else”分支,并且 NPE 是不可避免的。