Java,根据自己的功能快速图像变形
Java, fast image warping according to own function
我将根据 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 class...
中使用 warpRect() 方法
感谢您的帮助。
使用 get/setRGB()
基本上是在 Java2D API 中复制像素的最简单但也可能是最慢的方法。这是因为每个像素的值必须从其原始表示形式转换为 sRGB 颜色 space 中的打包 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 中的数据局部性和缓存,这可能会提供更好的性能。
我将根据 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 class...
中使用 warpRect() 方法感谢您的帮助。
使用 get/setRGB()
基本上是在 Java2D API 中复制像素的最简单但也可能是最慢的方法。这是因为每个像素的值必须从其原始表示形式转换为 sRGB 颜色 space 中的打包 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 中的数据局部性和缓存,这可能会提供更好的性能。