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

How to convert byte array to SKBitmap in SkiaSharp? #416

Closed
parthipanr opened this issue Dec 28, 2017 · 4 comments
Closed

How to convert byte array to SKBitmap in SkiaSharp? #416

parthipanr opened this issue Dec 28, 2017 · 4 comments
Projects

Comments

@parthipanr
Copy link

parthipanr commented Dec 28, 2017

SKBitmap.Bytes is read only, any suggestion on how to Marshal.Copy a byte array to the SKBitmap? I am using using below code snippet but it not working.

Code snippet:

        SKBitmap bitmap = new SKBitmap((int)Width, (int)Height);
        bitmap.LockPixels();
        byte[] array = new byte[bitmap.RowBytes * bitmap.Height];
        for (int i = 0; i < pixelArray.Length; i++)
        {
            SKColor color = new SKColor((uint)pixelArray[i]);
            int num = i % (int)Width;
            int num2 = i / (int)Width;
            array[bitmap.RowBytes * num2 + 4 * num] = color.Blue;
            array[bitmap.RowBytes * num2 + 4 * num + 1] = color.Green;
            array[bitmap.RowBytes * num2 + 4 * num + 2] = color.Red;
            array[bitmap.RowBytes * num2 + 4 * num + 3] = color.Alpha;
        }
        Marshal.Copy(array, 0, bitmap.Handle, array.Length);
        bitmap.UnlockPixels();
@xPaw
Copy link

xPaw commented Jan 8, 2018

I was just trying to solve the same problem, it worked for me by using bitmap.GetPixesl() instead of bitmap.Handle. However I would like to know some approach that could be used without marshalling.

@parthipanr
Copy link
Author

parthipanr commented Jan 8, 2018

@xPaw does retrieving the bitmap pointer by using bitmap.GetPixels() is working properly to copy the byte array to bitmap ?

@xPaw
Copy link

xPaw commented Jan 8, 2018

It worked for me.

@mattleibow
Copy link
Contributor

mattleibow commented Jan 11, 2018

You will always have to do some marshaling as the bitmap lives in unmanaged/native memory and the byte array is in managed code. But, you may be able to do something like this:

// the pixel array of uint 32-bit colors
var pixelArray = new uint[] {
	0xFFFF0000, 0xFF00FF00,
	0xFF0000FF, 0xFFFFFF00
};

// create an empty bitmap
bitmap = new SKBitmap();

// pin the managed array so that the GC doesn't move it
var gcHandle = GCHandle.Alloc(pixelArray, GCHandleType.Pinned);

// install the pixels with the color type of the pixel data
var info = new SKImageInfo(2, 2, SKImageInfo.PlatformColorType, SKAlphaType.Unpremul);
bitmap.InstallPixels(info, gcHandle.AddrOfPinnedObject(), info.RowBytes, null, delegate { gcHandle.Free(); }, null);

This pins the managed memory and passes the pointer to the bitmap. This way, both are accessing the same memory data and there is no need to actually do any conversions (or copying). (It is essential that the pinned memory be unpinned after usage so that the memory can be freed by the GC.)

xPaw added a commit to ValveResourceFormat/ValveResourceFormat that referenced this issue Jan 11, 2018
@mattleibow mattleibow added this to Complete / Invalid in Triage May 5, 2018
@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
No open projects
Triage
  
Done
Development

No branches or pull requests

3 participants