1

我将根据 Java 中的用户定义函数来扭曲图像。一般来说,图像比较大(JPEG,30-50 MB)。

最初,图像被加载:

BufferedImage img = ImageIO.read("image.jpg");

假设 [X,Y] 为图像的重采样像素坐标,其中 [x,y] 表示其像素坐标。

坐标函数(一个简单的例子)写成如下:

X = y * cos(x);
Y = x;

我的想法是使用逐像素转换:

//Get size of the raster
int width = img.getWidth(), height = img.getHeight();
int proj_width =  (int)(width * Math.cos(height*Math.pi/180)),proj_height = height;

 //Create output image
 BufferedImage img2 = new BufferedImage(proj_width+1, proj_height+1, img.getType());

 //Reproject raster
 for (int i = 0; i < img.getWidth(); i++) {
      for (int j = 0; j < img.getHeight(); j++) {

            //Color of the pixel
            int col = img.getRGB(i, j);

            //Its new coordinates
            int X = (int)(i * Math.cos(j*Math.pi/180));
            int Y = j;

            //Set X,Y,col to the new raster
            img2.setRGB(X,Y,col);                 
       } 
  }

有没有更快的方法来实现这个操作而不需要任何额外的库?

例如使用 Warp 类中的 warpRect() 方法...

谢谢你的帮助。

4

1 回答 1

2

使用get/setRGB()基本上是在 Java2D API 中复制像素的最简单但也可能最慢的方法。这是因为必须将每个像素的值从其本机表示转换为 sRGB 颜色空间中的压缩 32 位 ARGB 格式(然后再返回该setRGB()方法)。

由于您并不真正关心本机像素数据在您的情况下是什么样子,因此使用(Writable)Raster及其get/setDataElements()方法可能会更快(快多少取决于BufferedImage类型):

// Reproject raster
Object pixel = null;

Raster from = img.getRaster();
WritableRaster to = img2.getRaster(); // Assuming img2.getType() == img.getType() always

for (int y = 0; y < img.getHeight(); y++) {
    for (int x = 0; x < img.getWidth(); x++) {
        // Color of the pixel
        pixel = from.getDataElements(x, y, pixel);

        // Its new coordinates
        int X = (int) (x * Math.cos(y * Math.pi/180));
        int Y = y;

        // Set X,Y,pixel to the new raster
        to.setDataElements(X, Y, pixel);                 
   } 

}

请注意,我还更改了嵌套循环以在内部循环中迭代宽度。由于数据局部性和普通 CPU 中的缓存,这可能会提供更好的性能。

于 2017-08-14T10:54:29.427 回答