2012-11-14 125 views
1

我正在进行像程序一样的图像编辑,并且当我想要编辑大图像时,它确实开始变慢。什么是快速编辑大图像的好方法?这个例子调整图像的亮度,它的工作原理,但是当我得到像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

你正在单独调整800万像素。这将是缓慢的。通常,通过在GPU上对图形内存中的图像执行操作,可以快速完成此类事情。 –

+0

任何建议如何我可以做到这一点? –

回答

1

据我所知,该图片是为用户提供的,以便即时反馈所做的更改,您可以做些什么来显示缩小图片的版本,并在滑块移动时执行亮度更改, 。一旦用户对使用滑块选择的值感到满意,您可以将更改应用于原始图像。你可以添加应用按钮或其他东西

3

我有一个滑块,每次移动时调用该函数。

在滑块停止移动之前不要调整图像。我不知道Swing,但我打赌有一个测试evt它说,它是否正在移动或已停止。

你的方式,applyFilter可能会被调用100次或更多的滑块移动。

+0

即使在停止并调整后仍然需要2至5秒。 –

+0

+您只能更新预览图像,大图像可以在后台线程中处理。 – Eugene

0

我建议你调查OpenCL及其Java绑定,JOCL。 OpenCL是一个用于在各种不同的图形卡上直接与GPU进行交互的库。 JOCL是OpenCL API的Java绑定库。

公平的警告,这可能比你想要解决的要多得多,因为你的工作水平要比Swing低得多。

0

我不确定,但看起来您正在使用类型为BufferedImage.TYPE_INT_ARGB的BufferedImage。这意味着BufferedImage正在使用一个使用DataBufferInt类型的DataBuffer的WritableRaster。在最简单的形式中,DataBufferInt不过是一个int []的包装。如果你能得到与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