如何优化这个缓冲图像循环?



>我使用以下循环来计算两个相同大小的图像之间的差异:

static double calculateError(BufferedImage canvas, BufferedImage ideal) {
    double error = 0.0D;
    for (int x = 0; x < Polygonizer.WIDTH; x++) {
      for (int y = 0; y < Polygonizer.HEIGHT; y++) {
        Color c1 = new Color(canvas.getRGB(x, y));
        Color c2 = new Color(ideal.getRGB(x, y));
        error += Math.abs(c1.getRed() - c2.getRed());
        error += Math.abs(c1.getGreen() - c2.getGreen());
        error += Math.abs(c1.getBlue() - c2.getBlue());
      } 
    } 
    return error;
  }

它工作得很好,但相当慢,我不知道如何让它走得更快。

我已经尝试使用ExecutorService没有好处,我可以使用一些建议。


编辑:谢谢大家。这是优化版本:

private static int APPROXIMATION = 1;
private static int[] idealData;
public static final void setIdeal(BufferedImage ideal) {
        int[] rawData = ((DataBufferInt)ideal.getRaster().getDataBuffer()).getData();
        idealData = new int[rawData.length * 3];
        int counter = 0;
        for (int i = 0; i < rawData.length * 3; i += 3) {
            idealData[i]     = (rawData[counter]       & 0xFF);
            idealData[i + 1] = (rawData[counter] >> 8  & 0xFF);
            idealData[i + 2] = (rawData[counter] >> 16 & 0xFF);
            counter++;
        }
    }
    static double calculateError(BufferedImage canvas) {
        long error = 0;
        final int[] canvasData = ((DataBufferInt)canvas.getRaster().getDataBuffer()).getData();
        int counter = 0;
        for (int i = 0; i < canvasData.length; i += APPROXIMATION) {
            error += Math.abs((canvasData[i]       & 0xFF) - (idealData[counter]));
            error += Math.abs((canvasData[i] >>  8 & 0xFF) - (idealData[counter + 1]));
            error += Math.abs((canvasData[i] >> 16 & 0xFF) - (idealData[counter + 2]));
            counter += 3 * APPROXIMATION;
        }
        return error;
    }

如果您知道BufferedImage的格式,例如,因为您使用构造函数实例化了它们,那么还有一种更快的方法。

如果BufferedImage的类型为 TYPE_3BYTE_BGR ,请执行以下操作:

byte[] canvasData = ((DataBufferByte)canvas.getRaster().getDataBuffer()).getData();
byte[] idealData  = ((DataBufferByte)ideal .getRaster().getDataBuffer()).getData();
int error = 0;
for (int i = 0; i < canvasData.length; i++) {
    error += Math.abs((canvasData[i] & 0xFF) - (idealData[i] & 0xFF));
}

如果 BufferedImage 的类型为 TYPE_INT_RGB ,请执行以下操作:

int[] canvasData = ((DataBufferInt)canvas.getRaster().getDataBuffer()).getData();
int[] idealData  = ((DataBufferInt)ideal .getRaster().getDataBuffer()).getData();
int error = 0;
for (int i = 0; i < canvasData.length; i++) {
    error += Math.abs((canvasData[i]       & 0xFF) - (idealData[i]       & 0xFF));
    error += Math.abs((canvasData[i] >>  8 & 0xFF) - (idealData[i] >>  8 & 0xFF));
    error += Math.abs((canvasData[i] >> 16 & 0xFF) - (idealData[i] >> 16 & 0xFF));
}

(免责声明:未经测试的代码,但我经常做一些事情,我很有信心(

你为每个点创建两个Color实例,这是相当多的。有一种更快的方法可以从 int 中提取 RGB(查看 Color 的来源(。

更重要的是,你一个接一个地提取点,这通常非常慢(因为它们在BufferedImage中可能以不同的方式组织(。调用一个方法,一次将更多提取到int[]中。

AFAIK有一种方法可以让图像计算结果,这可能仍然更快。

我已经尝试使用ExecutorService没有好处,我真的可以使用一些建议。

这也应该有所帮助,但仅限于您拥有的内核数量。但是,使用平行流通常要简单得多。但这是一个不同的故事(问题(。

最新更新