Closed MazighusDZ closed 2 years ago
Plese note that support of SKIA4Delphi into SVGIconImageList is only for VCL, at the moment... FMX is coming...
I've notice this problem in the recent version of Image32 Library
I can't duplicate this. Could you please attach an SVG that shows the problem. Also, try downloading Image32 (ver 4.1) again.
I'll investigate, because it seems a problem with an FMX Windows application with HIGH-DPI support "PerMonitor V2" on a 4K monitor...
Hi Carlo Barazzetta I send you a demo with the code take a look Demo Render.zip
Please try Image32's latest repository 'snapshot' here.
The proleme is in FMX.Image32SVG at line 175 when assigned Image32 to Bitmap I found an alternative function by saving Imag32 to stream and load it by Bitmap
procedure Image32ToFmxBitmap(const ASource: TImage32; const ATarget: FMX.Graphics.TBitmap);
var
LStream: TMemoryStream;
begin
LStream := TMemoryStream.Create;
try
ASource.SaveToStream(LStream, 'PNG');
LStream.Position := 0;
ATarget.LoadFromStream(LStream);
finally
LStream.Free;
end;
end;
Example
procedure TForm1.PaintBox2Paint(Sender: TObject; Canvas: TCanvas);
var
bmp: TBitmap;
img32: TImage32;
rec: TRectF;
begin
img32 := TImage32.Create(80, 80);
try
img32.LoadFromFile('C:\Users\COAMA\Desktop\icons8_ok.svg');
bmp := TBitmap.Create;
try
Image32ToFmxBitmap(img32, bmp);
rec := RectF(0,0,bmp.Width,bmp.Height);
Canvas.Lock;
Canvas.DrawBitmap(bmp, rec, rec, 1.0);
Canvas.Unlock;
finally
bmp.Free;
end;
finally
img32.Free;
end;
end;
Result
SVG file
I suspect the problem you're trying to circumvent is due to a misunderstanding of how Image32 loads SVG files (which are very different to raster image files).
With raster images (BMP, PNG, JPG) the image size is effectively fixed and these raster images will be loaded at that resolution. But with SVGs, the TImage32 object should be resized before loading the image, as this will scale the vectors to the correct size before rasterization. In other words, if you have an SVG icon that has a view box width and height of say 32 x 32px, but you want to display this image at 512 x 512px, then you should set the image size to 512 x 512 before loading from file.
See also the documentation here: http://www.angusj.com/delphi/image32/Docs/Units/Img32.Fmt.SVG/_Body.htm
Also, if you want to convert from Image32 to TBitmap via streaming (though there's a much more efficient way, at least on Windows), I suggest you don't use the PNG format, as this will waste a lot of time/resources compressing and decompressing the image unnecessarily. Just use a BMP stream and set the bitmap to pf32bits pixelformat. You may also want to set AlphaFormat to afDefined too if you're displaying semi-transparent images.
I'll try to fix as soon as possibile.
I've fixed the problem using the suggestion of @MazighusDZ but using ASource.SaveToStream(LStream, 'BMP'); as suggested by @AngusJohnson. In the previous version I'm using Img32.FMX.AssignImage32ToFmxBitmap(FImage32, ABitmap); written by @AngusJohnson but the result is not "smoot".
In the previous version I'm using Img32.FMX.AssignImage32ToFmxBitmap(FImage32, ABitmap); written by @AngusJohnson but the result is not "smoot".
OK. I don't understand why a seemingly straight pixel copy (via a TBitMapData object) would be doing this. I'll investigate.
I now understand what's happening ...
Evidently TBitmap automatically premultiplies images on load which I believe is problematic. Firstly, it (marginally) degrades image quality. But the real problem is when you save a premultiplied image there's no way to tell it has been premultiplied. So in loading it again there's every likelihood that it will be premultiplied once again which IS NOT a good thing. Nevertheless when premultiply is managed sensibly it does is make displaying images faster (and is a prerequisite at least for Windows alpha blending).
Here's my code. (I've made temporary changes to FMX.Image32SVG by added Img32.FMX to the uses clause and modifying the TFmxImage32SVG.PaintToBitmap method as per below):
With the following SVG loaded into the SVGIconImageFMX Demo -
and zooming (X10) into the top of this image we see the following ...
FImage32 (STARTING IMAGE)
LSource := TBitMapData.Create(FImage32.Width, FImage32.Height, TPixelFormat.BGRA);
LSource.Data := FImage32.PixelBase;
LSource.Pitch := FImage32.Width * 4;
ABitmap.SetSize(FImage32.Width, FImage32.Height);
if ABitmap.Map(TMapAccess.Write, LDest) then
try
LDest.Copy(LSource);
finally
ABitmap.Unmap(LDest);
end;
ABitmap.SaveToFile('c:\temp\Test_TBitMapData.bmp');
A PERFECT COPY
LStream := TMemoryStream.Create;
try
FImage32.SaveToStream(LStream, 'BMP');
LStream.Position := 0;
ABitmap.LoadFromStream(LStream);
finally
LStream.Free;
end;
ABitmap.SaveToFile('c:\temp\Test_TMemoryStream.bmp');
end;
Note blackening behind antialias
As you can see FMX.TBitmap has modified the image during the load (using premultiplied alpha)! Evidently FMX requires premultiplied alphas to properly display semi-transparent images. But there doesn't seem to be any mention of this in the FMX.TBitmap documentation. And there's no AlphaFormat property either as there is in VCL.TBitmap.
However TImage32 does allow you to apply premultiply alpha through its PreMultiply method. But because this process is mildly destructive it can't be perfectly reversed, so there's no UnPreMultiply method. (If you will later need to reverse PreMultiply, then you'll need to save a copy of the original image.)
FImage32.PreMultiply;
LSource := TBitMapData.Create(FImage32.Width, FImage32.Height, TPixelFormat.BGRA);
LSource.Data := FImage32.PixelBase;
LSource.Pitch := FImage32.Width * 4;
ABitmap.SetSize(FImage32.Width, FImage32.Height);
if ABitmap.Map(TMapAccess.Write, LDest) then
try
LDest.Copy(LSource);
finally
ABitmap.Unmap(LDest);
end;
ABitmap.SaveToFile('c:\temp\Test_Image32_PreMultiply.bmp');
Image32 + premultiply
Recommendation:
Use Image32's PreMultiply method before converting it to a TBitmap.
This will be more efficient than adding the extra steps of saving to and loading from stream.
As a background to this you may want to read Anders's comment at https://quality.embarcadero.com/browse/RSP-26621.
Yes, VCL TBitmap alpha management is a real mess. Unfortunately in FMX, TBitmap alpha management even worse, because the mess is simply hidden from view.
Done and pushed now.
The render with Skia is great but with SvgIconImage in Firemonkey is not smooth, can you fix it