skia4delphi / skia4delphi

Skia4Delphi is a cross-platform 2D graphics API for Delphi platforms based on Google's Skia Graphics Library. It provides a comprehensive 2D API that can be used across mobile, server and desktop models to render images.
https://skia4delphi.org
MIT License
693 stars 141 forks source link

PNG decoding #15

Closed FlavienQui closed 2 years ago

FlavienQui commented 2 years ago

Some PNG files don’t get decoded correctly with Skia4Delphi 2.0.1 on Windows. Images have been loaded and saved with the following method:

procedure DecodeEncodePng(const AFileNameIn, AFileNameOut: string);
var
    LStreamIn, LStreamOut: TStream;
    LImage: ISkImage;
begin
    LStreamOut := nil;
    LStreamIn := TFileStream.Create(AFileNameIn, fmOpenRead or fmShareDenyWrite);
    try
        LStreamOut := TFileStream.Create(AFileNameOut, fmOpenWrite or fmCreate);

        LImage := TSkImage.MakeFromEncoded(LStreamIn);
        LImage.EncodeToStream(LStreamOut, TSkEncodedImageFormat.PNG);
    finally
        LStreamIn.Free;
        LStreamOut.Free;
    end;
end;

DecodeEncodePng('World_time.png', 'World_time_skia.png');

World_time.png World_time

World_time_skia.png World_time_skia

viniciusfbb commented 2 years ago

Hi @FlavienQui!

Thank you very much to report this issue.

We had detected some problems a few days ago in the decoder implementation and we've even fixed it. However, we will only make the fix available in version 3.0 that is being developed because the solution we propose involves a lot of changes, including binaries for all platforms.

Version 3.0 will be released later this month.

Until then, a workaround would be to use TBitmap to decode and transform into ISkImage. For example:

uses
  System.IOUtils,
  Skia,
  Skia.FMX;

procedure DecodeEncodePng(const AInput, AOutput: string);
var
  LInputBitmap: TBitmap;
  LImage: ISkImage;
begin
  LInputBitmap := TBitmap.Create;
  try
    LInputBitmap.LoadFromFile(AInput);
    LImage := LInputBitmap.ToSkImage;
  finally
    LInputBitmap.Free;
  end;
  TFile.WriteAllBytes(AOutput, LImage.EncodeToBytes(TSkEncodedImageFormat.PNG));
end;

The same implementation above applies to Vcl as well.

Once again, thanks for the issue report, I will put this World_time.png in the unit tests.

Regards, Vinicius

FlavienQui commented 2 years ago

Hi @viniciusfbb,

Thanks a lot for your reply and your great work on this project.

I'm looking forward version 3.0.

Best regards,

Flavien

viniciusfbb commented 2 years ago

The problem was solved in new release. Please download new version 3.0.0.