4

を32 ビット RGBA から 24 ビット RGBに変換しようとしていましたBufferedImageこの回答byte[]によると、画像からを取得する最速の方法は次のとおりです。byte[]

byte[] pixels = ((DataBufferByte) bufferedImage.getRaster().getDataBuffer()).getData();

したがって、順序が RGBA であると仮定してすべてのバイトを反復処理し、4 バイトごとに出力 byte[] に最初の 3 を書き込みます (つまり、アルファ値を無視します)。

これは、Eclipse から実行すると正常に機能し、バイトは正しく変換されます。ただし、コマンド ラインから同じプログラムを実行すると、同じバイトが逆のバイト順で返されます。

テストに使用するテスト イメージは 5x5 の黒のイメージで、左上隅だけが異なり、RGBA カラーを持っています[aa cc ee ff]テスト画像 5x5

便利なズームイン バージョン:

拡大テスト画像

私のフォルダ構造は次のとおりです。

- src/  
  - test.png
  - test/
      - TestBufferedImage.java  

SSCCE は次のとおりです。

package test;

import java.awt.image.BufferedImage;
import java.awt.image.DataBufferByte;
import java.io.IOException;
import java.io.InputStream;

import javax.imageio.ImageIO;

public class TestBufferedImage {

  private static void log(String s) {
    System.out.println(s);
  }

  private static String toByteString(byte b) {
    // Perform a bitwise AND for convenience while printing. 
    // Otherwise Integer.toHexString() interprets values as integers and a negative byte 0xFF will be printed as "ffffffff"
    return Integer.toHexString(b & 0xFF);
  }

  /**
   * @param args
   * @throws IOException 
   */
  public static void main(String[] args) throws IOException {

    InputStream stream = TestBufferedImage.class.getClassLoader().getResourceAsStream("test.png");
    BufferedImage image = ImageIO.read(stream);
    stream.close();
    log("Image loaded succesfully, width=" + image.getWidth() + " height=" + image.getHeight());

    log("Converting from 32-bit to 24-bit...");
    DataBufferByte buffer = (DataBufferByte)image.getRaster().getDataBuffer(); 
    byte[] input = buffer.getData();
    byte[] output = convertTo24Bit(input);
    log("Converted total of " + input.length + " bytes to " + output.length + " bytes");
  }

  private static byte[] convertTo24Bit(byte[] input) {
    int dataLength = input.length;
    byte[] convertedData = new byte[ dataLength * 3 / 4 ];

    for (int i = 0, j = 0; i < dataLength; i+=4, j+=3) {
      convertIntByteToByte(input, i, convertedData, j);
    }
    return convertedData;
  }

  private static void convertIntByteToByte(byte[] src, int srcIndex, byte[] out, int outIndex) {
    byte r = src[srcIndex];
    byte g = src[srcIndex+1];
    byte b = src[srcIndex+2];
    byte a = src[srcIndex+3];

    out[outIndex] = r;
    out[outIndex+1] = g; 
    out[outIndex+2] = b; 

    log("i=" + srcIndex 
        + " Converting [" + toByteString(r) + ", " + toByteString(g) 
        + ", " + toByteString(b) + ", " + toByteString(a) + "] --> ["
        + toByteString(out[outIndex]) + ", " + toByteString(out[outIndex+1])
        + ", " + toByteString(out[outIndex+2]) + "]"
        );
  }

}

Eclipse から実行した場合の出力 (バージョン: Juno Service Release 2 ビルド ID: 20130225-0426):

Image loaded succesfully, width=5 height=5
Converting from 32-bit to 24-bit...
i=0 Converting [aa, cc, ee, ff] --> [aa, cc, ee]   // <-- Bytes have the correct order
i=4 Converting [0, 0, 0, ff] --> [0, 0, 0]
i=8 Converting [0, 0, 0, ff] --> [0, 0, 0]
.....
i=96 Converting [0, 0, 0, ff] --> [0, 0, 0]
Converted total of 100 bytes to 75 bytes

コマンド ライン (Windows Vista) から実行した場合の出力java test.TestBufferedImage:

Image loaded succesfully, width=5 height=5
Converting from 32-bit to 24-bit...
i=0 Converting [ff, ee, cc, aa] --> [ff, ee, cc]    // <-- Bytes are returned with a different byte order!
i=4 Converting [ff, 0, 0, 0] --> [ff, 0, 0]
i=8 Converting [ff, 0, 0, 0] --> [ff, 0, 0]
.....
i=96 Converting [ff, 0, 0, 0] --> [ff, 0, 0]
Converted total of 100 bytes to 75 bytes

それで、誰かが同様の問題に遭遇したことがありますか、そして/または実際に何が起こっているのか説明できますか? Eclipse内から実行するとバイトオーダーが異なるのはなぜですか?

4

1 に答える 1