2007 年 2 月 16 日 9 時 59 分

RFBCanvas #4


このアーカイブは同期化されません。 mixi の日記が更新されても、このアーカイブには反映されません。


昨日の続き。encodeRawPixels の実装を行う。

RAW 符号化は、ピクセルの画素表現をそのまま使う。
1 画素のサイズは、PixelFormat#getBitPerPixel、
画素のバイト表現は PixelFormat#isBigEndian、
そして、画素は左から右、上から下の順で並べられる。

========== RFBCanvas#encodeRawPixels ==========

    private byte[] encodeRawPixels(Rectangle rect) throws IOException {

        // まずは画素の配列を取得
        WritableRaster raster = displayBuffer.getRaster();
        Object data = raster.getDataElements(rect.x, rect.y,
                rect.width, rect.height, null);

        PixelFormat format = context.getPixelFormat();
       
        // 画素あたり 1 バイトならバイト配列なのでそのまま返す
        if (format.getBitPerPixel() == 8) {
            return (byte[])data;
        }
       
        // それ以外の場合、エンディアンに応じて変換が必要
       
        int count = rect.width * rect.height;
        int bytes = count * (format.getBitPerPixel() / 8);
       
        ByteBuffer buffer = ByteBuffer.allocate(bytes);
        if (format.isBigEndian()) {
            buffer.order(ByteOrder.BIG_ENDIAN);
        } else {
            buffer.order(ByteOrder.LITTLE_ENDIAN);
        }
       
        switch (format.getBitPerPixel()) {

        case 16:
            {
                short[] pixels = (short[])data;
                for (int i = 0; i < count; ++i) {
                    buffer.putShort(pixels[i]);
                }
            }
            break;
   
        case 32:
            {
                int[] pixels = (int[])data;
                for (int i = 0; i < count; ++i) {
                    buffer.putInt(pixels[i]);
                }
            }
            break;
           
        default:
            throw new IOException();

        }

        return buffer.array();
    }

========== end of RFBCanvas#encodeRawPixels ==========

画面データは BufferedImage に格納されており、
BufferedImage は内部的に WritableRaster を持つ。
その WritableRaster の getDataElements を使うと、
画像の一部領域のデータを取得することができる。

これは非常に便利なメソッドで、指定範囲の画素データを、
SampleModel#getTransferType(転送型)が示す、
プリミティブ形の配列として取得することができる。

転送型に対応するプリミティブは決まっており、
8 ビットの場合は byte、16 ビットの場合は short、
32 ビットの場合は int である。

RFBCanvas の場合、転送型は間接的に、
PixelFormat#getBitPerPixel によって決まる。

後は、RAW 符号化を行うためには、
転送型で表現された配列を、
byte 配列に変換する必要がある。

PixelFormat#getBitPerPixel が 8 ならば、
転送型 = byte なので、そのまま使えるのだが、
16 や 32 であれば、そのエンディアンを考慮して、
byte 配列に格納しなおす必要がある。

そういった変換は、java.nio パッケージにある、
ByteBuffer クラスを使えば簡単に実現できるのである。



Copyright (c) 1994-2007 Project Loafer. All rights reserved.