GDI(GDI +ではない)を使用して32ビットビットマップをグレースケールに変換する方法の簡単な解決策を探しています。ビットマップのパレットなどを変更するなどの可能性はありますか?
もちろん、Delphiにはこのような例がたくさんありますが、行を繰り返すことなくこれを実行するWinAPI関数を探しています。
これを行う単一のGDI関数は見つかりませんでした。Davidがコメントで述べたように、最も簡単な方法は、各行をスキャンしてピクセルの色を計算することです。あなたが探しているのはおそらくluminance
公式です。
この式にはいくつかのバリエーションがあり、次の例では、によって推奨されているものを使用しました。セクション2.5.1ITU
を参照してください。this document
どこかで見つけたように、この式は、たとえば有名なAdobePhotoshopでも使用されています。次のコード例は、入力として24ビットピクセル形式のビットマップのみをサポートおよび想定しています。
procedure BitmapGrayscale(ABitmap: TBitmap);
type
PPixelRec = ^TPixelRec;
TPixelRec = packed record
B: Byte;
G: Byte;
R: Byte;
end;
var
X: Integer;
Y: Integer;
Gray: Byte;
Pixel: PPixelRec;
begin
for Y := 0 to ABitmap.Height - 1 do
begin
Pixel := ABitmap.ScanLine[Y];
for X := 0 to ABitmap.Width - 1 do
begin
Gray := Round((0.299 * Pixel.R) + (0.587 * Pixel.G) + (0.114 * Pixel.B));
Pixel.R := Gray;
Pixel.G := Gray;
Pixel.B := Gray;
Inc(Pixel);
end;
end;
end;
パレット化されたDIBセクションを作成できます。ピクセルあたり8ビット、256色で、パレットを灰色の色調に初期化します{0、0、0}、{1、1、1}、... {255、255、255}。
このビットマップへの単一のGDIBitBlt
は、元の画像をグレー表示します。これがコードスニペットです(C ++、ATL、WTLの場合-しかし、あなたはその考えを理解する必要があります)。
CWindowDC DesktopDc(NULL);
CDC BitmapDc;
ATLVERIFY(BitmapDc.CreateCompatibleDC(DesktopDc));
CBitmap Bitmap;
CTempBuffer<BITMAPINFO> pBitmapInfo;
const SIZE_T nBitmapInfoSize = sizeof (BITMAPINFO) + 256 * sizeof (RGBQUAD);
pBitmapInfo.AllocateBytes(nBitmapInfoSize);
ZeroMemory(pBitmapInfo, nBitmapInfoSize);
pBitmapInfo->bmiHeader.biSize = sizeof pBitmapInfo->bmiHeader;
pBitmapInfo->bmiHeader.biWidth = 320;
pBitmapInfo->bmiHeader.biHeight = 240;
pBitmapInfo->bmiHeader.biPlanes = 1;
pBitmapInfo->bmiHeader.biBitCount = 8;
pBitmapInfo->bmiHeader.biCompression = BI_RGB;
pBitmapInfo->bmiHeader.biSizeImage = 240 * 320;
pBitmapInfo->bmiHeader.biClrUsed = 256;
pBitmapInfo->bmiHeader.biClrImportant = 256;
for(SIZE_T nIndex = 0; nIndex < 256; nIndex++)
{
pBitmapInfo->bmiColors[nIndex].rgbRed = (BYTE) nIndex;
pBitmapInfo->bmiColors[nIndex].rgbGreen = (BYTE) nIndex;
pBitmapInfo->bmiColors[nIndex].rgbBlue = (BYTE) nIndex;
}
Bitmap.Attach(CreateDIBSection(DesktopDc, pBitmapInfo, 0, DIB_RGB_COLORS, NULL, 0));
ATLVERIFY(Bitmap);
BitmapDc.SelectBitmap(Bitmap);
////////////////////////////////////////////////
// This is what greys it out:
ATLVERIFY(BitBlt(BitmapDc, 0, 0, 320, 240, DesktopDc, 0, 0, SRCCOPY));
////////////////////////////////////////////////
ATLVERIFY(BitBlt(DesktopDc, 0, 240, 320, 240, BitmapDc, 0, 0, SRCCOPY));