Saturday, 11 February 2012

WebP from .Net

I recently had the need to convert images to Google's .webp format from .net. There is a .net port of the WebP library available, but it didn't seem to work for me and it seems to be no longer maintained.

So P/Invoke it was. Here's the code I used:

Bitmap source = new Bitmap("Desert.jpg");
BitmapData data = source.LockBits(
    new Rectangle(0, 0, source.Width, source.Height),
    ImageLockMode.ReadOnly,
    PixelFormat.Format24bppRgb);
IntPtr unmanagedData;
int size = WebPEncodeBGR(data.Scan0, source.Width, source.Height, data.Stride, 85, out unmanagedData);
byte[] managedData = new byte[size];
Marshal.Copy(unmanagedData, managedData, 0, size);
File.WriteAllBytes("Desert.webp", managedData);

Marshal.FreeHGlobal(unmanagedData); // Doesn't work. How do we free the unmanaged data?

As you can see, all goes swimmingly until it comes to freeing the unmanaged memory allocated by the WebP library. The memory is allocated by malloc() and needs to be freed by calling free(), however you have no access to this from .net.

My solution was to modify the WebP library to provide a WebPFree function, which simply calls the C free(). Calling this instead of Marshal.FreeHGlobal fixes the memory leak.

I've included my modifed WebP binaries as part of a sample project here.

3 comments:

  1. Hi I was wondering how one would use this in VB environment as well as decode to a bitmap to display onto a picturebox etc. Thank you.

    ReplyDelete
  2. oh I came back to trying to work with webp and see here that ive already made a post here. As to releasing the memory maybe have the garbage collector do its thing?
    system.gc.collect(); //I think thats what it was.

    ReplyDelete
  3. Oh yeah and I was wondering about the pinvoke bit that isnt shown here, could we get that here aswell.

    ReplyDelete