语境:
我正在尝试用
java创建动画.
动画只是拍摄一张图像,使其从最暗的像素到最亮的像素.
问题:
定义像素变换的内部算法不是我的问题.
我是Java和计算的新手.我做了一些研究,并且知道有很多API可以帮助进行图像过滤/转换.
我的问题是表现,理解它.
在实现中,我创建了一个执行以下操作的方法:
>接收BufferedImage.
>获取BufferedImage的WritableRaster.
>使用setSample和getSample,逐个像素地处理和更改.
>返回BufferedImage.
之后,我使用Timer来调用该方法.
返回的BufferedImage在每次调用后通过setIcon附加到JButton.
使用500×500图像,我的机器需要大约3ms来处理每个呼叫.
对于标准1080p图像,它需要大约30ms,大约每秒33帧.
我的目标是以30fps的速度处理/动画全高清图像…而且我将无法使用我正在追踪的路径.不在大多数计算机中.
我错了什么?我怎么能让它更快?使用getDataBuffer或getPixels而不是getSample可以改善它吗?
提前致谢!抱歉我的英语.
部分结论:
感谢这里的一些帮助.我改变了概念.我没有使用getSample和setSample,而是将BufferedImage的像素ARGB信息存储到数组中.所以我处理数组并将其全部复制到另一个BufferedImage的Raster中.
处理时间从30ms(获取/设置样本)减少到1ms. (测得很差,但在同一台机器,环境和代码中).
下面是我编写实现它的一个小类.该类只能在亮度级别下过滤像素,其他像素变为透明(alpha = 0).
希望将来能够帮助您寻找相同的解决方案.要小心我在Java中的新手级别以下,因此代码可能组织不当/优化.
import java.awt.Graphics2D;
import java.awt.image.*;
/**
* @author Psyny
*/
public class ImageAppearFX {
//Essencial Data
BufferedImage imgProcessed;
int[] RAWoriginal;
int[] RAWprocessed;
WritableRaster rbgRasterProcessedW;
//Information about the image
int x,y;
int[] mapBrightness;
public ImageAppearFX(BufferedImage inputIMG) {
//Store Dimensions
x = inputIMG.getWidth();
y = inputIMG.getHeight();
//Convert the input image to INT_ARGB and store it.
this.imgProcessed = new BufferedImage(x, y, BufferedImage.TYPE_INT_ARGB);
Graphics2D canvas = this.imgProcessed.createGraphics();
canvas.drawImage(inputIMG, 0, 0, x, y, null);
canvas.dispose();
//Create an int Array of the pixels informations.
//p.s.: Notice that the image was converted to INT_ARGB
this.RAWoriginal = ((DataBufferInt) this.imgProcessed.getRaster().getDataBuffer()).getData();
//Dupplication of original pixel array. So we can make changes based on original image
this.RAWprocessed = this.RAWoriginal.clone();
//Get Raster. We will need the raster to write pixels on
rbgRasterProcessedW = imgProcessed.getRaster();
//Effect Information: Store brightness information
mapBrightness = new int[x*y];
int r,g,b,a,greaterColor;
// PRocess all pixels
for(int i=0 ; i < this.RAWoriginal.length ; i++) {
a = (this.RAWoriginal[i] >> 24) & 0xFF;
r = (this.RAWoriginal[i] >> 16) & 0xFF;
g = (this.RAWoriginal[i] >> 8) & 0xFF;
b = (this.RAWoriginal[i] ) & 0xFF;
//Search for Stronger Color
greaterColor = r;
if( b > r ) {
if( g > b ) greaterColor = g;
else greaterColor = b;
} else if ( g > r ) {
greaterColor = g;
}
this.mapBrightness[i] = greaterColor;
}
}
//Effect: Show only in a certain percent of brightness
public BufferedImage BrightnessLimit(float percent) {
// Adjust input values
percent = percent / 100;
// Pixel Variables
int hardCap = (int)(255 * percent);
int r,g,b,a,bright;
// Process all pixels
for(int i=0 ; i < this.RAWoriginal.length ; i++) {
//Get information of a pixel of the ORIGINAL image
a = (this.RAWoriginal[i] >> 24) & 0xFF;
r = (this.RAWoriginal[i] >> 16) & 0xFF;
g = (this.RAWoriginal[i] >> 8) & 0xFF;
b = (this.RAWoriginal[i] ) & 0xFF;
//Brightness information of that same pixel
bright = this.mapBrightness[i];
//
if( bright > hardCap ) {
a = 0;
}
this.RAWprocessed[i] = ((a << 24) + (r << 16) + (g << 8) + ( b )); //Write ARGB in byte format
}
//Copy the processed array into the raster of processed image
rbgRasterProcessedW.setDataElements(0, 0, x, y, RAWprocessed);
return imgProcessed;
}
//Return reference to the processed image
public BufferedImage getImage() {
return imgProcessed;
}
}