public static IntPtr WebPAnimDecoderNew(ref WebPData webpdata, ref WebPAnimDecoderOptions decopts) { switch (IntPtr.Size) { case 4: return(WebPAnimDecoderNew_x86(ref webpdata, ref decopts, WEBP_DEMUX_ABI_VERSION)); case 8: return(WebPAnimDecoderNew_x64(ref webpdata, ref decopts, WEBP_DEMUX_ABI_VERSION)); default: throw new InvalidOperationException("Invalid platform. Can not find proper function"); } }
private static extern int WebPAnimDecoderOptionsInit_x64(ref WebPAnimDecoderOptions decopts, int abiversion);
private static extern IntPtr WebPAnimDecoderNew_x64(ref WebPData webpdata, ref WebPAnimDecoderOptions decopts, int abiversion);
private void decodeWebP(MemoryStream stream) { Bitmap bmp = null; Bitmap firstbmp = null; bool firstbitmap = true; BitmapData bmpData = null; IntPtr dec = (IntPtr)0; const int UintBytes = 4; byte [] rawWebP = stream.ToArray(); UIntPtr dataSize = (UIntPtr)rawWebP.Length; GCHandle pinnedWebP = GCHandle.Alloc(rawWebP, GCHandleType.Pinned); IntPtr ptrData = pinnedWebP.AddrOfPinnedObject(); try { //Get info about webp image GetWebpInfo(ptrData, rawWebP.Length, out int imgWidth, out int imgHeight, out bool hasAlpha, out bool hasAnimation, out string format); if (hasAnimation) { //demux the image WebPData webpdata = new WebPData() { bytes = ptrData, size = dataSize }; WebPAnimDecoderOptions dec_options = new WebPAnimDecoderOptions(); //init decoder options with default values WebPWrapper.WebPAnimDecoderOptionsInit(ref dec_options); //set color mode to blue green red alpha to match up with how the bitmap is formatted dec_options.color_mode = WEBP_CSP_MODE.MODE_BGRA; //create the decoder dec = WebPWrapper.WebPAnimDecoderNew(ref webpdata, ref dec_options); IntPtr buf; int timestamp; uint outputSize; WebPAnimInfo animinfo = new WebPAnimInfo(); //get animation info WebPWrapper.WebPAnimDecoderGetInfo(dec, ref animinfo); imgWidth = (int)animinfo.canvas_width; imgHeight = (int)animinfo.canvas_height; int prevtimestamp = 0; bool first = true; while (WebPWrapper.WebPAnimDecoderHasMoreFrames(dec) == 1) { //get next frame WebPWrapper.WebPAnimDecoderGetNext(dec, out buf, out timestamp); //copy frame into an Image (Bitmap) bmp = new Bitmap(imgWidth, imgHeight, PixelFormat.Format32bppArgb); bmpData = bmp.LockBits(new Rectangle(0, 0, imgWidth, imgHeight), ImageLockMode.WriteOnly, bmp.PixelFormat); outputSize = (uint)(bmpData.Stride * imgHeight); WebPWrapper.CopyMemory(bmpData.Scan0, buf, outputSize); bmp.UnlockBits(bmpData); //Add frame to the list AddFrame(bmp, (timestamp - prevtimestamp) / 10); prevtimestamp = timestamp; bmpData = null; if (first) { ActiveImage = bmp; Height = imgHeight; Width = imgWidth; first = false; } } WebPWrapper.WebPAnimDecoderReset(dec); WebPWrapper.WebPAnimDecoderDelete(dec); dec = (IntPtr)0; IsAnimated = true; } else { //Create a Bitmap and Lock all pixels to be written if (hasAlpha) { bmp = new Bitmap(imgWidth, imgHeight, PixelFormat.Format32bppArgb); } else { bmp = new Bitmap(imgWidth, imgHeight, PixelFormat.Format24bppRgb); } bmpData = bmp.LockBits(new Rectangle(0, 0, imgWidth, imgHeight), ImageLockMode.WriteOnly, bmp.PixelFormat); //Uncompress the image int outputSize = bmpData.Stride * imgHeight; if (bmp.PixelFormat == PixelFormat.Format24bppRgb) { WebPWrapper.WebPDecodeBGRInto(ptrData, rawWebP.Length, bmpData.Scan0, outputSize, bmpData.Stride); } else { WebPWrapper.WebPDecodeBGRAInto(ptrData, rawWebP.Length, bmpData.Scan0, outputSize, bmpData.Stride); } ActiveImage = bmp; Height = imgHeight; Width = imgWidth; } } catch (Exception e) { GuiEngine.Current.log(e.ToString()); } finally { //Unlock the pixels if (bmpData != null) { bmp.UnlockBits(bmpData); } if (dec != (IntPtr)0) { WebPWrapper.WebPAnimDecoderDelete(dec); } //Free memory if (pinnedWebP.IsAllocated) { pinnedWebP.Free(); } } }