Via Cà Matta 2 - Peschiera Borromeo (MI)
+39 02 00704272
info@synaptica.info

Firemonkey bitmap scaling without Aliasing on Android

Digital solution partner

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:

IMG_0058