このアーカイブは同期化されません。 mixi の日記が更新されても、このアーカイブには反映されません。
RFB の画素形式は、初期化時にサーバが既定値を決め、
主処理においてはクライアントが自由に変更できる。
それぞれ ServerInit と SetPixelFormat メッセージだ。
サーバ側では常に自然な画素形式を使い、
通信時に画像形式を変換すると言う手もあるが、
それには多くのオーバヘッドが掛かると思われる。
そこで、クライアントの指定した画素形式に応じて、
サーバは常に最適な画面バッファを持つことにする。
また、今回は実装の手間を考え TrueColor だけに対応しよう。
Java で動的にカラーテーブルを扱うには手間がかかる上に、
VNC クライアントの大半がカラーテーブルを扱わないからだ。
まずは、PIXEL_FORMAT 構造(PixelFormat クラス)を、
ColorModel に変換する必要がある。
getRedMax() は、赤の取り得る最大値を表し、
getRedShift() は、ピクセルの赤を示すビット位置を表す。
そのため、getRedMax() で得られた最大値を、
getRedShift() だけ 左シフトすれば、
赤要素のビットマスクが計算できることになる。
// PixelFormat format = ...;
if (!format.isTrueColor())
throw new IOException("Can't handle indexed pixel format.");
int redMask = format.getRedMax() << format.getRedShift();
int greenMask = format.getGreenMax() << format.getGreenShift();
int blueMask = format.getBlueMax() << format.getBlueShift();
次に、ピクセルが占めるサイズだが、PixelFormat には、
getBitPerPixel() と getDepth() の 2 つの値がある。
RFB のピクセルサイズと Java の転送型のサイズを一致させるためには、
getBitPerPixel() で得られる 8, 16, 32 を使う必要がある。
ColorModel model = new DirectColorModel(
format.getBitPerPixel(), redMask, greenMask, blueMask);
ColorModel ができたら、それを元にして WritableRaster を生成する事ができる。
WritableRaster raster = model.createCompatibleWritableRaster(
width, height);
次に描画のことを考えなければならない。
WritableRaster は書き込み可能な画面データを提供してくれるが、
その扱いは少し面倒で、単一の点もしくは矩形領域に、
ピクセル値(RGB パック済み)を読み書きする必要がある。
Java では、java.awt.Graphics クラスを基本とする、
描画に関する強力なクラス群がそろっている。
Graphics のメソッドを使って描画できるようにすれば、
サーバの画面を描画するのには非常に便利となるのだ。
この橋渡しをしてくれるのが、java.awt.image.BufferedImage だ。
BufferedImage クラスは、WritableRaster に対して、
画像として操作可能な能力を付与する機能を持つ。
BufferedImage は java.awt.Image を実装しているので、
Image の一種として色々な場所で利用可能だ。
また、BufferedImage の createGraphics() メソッドを使うと、
WritableRaster に描画するための Graphics を作成可能である。
この Graphics を使って描画操作を行うことで、
WritableRaster に高度な描画ロジックを適用する事が可能となる。
BufferedImage canvas = new BufferedImage(model, raster, false, null);
……ううむ。グラフィックス関係はえらいややこしいな。