Skiasharp: [QUESTION] How to validate a given stream/byte-array contains a valid image?

Created on 14 Feb 2020  路  5Comments  路  Source: mono/SkiaSharp

This can be achieved quite simply using .NET's library for images, but I've still not found out a way to do this via SkiaSharp.

Could you please give me some pointers?

type-question

All 5 comments

The best way would be to make use of the SKCodec class: https://docs.microsoft.com/dotnet/api/skiasharp.skcodec

You could try try creating it with this: https://docs.microsoft.com/en-us/dotnet/api/skiasharp.skcodec.create?view=skiasharp-1.68.1#SkiaSharp_SKCodec_Create_System_IO_Stream_SkiaSharp_SKCodecResult__

That would mean that the image appears correct.

using var codec = SKCodec.Create(<stream>, out var result);
if (codec == null || result != SKCodecResult.Success)
    throw new Exception("bad image.");

Another way would be to just use the SKImage.FromEncodedData and see if there is an image: https://docs.microsoft.com/en-us/dotnet/api/skiasharp.skimage.fromencodeddata?view=skiasharp-1.68.1

Basically this:

using var image = SKImage.FromEncodedData(<stream>);
if (image == null)
    throw new Exception("bad image.");

This is a bit heavier as it actually loads the image.

Thank you @mattleibow!

@mattleibow just one quick question if I may, if our image comes in a byte[] format, I can't actually use the SKCodec.Create method. Should I copy the array to a stream, or would that make the operation as slow as its alternatives? (SKImage.FromEncodedData/SKBitmap.Decode)

EDIT: I basically want to check if the image is valid, so that then I can proceed to manipulate it. In that case, it shouldn't be a problem to rely on SKImage.FromEncodedData/SKBitmap.Decode returning a null object, right?

Oh, yeah. I see there is no overload for byte[]. I'll add that.

But, for now, you could even use SKBitmap.DecodeBounds. That also just does the reading of the header so as not to fully decode the entire image. If you want to make sure that it truly is a valid image (not corrupted), then using SKImage.FromEncodedData/SKBitmap.Decode to fully decode is probably the best.

But, as a separate thing, you can also create a SKData from any array:

```csharp
byte[] bytes = ...;

fixed (void* ptr = bytes) {
using var data = SKData.Create((IntPtr)ptr, bytes.length);
}
````

Just remember, the data cannot outlive the fixed block as it requires that the GC does not move/collect the array.

Was this page helpful?
0 / 5 - 0 ratings