10

タイプがTYPE_CUSTOMであるBufferedImagesをTYPE_INT_RGBに変換するメソッドがあります。私は次のコードを使用していますが、これを行うためのより高速な方法を本当に見つけたいと思います。

BufferedImage newImg = new BufferedImage(
    src.getWidth(), 
    src.getHeight(), 
    BufferedImage.TYPE_INT_RGB);

ColorConvertOp op = new ColorConvertOp(null);
op.filter(src, newImg);

それはうまく機能しますが、それはかなり遅いので、この変換を行うためのより速い方法があるかどうか疑問に思っています。

変換前のカラーモデル:

ColorModel: #pixelBits = 24 numComponents = 3 color space = java.awt.color.ICC_ColorSpace@1c92586f transparency = 1 has alpha = false isAlphaPre = false

変換後のカラーモデル:

DirectColorModel: rmask=ff0000 gmask=ff00 bmask=ff amask=0

ありがとう!


アップデート:

生のピクセルデータで作業することが最良の方法であることが判明しました。TYPE_CUSTOMは実際にはRGB変換であったため、手動で変換するのは簡単で、ColorConvertOpよりも約95%高速です。

public static BufferedImage makeCompatible(BufferedImage img) throws IOException {
    // Allocate the new image
    BufferedImage dstImage = new BufferedImage(img.getWidth(), img.getHeight(), BufferedImage.TYPE_INT_RGB);

    // Check if the ColorSpace is RGB and the TransferType is BYTE. 
    // Otherwise this fast method does not work as expected
    ColorModel cm = img.getColorModel();
    if ( cm.getColorSpace().getType() == ColorSpace.TYPE_RGB && img.getRaster().getTransferType() == DataBuffer.TYPE_BYTE ) {
        //Allocate arrays
        int len = img.getWidth()*img.getHeight();
        byte[] src = new byte[len*3];
        int[] dst = new int[len];

        // Read the src image data into the array
        img.getRaster().getDataElements(0, 0, img.getWidth(), img.getHeight(), src);

        // Convert to INT_RGB
        int j = 0;
        for ( int i=0; i<len; i++ ) {
            dst[i] = (((int)src[j++] & 0xFF) << 16) | 
                     (((int)src[j++] & 0xFF) << 8) | 
                     (((int)src[j++] & 0xFF));
        }

        // Set the dst image data
        dstImage.getRaster().setDataElements(0, 0, img.getWidth(), img.getHeight(), dst);

        return dstImage;
    }

    ColorConvertOp op = new ColorConvertOp(null);
    op.filter(img, dstImage);

    return dstImage;
}
4

6 に答える 6

7

BufferedImagesは痛々しいほど遅いです。私は解決策を得ましたが、あなたがそれを好きになるかどうかはわかりません。バッファリングされた画像を処理および変換する最も速い方法は、BufferedImage内から生データ配列を抽出することです。これを行うには、buffImg.getRaster()を呼び出し、それを特定のラスターに変換します。次に、raster.getDataStorage()を呼び出します。生データにアクセスできるようになると、BufferedImagesのすべての抽象化によって速度が低下することなく、高速な画像処理コードを記述できます。この手法では、画像形式を深く理解し、リバースエンジニアリングを行う必要があります。これは、画像処理コードをアプリケーションで十分な速度で実行できるようにする唯一の方法です。

例:

ByteInterleavedRaster srcRaster = (ByteInterleavedRaster)src.getRaster();
byte srcData[] = srcRaster.getDataStorage();

IntegerInterleavedRaster dstRaster = (IntegerInterleavedRaster)dst.getRaster();
int dstData[] = dstRaster.getDataStorage();

dstData[0] = srcData[0] << 16 | srcData[1] << 8 | srcData[2];

またはそのようなもの。そのような低レベルのラスターにアクセスしないように警告するコンパイラエラーが予想されます。この手法で問題が発生したのは、アクセス違反が発生するアプレットの内部だけです。

于 2012-01-15T04:13:40.300 に答える
3

ColorConvertOpの代わりにGraphics.drawImage()を使用したレンダリングが50倍高速であることがわかりました。drawImage()はGPUで高速化されているとしか思えません。

つまり、これは本当に遅いです。たとえば、100x200の長方形の場合は50ミリ秒です。

public void BufferdImage convert(BufferedImage input) {
   BufferedImage output= new BufferedImage(input.getWidht(), input.getHeight(), BufferedImage.TYPE_BYTE_BINARY, CUSTOM_PALETTE);

   ColorConvertOp op = new ColorConvertOp(input.getColorModel().getColorSpace(), 
                                          output.getColorModel().getColorSpace());

   op.filter(input, output);
   return output;
}

つまり、これは同じ入力に対して1ms未満を記録します

public void BufferdImage convert(BufferedImage input) {
   BufferedImage output= new BufferedImage(input.getWidht(), input.getHeight(), BufferedImage.TYPE_BYTE_BINARY, CUSTOM_PALETTE);

   Graphics graphics = output.getGraphics();
   graphics.drawImage(input, 0, 0, null);
   graphics.dispose();
   return output;
}
于 2014-08-27T08:38:09.420 に答える
0

問題は、ColorConvertOp()がピクセルごとに機能することである可能性があります(「遅い」ことが保証されています)。

Q:gc.createCompatibleImage()を使用することはできますか?

Q:元のビットマップはトゥルーカラーですか、それともカラーマップを使用していますか?

Q:他のすべてに失敗した場合、JNIインターフェースを作成することに同意しますか?独自のカスタムCコード、またはImageMagickなどの外部ライブラリのいずれかに?

于 2012-01-09T19:16:09.960 に答える
0

RenderingHintsを提供してみましたか?保証はありませんが、

ColorConvertOp op = new ColorConvertOp(new RenderingHints(
    RenderingHints.KEY_COLOR_RENDERING, 
    RenderingHints.VALUE_COLOR_RENDER_SPEED));

コードスニペットではなく、null多少スピードアップする可能性があります。

于 2012-01-05T14:58:55.357 に答える
0

JAIをインストールしている場合は、可能であればアンインストールするか、JPEGの読み込み時にcodecLibを無効にする方法を探すことができます。過去の人生で私は同様の問題を抱えていました(http://www.java.net/node/660804)そしてColorConvertOpは当時最速でした。

私が覚えているように、根本的な問題は、Java2Dが一般的にTYPE_CUSTOMイメージに対してまったく最適化されていないことです。JAIをインストールすると、TYPE_CUSTOMを返し、デフォルトの代わりに使用されるデコーダーを備えたcodecLibが付属しています。JAIリストはより多くの助けを提供することができるかもしれません、それは数年前です。

于 2012-01-12T17:14:36.913 に答える
-1

多分これを試してみてください:

Bitmap source = Bitmap.create(width, height, RGB_565);//don't remember exactly...
Canvas c = new Canvas(source);
// then 
c.draw(bitmap, 0, 0);

次に、ソースビットマップが変更されます。

後で行うことができます:

onDraw(Canvas canvas){
canvas.draw(source, rectSrs,rectDestination, op);
}

管理できる場合は、常にビットマップを再利用して、パフォーマンスを向上させることができます。また、他のキャンバス関数を使用してビットマップを描画することもできます

于 2012-01-14T20:19:51.417 に答える