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);
    }
}
4

4 に答える 4

3

移動するたびにこの関数を呼び出すスライダーがあります。

スライダーの動きが止まるまで画像を調整しないでください。Swing はわかりませんが、evt動いているか停止しているかを示すテストがあるに違いありません。

あなたが持っている方法では、applyFilter は、スライダーが移動すると 100 回以上呼び出される場合があります。

于 2012-11-14T23:52:25.480 に答える
1

行われた変更の即時フィードバックを提供するために画像がユーザーに表示されることを理解しているので、ダウンサンプリングされたバージョンの画像を表示し、スライダーが移動している間に明るさの変更を実行できます。これは高速です。ユーザーがスライダーを使用して選択した値に満足したら、元の画像に変更を適用できます。適用ボタンなどを追加できます

于 2012-11-15T06:48:33.553 に答える
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;
}

これは、新しいピクセルの別の int[] と別の BufferedImage を作成する必要なく、Preview が持っている BufferedImage のピクセルがその場で変更されることを意味します。

これが機能するかどうかはわかりませんが、多くの場合、Java で仲介者を排除し、多くのオブジェクトを作成しないようにすることが役立ちます。

これでうまくいかない場合は、Java Advanced Imagingを調べてください。

于 2012-11-15T04:32:21.740 に答える
0

OpenCLとその Java バインディングであるJOCLを調査することをお勧めします。OpenCL は、さまざまなグラフィック カード上の GPU と直接対話するためのライブラリです。JOCL は、OpenCL API 用の Java バインディング ライブラリです。

Swing よりもはるかに低いレベルで作業することになるため、注意が必要です。

于 2012-11-15T02:53:42.513 に答える