Странно, что на мой вопрос никто не дал даже самый глупый ответ (что бывает в этом форуме чаще чем хотелось бы) :)
Для тех кому интересно - мне таки удалось добиться нужного результата. Это оказалось вовсе не интуитиво...
Что бы нарисовать Bitmap с нужной степенью прозрачности необходимо:
1) создать объект GpImageAttributes
2) заполнить странным способом массив TColorMatrix
3) вызвать функцию GdipSetImageAttributesColorMatrix указав ей объект GpImageAttributes и массив TColorMatrix
4) и наконец вызвать страшную функцию GdipDrawImageRectRectI требующую кучу аргументов, большинство которых для данной задачи либо дублируется либо и вовсе пустые.
Вот собственно функия-оболочка для указанных действий:
procedure DrawAlphaBitmap2(gpaGraphics: GpGraphics; Bitmap: TBitmap; X, Y: Integer; BitmapAlpha: Byte);
var
gpaBitmap: GpBitmap;
gpaImgAttr: GpImageAttributes;
gpaColorMatrix: TColorMatrix;
begin
gpaBitmap:=nil;
GdipCreateBitmapFromHBITMAP(Bitmap.Handle, Bitmap.Palette, gpaBitmap);
try
gpaImgAttr:=nil;
GdipCreateImageAttributes(gpaImgAttr);
try
FillChar(gpaColorMatrix, SizeOf(gpaColorMatrix), 0);
gpaColorMatrix[0, 0]:=1;
gpaColorMatrix[1, 1]:=1;
gpaColorMatrix[2, 2]:=1;
gpaColorMatrix[3, 3]:=BitmapAlpha/255;
gpaColorMatrix[4, 4]:=1;
GdipSetImageAttributesColorMatrix(
gpaImgAttr,
ColorAdjustTypeDefault,
True,
@gpaColorMatrix,
nil,
ColorMatrixFlagsDefault);
GdipDrawImageRectRectI(
gpaGraphics,
gpaBitmap,
X,
Y,
Bitmap.Width,
Bitmap.Height,
0,
0,
Bitmap.Width,
Bitmap.Height,
UnitPixel,
gpaImgAttr,
nil,
nil);
finally
GdipDisposeImageAttributes(gpaImgAttr);
end;
finally
GdipDisposeImage(gpaBitmap);
end;
end;
Эта функция принимает параметры:
gpaGraphics - объект Graphics на котором следует рисовать
Bitmap - Bitmap который и нужно нарисовать
X, Y - координаты верхнего левого угла
BitmapAlpha - степень прозрачности от 0 до 255 - собственно то, ради чего всё и затевалось... :)
Пример использования:
procedure TForm1.Button1Click(Sender: TObject);
var
bmp: TBitmap;
gpaGraphics: GpGraphics;
begin
Canvas.Brush.Color:=clWhite;
Canvas.FillRect(Rect(0, 0, 400, 400));
bmp:=TBitmap.Create;
try
GdipCreateFromHDC(Canvas.Handle, gpaGraphics);
try
bmp.LoadFromFile('C:\WINDOWS\Пузыри.bmp');
DrawAlphaBitmap2(gpaGraphics, bmp, 30, 40, 50);
bmp.LoadFromFile('C:\WINDOWS\Паркет.bmp');
DrawAlphaBitmap2(gpaGraphics, bmp, 10, 10, 150);
finally
GdipDeleteGraphics(gpaGraphics);
end;
finally
bmp.Free;
end;
end;
Ещё в uses нужно добавить GDIPAPI (этот модуль можно скачать в интернете) и ещё неплохо добавить GDIPOBJ, ну или же вручную проинициализировать GDI+
И ещё приведу процедуру, которую я наваял ещё до того как написал в форум этот вопрос и от которой я пытался избавиться, так как она работает через ScanLine, да и вобще кривоватая.
Она вполне рабочая, но как впоследствии оказалось всё же медленнее, чем мой второй вариант который я привёл выше. Скорее всего это изза того, что GpBitmap приходится создавать дважды: сначала функцией GdipCreateBitmapFromHBITMAP по образу TBitmap, а потом функцией GdipCloneBitmapArea, чтобы добавить к GpBitmap альфа-канал. Да и принцип получения ScanLine другой: в стандартном GDI просто даётся указатель на область памяти где хранится сам Bitmap, а в GDI+ создаётся временный буфер (функцией GdipBitmapLockBits), в него копируется (если указан флаг ImageLockModeRead) заданная область в заданном пиксельном формате, а по завершению (функцией GdipBitmapUnlockBits) содержимое этого буфера вновь копируется (если указан флаг ImageLockModeWrite) в GpBitmap...
procedure DrawAlphaBitmap0(gpaGraphics: GpGraphics; Bitmap: TBitmap; X, Y: Integer; BitmapAlpha: Byte);
type
PGPColorRec = ^TGPColorRec;
TGPColorRec = packed record
b, g, r, a: Byte;
end;
var
gpaBitmap, gpaBitmap2: GpBitmap;
gpaRect: TGPRect;
gpaPColor: PGPColorRec;
gpaBitmapData: TBitmapData;
xx, yy: Integer;
begin
gpaBitmap:=nil;
GdipCreateBitmapFromHBITMAP(Bitmap.Handle, Bitmap.Palette, gpaBitmap);
try
GdipCloneBitmapArea(0, 0, Bitmap.Width, Bitmap.Height, PixelFormat32bppARGB, gpaBitmap, gpaBitmap2);
try
gpaRect:=MakeRect(0, 0, Bitmap.Width, Bitmap.Height);
GdipBitmapLockBits(
gpaBitmap2,
@gpaRect,
ImageLockModeRead or ImageLockModeWrite,
PixelFormat32bppARGB,
@gpaBitmapData);
try
gpaPColor:=gpaBitmapData.Scan0;
for yy := 0 to gpaBitmapData.Height-1 do
begin
gpaPColor:=Pointer(Integer(gpaBitmapData.Scan0)+yy*gpaBitmapData.Stride);
for xx := 1 to gpaBitmapData.Width do
begin
gpaPColor.a:=BitmapAlpha;
Inc(gpaPColor);
end;
end;
finally
GdipBitmapUnlockBits(gpaBitmap2, @gpaBitmapData);
end;
GdipDrawImage(gpaGraphics, gpaBitmap2, X, Y);
finally
GdipDisposeImage(gpaBitmap2);
end;
finally
GdipDisposeImage(gpaBitmap);
end;
end;