Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

SKBitmap.Decode not working with PNG #640

Closed
anetapetryla opened this issue Sep 20, 2018 · 21 comments
Closed

SKBitmap.Decode not working with PNG #640

anetapetryla opened this issue Sep 20, 2018 · 21 comments
Milestone

Comments

@anetapetryla
Copy link

anetapetryla commented Sep 20, 2018

Description

When I want to decode my image "photo.png", the Decode method return null (with JPEG works fine). I think, It's a version bug.

Code

        using (var bitmap = SKBitmap.Decode("photo.png"))
        {
            ....
        }

Version

SkiaSharp: 1.60.3
SkiaSharp.Views: 1.60.3
SkiaSharp.Views.Forms: 1.60.3

@GalaxyVelocity
Copy link

Tried to open simple PNG file from MS Paint, all is well.

SkiaSharp: 1.60.3
.NET Framework 4.6.1

Maybe a problem in the PNG file, wrong format.

Place the file that you are trying to open.

@mattleibow
Copy link
Contributor

You could try and get the error code by doing something like this:

// open the stream
var stream = new SKFileStream("photo.png");

// create the codec
var codec = SKCodec.Create(stream));

// we need a place to store the bytes
var bitmap = new SKBitmap(codec.Info);

// decode!
// result should be SKCodecResult.Success, but you may get more information
var result = codec.GetPixels(bitmap.Info, bitmap.GetPixels());

@anetapetryla
Copy link
Author

Tried to open simple PNG file from MS Paint, all is well.

SkiaSharp: 1.60.3
.NET Framework 4.6.1

Maybe a problem in the PNG file, wrong format.

Place the file that you are trying to open.

The format is correct, the photo is opened in every graphic program and I tried to show in application view. So, everything is good

@anetapetryla
Copy link
Author

anetapetryla commented Sep 21, 2018

You could try and get the error code by doing something like this:

// open the stream
var stream = new SKFileStream("photo.png");

// create the codec
var codec = SKCodec.Create(stream));

// we need a place to store the bytes
var bitmap = new SKBitmap(codec.Info);

// decode!
// result should be SKCodecResult.Success, but you may get more information
var result = codec.GetPixels(bitmap.Info, bitmap.GetPixels());

Not working, because SKCodec.Create(stream) return null, despite the stream was created.

zrzut ekranu 2018-09-21 o 07 32 49

@GalaxyVelocity
Copy link

@aneti9862 try reading the byte array

var bytes = System.IO.File.ReadAllBytes("photo.png");

using (var bitmap = SKBitmap.Decode(bytes))
{
  ....
}

Will receive an error?

@anetapetryla
Copy link
Author

anetapetryla commented Sep 21, 2018

@GalaxyVelocity, decode method still returns the null, despite the bytes are filled (out of errors)

zrzut ekranu 2018-09-21 o 08 38 27

@GalaxyVelocity
Copy link

GalaxyVelocity commented Sep 21, 2018

@aneti9862 Try to convert the png using GDI+ as a test

    public byte[] ImageToByteArray(System.Drawing.Image image)
    {
        using (var ms = new System.IO.MemoryStream())
        {
            image.Save(ms, System.Drawing.Imaging.ImageFormat.Png);
            return ms.ToArray();
        }
    }
    var bytes = ImageToByteArray(System.Drawing.Image.FromFile("photo.png"));

    using (var bitmap = SKBitmap.Decode(bytes))
    {
        ...
    }

Maybe this temporary solution will help.

@anetapetryla
Copy link
Author

anetapetryla commented Sep 21, 2018

@GalaxyVelocity, I don't have access to System.Drawing.Image (Xamarin.Forms iOS)

zrzut ekranu 2018-09-21 o 09 07 08

@GalaxyVelocity
Copy link

Yes, sorry. GDI+ graphics library. System.Drawing.Image, is a Win32 implementation that ties into the Windows Desktop.

The test was to convert the original png file and transfer it SKBitmap.Decode.

@mattleibow
Copy link
Contributor

@aneti9862 Is it possible to upload the image somewhere? Maybe not here as GitHub processes the image. OneDrive, Dropbox, Google Drive, etc. Then I can check to see exactly what is happening. If you don't want to go public, just send it over to my email maleib@microsoft.com.

@anetapetryla
Copy link
Author

anetapetryla commented Sep 24, 2018

@mattleibow, PNG and JPG photos are set in Google Drive folder (link below):

https://drive.google.com/drive/folders/17JSyRUXGVLIkuShWpDqRO0X_Q8jZbtrD?usp=sharing

@mattleibow mattleibow added this to New in Triage via automation Sep 26, 2018
@mattleibow
Copy link
Contributor

@aneti9862 I think it may have to do with the fact of iOS compressing the .png images with a proprietary format. See #140

See this comment to fix: #140 (comment)

If this is not the case, could you attach a simple sample? Also, how are you getting the image? is it a resource, or downloaded, or on the device?

@mattleibow
Copy link
Contributor

Closing this as there appears to be no more comments. The solution is that the png needs to have the optimization turned off.

The Apple optimized png is no longer a traditional png, and just retains its old extension. Apple processes it and transforms it into something else.

Triage automation moved this from New to Complete / Invalid Oct 30, 2018
@sergiokoo
Copy link

Despite I have 'Optimize PNG images' turned off in project settings, I still unable to use my *.png on iOS with exactly the same errors as aneti9862 described above. For me, the solution was to replace

return SKBitmap.Decode(File.OpenRead(path));

with

return UIImage.FromFile(path).ToSKBitmap();

@najak3d
Copy link

najak3d commented Jul 12, 2020

Despite I have 'Optimize PNG images' turned off in project settings, I still unable to use my *.png on iOS with exactly the same errors as aneti9862 described above. For me, the solution was to replace

return SKBitmap.Decode(File.OpenRead(path));

with

return UIImage.FromFile(path).ToSKBitmap();

SKBitmap.Decode() - all forms were failing... many alterations/trials to get it working failed. It works fine on Android/UWP, but just not iOS!

HOWEVER, THIS KLUDGE WORKED FOR ME! (using UIImage.FromFile() first)

In order to make it work for our project, only our iOS Launcher included UIImage, since the rest of our project was .Net Standard 2.0. Therefore, I inserted a plugin method to make this work from our core code, like this:

class PluginMethods
{
static Func<string, SKBitmap> LoadImageFromFilepath;
}

And then from our Launcher, I hooked up this method to the method that makes it work in AppDelegate.cs:

class AppDelegate
{
public override void OnActivated(.....)
{
....
PluginMethods.LoadImageFromFilepath = _LoadImageFromFilepath;
}

static private SKBitmap _LoadImageFromFilepath(string filepath)
{
UIImage img = UIImage.FromFile(filepath);
SkiaSharp.SKBitmap bm = img.ToSKBitmap();
return bm;
}
}

===
So now my .NET Standard application code is able to load PNG images from file on iOS using "PluginMethods.LoadImageFromFilepath(path)".

Thanks for this kludge!

@mattleibow
Copy link
Contributor

@najak3d is it possible to attach a diagnostic build log or a binlog? I'll have a look and see what is happening to the build

@najak3d
Copy link

najak3d commented Jul 12, 2020

Please tell me how to obtain the log you are wanting? I run from Visual Studio, and when the Decode method is called, nothing shows up in the Console log. Maybe there is something in the Device Log, or elsewhere.

@mattleibow
Copy link
Contributor

mattleibow commented Jul 12, 2020

@najak3d Ah, sorry. You can either run the build from the command line with:

msbuild /r /bl <path-to-project-file>

Or, install the extension: https://marketplace.visualstudio.com/items?itemName=VisualStudioProductTeam.ProjectSystemTools

Click the play/start button in the View > Other Windows > Build Logging window:

When the window appears, you can right-click and save the logs:

When the window is open and you have pressed record, then rebuild the project. The build will appear.

@najak3d
Copy link

najak3d commented Jul 13, 2020

I installed those Project System Tools, and then opened the "Build Logging" window. Then did a Clean/Rebuild in Visual Studio, but the Build Logging window remained empty black (filter set to "All"). So nothing shows here.

@mattleibow
Copy link
Contributor

@najak3d did you click the little black arrow in the top left of the tool window? You need to start a listener.

@bennor
Copy link

bennor commented Oct 19, 2020

In case anyone else runs into this, the problem for me was that I needed to keep the source stream open, so I was creating a copy:

using var copy = new MemoryStream();
await source.CopyToAsync(copy);

using var bitmap = SKBitmap.Decode(copy); // sets bitmap to `null` 😢

The solution was to rewind the stream after CopyTo:

using var copy = new MemoryStream();
await source.CopyTo(copy);
source.Position = 0;
copy.Position = 0;

using var bitmap = SKBitmap.Decode(copy); // 🎉

@mattleibow mattleibow removed this from Done in Triage May 22, 2022
@mattleibow mattleibow added this to the v2.88.1 milestone May 22, 2022
@mono mono locked as resolved and limited conversation to collaborators Aug 19, 2022
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
Status: Done
Development

No branches or pull requests

6 participants