Firemonkey bitmap scaling without Aliasing on Android
With Delphi , to the Seattle version , when you scale a bitmap image to enlarge using the command “Canvas.DrawBitmap(OiginalBitmap, RectF(0, 0, OiginalBitmap.Width, OiginalBitmap.Height), RectF(0, 0, Width, Height), 1, False);” the interpolation cant be disabled.
A way to eliminate the problem is to manually scale the bitmap directly creating an image pixel by pixel . To do this you need to get canvas.scale and create an image with the native resolution of the Android device .
This helped me for example to generate qrcode on the display of my Android devices that were as sharp as possible, i use the DelphiZXingQRCode to generate the qrcode in the original format.
To draw the qrcode generated from the library I have implemented the following procedure:
procedure TForm2.genQrCodeToImage(DestImage: TImage; ContentText: String);
var
Local_Row: Integer;
Local_Column: Integer;
vPixelB: Integer;
vPixelW: Integer;
QRCode: TDelphiZXingQRCode;
QRCodeBitmap: TBitmapData;
Row: Integer;
bmp: FMX.Graphics.TBitmap;
Column: Integer;
ms: TMemoryStream;
bmp2: FMX.Graphics.TBitmap;
DestW: Int64;
DestH: Int64;
pixW: Int64;
pixH: Int64;
j: Integer;
currentRow: Int64;
k: Int64;
currentCol: Int64;
begin
{ TODO :
Inserire nell’url http due parametri :
1) computer name
2) servizio di remoting }
ms := nil;
bmp := nil;
bmp2 := nil;
DestW := round(DestImage.Width * Canvas.Scale);
DestH := round(DestImage.Height * Canvas.Scale);
DestImage.Bitmap.SetSize(DestW, DestH);
DestImage.scale.X := 1;
DestImage.scale.Y := 1;
vPixelB := TAlphaColorRec.Black;
// determine colour to use
vPixelW := TAlphaColorRec.White;
// determine colour to use
QRCode := TDelphiZXingQRCode.Create;
try
QRCode.Data := ContentText;
QRCode.Encoding := TQRCodeEncoding(0);
QRCode.QuietZone := 4;
bmp := FMX.Graphics.TBitmap.Create;
bmp.SetSize(DestW,DestH);
pixW := Trunc(DestW / QRCode.Columns);
pixH := Trunc(DestH / QRCode.Rows);
if bmp.Map(TMapAccess.maReadWrite, QRCodeBitmap) then
begin
// QRCodeBitmap.SetSize(QRCode.Rows, QRCode.Columns);
for Local_Row := 0 to QRCode.Rows – 1 do
begin
currentRow := (pixH * Local_Row);
j := 0;
while J < pixH do
Begin
if J > 0 then
currentRow := currentRow + 1;
J := J + 1;
for Local_Column := 0 to QRCode.Columns – 1 do
begin
currentCol := (PixW * Local_Column);
k := 0;
while K < pixW do
Begin
if k > 0 then
currentCol := currentCol + 1;
k := k+1;
if (QRCode.IsBlack[Local_Row, Local_Column]) then
begin
QRCodeBitmap.SetPixel(currentRow, currentCol, vPixelB);
end
else
begin
QRCodeBitmap.SetPixel(currentRow, CurrentCol, vPixelW);
end;
End;
end;
End;
end;
bmp.Unmap(QRCodeBitmap);
end;
finally
QRCode.Free;
end;
ms := TMemoryStream.Create;
bmp.SaveToStream(ms);
ms.Position := 0;
DestImage.Bitmap.LoadFromStream(ms);
try
if ms <> nil then
ms.Free;
if bmp <> nil then
bmp.Free;
if bmp2 <> nil then
bmp2.Free;
except
end;
end;
and the result is a perfect qrCode without aliasing and interpolation: