という流れで処理してみました。バッファには、先頭2ダブルワード(8バイト)にイメージの幅と高さを記録し、その後にイメージのピクセル列を32ビットDIBピクセル列形式で記録します。バッファの大きさは、イメージの幅×高さ×4+8バイトなので、バッファの確保は p:=PInteger(GlobalAlloc(GPTR,bmp.width*bmp.height*4+8)); となります。後はこのバッファの先頭にイメージの大きさを書き込み、続いてTBitmapオブジェクトbmpのピクセル列をscanLineメソッドで取得して書き込んでいくだけですね。
pp:=p;
pp^:=jpg.width;
inc(pp,1);
pp^:=jpg.Height;
inc(pp,1);
for i:=0 to bmp.height-1 do
begin
CopyMemory(pp,bmp.scanLine[(bmp.height-1)-i],bmp.width*4);
inc(pp,bmp.width);
end;
DLLのソース全体は、以下のようになります。
library jload;
uses
Windows,Classes,Graphics,jpeg;
function load(fn:PChar):PInteger;export;stdcall;
var
jpg:TJpegImage;
bmp:TBitmap;
p,pp:PInteger;
i:Integer;
begin
jpg:=TJpegImage.Create;
jpg.PixelFormat:=jf24bit;
jpg.LoadFromFile(fn);
bmp:=TBitmap.Create;
bmp.HandleType:=bmDIB;
bmp.PixelFormat:=pf32bit;
bmp.Width:=jpg.Width;
bmp.Height:=jpg.Height;
bmp.Canvas.Draw(0,0,jpg);
p:=PInteger(GlobalAlloc(GPTR,bmp.width*bmp.height*4+8));
pp:=p;
pp^:=jpg.width;
inc(pp,1);
pp^:=jpg.Height;
inc(pp,1);
for i:=0 to bmp.height-1 do
begin
CopyMemory(pp,bmp.scanLine[(bmp.height-1)-i],bmp.width*4);
inc(pp,bmp.width);
end;
jpg.free;
bmp.free;
load:=p;
end;
exports
load name 'load';
begin
end.
DLLの作成は、DLLの新規プロジェクトを作成してこのプログラムソースを作成するだけです。 Jpegの読み込みでは、このDLL内のload()をVC++のプログラムから呼び出してみましょう。今回は、Jpegファイルをドロップするとそのファイルをloadに渡して32ビットDIBを作成し、そのDIBを表示するプログラムを作ってみました。 プログラムでは、まずload()用のポインタを宣言します。 typedef LPDWORD (CALLBACK* pLoad)(LPCTSTR); pLoad pload; 次に、プログラムの最初でDLL(jload.dll)を読み込んで関数のポインタを取得。
hDll=LoadLibrary("jload");
pload=(pLoad)GetProcAddress(hDll,"load");
これでjload.dll内のload()を関数ポインタploadを介して呼び出せるようになったので、この関数を使ってJpegファイルから32ビットDIBを作成する関数readJpeg()を定義します。
BOOL readJpeg(LPCTSTR fn) { /* Jpegファイル読み込み */
LPDWORD lpP;
/* DLL内のload関数呼び出し */
lpP=pload(fn);
/* ビットマップの大きさ保存 */
dwWidth=*lpP;
dwHeight=*(lpP+1);
/* DIB用メモリ確保・ポインタ設定 */
lpDIB=(LPBYTE)GlobalAlloc(GPTR,sizeof(BITMAPINFO)+dwWidth*dwHeight*4);
lpInfo=(LPBITMAPINFO)lpDIB;
lpPixels=lpDIB+sizeof(BITMAPINFO);
/* DIB用BITMAPINFOHEADER設定 */
lpInfo->bmiHeader.biSize=sizeof(BITMAPINFOHEADER);
lpInfo->bmiHeader.biWidth=dwWidth;
lpInfo->bmiHeader.biHeight=dwHeight;
lpInfo->bmiHeader.biPlanes=1;
lpInfo->bmiHeader.biBitCount=32;
lpInfo->bmiHeader.biCompression=BI_RGB;
/* DLL内で読み込んだピクセル列をコピー */
CopyMemory(lpPixels,lpP+2,dwWidth*dwHeight*4);
/* DLLから取得したピクセル列バッファを解放 */
GlobalFree(lpP);
return TRUE;
}
これで、JpegファイルからDIBを作れるようになったので、後はファイルがドロップされたらこの関数を呼び出すだけですね。 プログラム実行ファイル(またはプロジェクト)と同じディレクトリにjload.dllを置いて実行したら、ウインドウにJpegファイルをドロップしてみてください。ただし、エラーチェックはしていないのでJpegファイル以外はドロップしないでください。 今回は読み込みだけでしたが、同じようにしてビットマップの大きさとピクセル列のバッファを渡すとそのビットマップをJpegファイルに保存する関数も作れるでしょう。 |