How to create a solid mask from a semi-transparent Bitmap?
I want to create the image on the right, from the one on the left.
And I have the following structure:
var
Image, Mask : TBitmap;
begin
Mask := TBitmap.Create;
Image := TBitmap.Create;
Image.LoadFromFile('Yoshi.png');
// Criação da máscara aqui
end;
The result I'm looking for must turn Mask
into the image on the right to be shown in a form. Does anyone know what kind of method I should use? Mess with pixels directly? Or who knows there is another means through the canvas? Whoever has any idea, send it in.
3 answers
A possible solution:
var
Image, Mask : TBitmap;
i,j,Color : LongWord;
rowI, rowM : pRGBQuadArray;
begin
Color := $FF0000;
Image := TBitmap.Create;
Image.LoadFromFile('Yoshi.png');
Mask := TBitmap.Create;
Mask.PixelFormat := pf32bit;
Mask.Width := Image.Width;
Mask.Height := Image.Height;
FOR j := 0 TO Mask.Height-1 DO
begin
rowM := Mask.Scanline[j];
rowI := Mask.Scanline[j];
FOR i := 0 TO Mask.Width-1 DO
begin
rowM[i] := ( rowI[i] and $FF000000 ) + Color;
end;
end;
// ...use a máscara...
end;
Compensates for including a test to make sure that
Image
is alsopf32bit
before creating the mask.
Sorry for the delay in showing up, I've been very busy. It seems that we lacked a little research.
If the ideal is to work with PNG
because of transparency, then working with Bitmap
is not correct.
In fact, from Delphi 2009
with the introduction of Unicode
it became possible to work with several other types of images, including PNG
.
Here is a question in SOen about TPNGImage
: how-do-I-get-pngs-to-work-in-d2009
@ Guill, did you handle the TPNGImage type yourself in this question:How to load semi-transparent PNG through a memory stream?.
Anyway, my humble method to treat this image:
procedure TMainForm.btnCriarMascaraClick(Sender: TObject);
var
png: TPNGImage;
x,y: TColor;
begin
png := TPNGImage.Create;
try
png.Assign(imgOrig.Picture);
for x := 0 to pred(png.Width) do
for y := 0 to pred(png.Height) do
begin
if png.Pixels[x,y] <> png.TransparentColor then
begin
png.Pixels[x,y] := clLime;
end;
end;
ImgDest.Picture.Assign(png);
finally
png.Free;
end;
end;
Next, the result!
It is necessary to have the unit
pngimage
. In XE3 it is in Vcl.Imaging.pngimage
.
However, if you load the image at desing time, the IDE itself Delphi already adds a reference to it.
Try using the canvas and FillRect property.
Something like:
procedure CreateBitmapSolidColor(Width,Height:Word;Color:TColor;const FileName : TFileName);
var
bmp : TBitmap;
begin
bmp:=TBitmap.Create;
try
bmp.PixelFormat:=pf24bit;
bmp.Width:=Width;
bmp.Height:=Height;
bmp.Canvas.Brush.Color := Color;
bmp.Canvas.FillRect(Rect(0,0,Height, Width));
bmp.SaveToFile(FileName);
finally
bmp.Free;
end;
end;