我将根据 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() 方法...
感谢您的帮助。
最佳答案
使用 get/setRGB()
基本上是 Java2D API 中复制像素的最简单但也可能最慢的方法。这是因为每个像素的值必须从其 native 表示形式转换为 sRGB 颜色空间中的打包 32 位 ARGB 格式(并使用 setRGB()
方法再次转换回来)。
由于您并不真正关心您的情况下的 native 像素数据是什么样子,因此可能使用 (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 中的缓存,这可能会提供更好的性能。
关于Java,根据自己的功能快速图像变形,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/44914295/