我正在进行像程序一样的图像编辑,当我想编辑大图像时,它真的开始变慢。什么是快速编辑大图像的好方法?这个例子可以调整图像的亮度,但是当我得到像3456x2304这样的大图像时,它真的很慢。
我有一个滑块,每次移动时调用此功能。
// Slider in a dialog box
private void sldBrightnessStateChanged(javax.swing.event.ChangeEvent evt) {
// Get the position of the slider
int val = sldBrightness.getValue();
// Set the text in the textbox
txtBrightness.setText("" + val);
// New Brightness class (see below)
Brightness adjustment = new Brightness();
adjustment.amount(val);
adjustment.applyFilter();
// get the result built by applyFilter();
Canvas.preview = Preview.getImage();
// Update main program
this.getParent().repaint();
}
然后是过滤器:
package pocketshop.graphics.adjustments;
import java.awt.image.BufferedImage;
import pocketshop.Canvas;
import pocketshop.graphics.Colors;
import pocketshop.graphics.Preview;
public class Brightness{
protected int amount = 0;
public void amount(int amount){
this.amount = amount;
}
public void applyFilter(){
int width = Canvas.image.getWidth();
int height = Canvas.image.getHeight();
int[] pixels = new int[width * height];
Canvas.image.getRGB(0, 0, width, height, pixels, 0, width);
for(int i = 0; i < pixels.length; i++){
int pixel = pixels[i];
//int pixel = Canvas.image.getRGB(x, y);
int red = Colors.red(pixel);
int green = Colors.green(pixel);
int blue = Colors.blue(pixel);
red += amount;
if(red > 255){
red = 255;
}else if(red < 0){
red = 0;
}
green += amount;
if(green > 255){
green = 255;
}else if(green < 0){
green = 0;
}
blue += amount;
if(blue > 255){
blue = 255;
}else if(blue < 0){
blue = 0;
}
pixels[i] = Colors.rgba(red, green, blue);
}
//BrightnessContrastDialog.preview.setRGB(0, 0, width, height, pixels, 0, width);
BufferedImage img = new BufferedImage(width, height, BufferedImage.TYPE_INT_ARGB);
img.setRGB(0, 0, width, height, pixels, 0, width);
Preview.setImage(img);
}
}
答案 0 :(得分:3)
我有一个滑块,每次移动时调用此功能。
在滑块停止移动之前,请勿调整图像。我不知道Swing,但我打赌evt
有一个测试表明它是在移动还是已经停止。
你拥有它的方式,当移动滑块时,applyFilter可能被调用100次或更多次。
答案 1 :(得分:1)
据我所知,图片是为用户提供的,以便立即反馈所做的更改,您可以做什么我们显示图片的缩减采样版本,并在滑块移动时执行亮度更改,这将很快。一旦用户对使用滑块选择的值感到满意,您就可以将更改应用于原始图像。您可以添加应用按钮或其他内容
答案 2 :(得分:0)
我建议您调查OpenCL及其Java绑定JOCL。 OpenCL是一个用于在各种不同图形卡上直接与GPU交互的库。 JOCL是OpenCL API的Java绑定库。
公平警告,这可能比你想解决的要多得多,因为你的工作水平远低于Swing。
答案 3 :(得分:0)
我不确定,但看起来您使用的是BufferedImage.TYPE_INT_ARGB类型的BufferedImage。这意味着BufferedImage正在使用一个使用DataBufferInt类型的DataBuffer的WritableRaster。在最简单的形式中,DataBufferInt只不过是一个int []的包装器。如果您可以获得Canvas正在使用的BufferedImage,那么获取它的WritableRaster并从那里获取DataBufferInt:
WritableRaster raster = Canvas.image.getRaster();
DataBufferInt dataBuffer = (DataBufferInt)raster.getDataBuffer();
int[] pixels = dataBuffer.getData();
现在你有了表示像素的int [],你可以循环它并更改组件:
for (int i = 0, len = pixels.len; i < len; ++i) {
int pixel = pixels[i];
int red = ((pixel & 0x00FF0000) >> 16) + amount;
if (red < 0) red = 0 else if (red > 255) red = 255;
int green = ((pixel & 0x0000FF00) >> 8) + amount;
if (green < 0) green = 0 else if (green > 255) green = 255;
int blue = (pixel & 0x000000FF) + amount;
if (blue < 0) blue = 0 else if (blue > 255) blue = 255;
pixels[i] = (pixels[i] & 0xFF000000) + (red << 16) + (green << 8) + blue;
}
这意味着预览所具有的BufferedImage中的像素在就地更改,而不必创建另一个int []的新像素和另一个BufferedImage。
我不确定这是否会起作用,但很多时候它会帮助Java切断中间人并且不会创建尽可能多的对象。
如果这不起作用,请查看Java Advanced Imaging。