private unsafe List <(Texture2D, int)> LoadAnimation(string loadPath) { List <(Texture2D, int)> ret = new List <(Texture2D, int)>(); TextAsset textasset = Resources.Load <TextAsset>(loadPath); byte[] bytes = textasset.bytes; WebPAnimDecoderOptions option = new WebPAnimDecoderOptions { use_threads = 1, color_mode = (unity.libwebp.Interop.WEBP_CSP_MODE)WEBP_CSP_MODE.MODE_RGBA }; NativeLibwebpdemux.WebPAnimDecoderOptionsInit(&option); fixed(byte *p = bytes) { WebPData webpdata = new WebPData { bytes = p, size = new UIntPtr((uint)bytes.Length) }; WebPAnimDecoder *dec = NativeLibwebpdemux.WebPAnimDecoderNew(&webpdata, &option); WebPAnimInfo anim_info = new WebPAnimInfo(); NativeLibwebpdemux.WebPAnimDecoderGetInfo(dec, &anim_info); Debug.LogWarning($"{anim_info.frame_count} {anim_info.canvas_width}/{anim_info.canvas_height}"); int size = (int)anim_info.canvas_width * 4 * (int)anim_info.canvas_height; dec->config_.options.flip = 1; dec->config_.options.no_fancy_upsampling = 1; int timestamp = 0; IntPtr pp = new IntPtr(); byte **unmanagedPointer = (byte **)&pp; for (int i = 0; i < anim_info.frame_count; ++i) { int result = NativeLibwebpdemux.WebPAnimDecoderGetNext(dec, unmanagedPointer, ×tamp); Assert.AreEqual(1, result); int lWidth = (int)anim_info.canvas_width; int lHeight = (int)anim_info.canvas_height; bool lMipmaps = false; bool lLinear = false; Texture2D texture = Texture2DExt.CreateWebpTexture2D(lWidth, lHeight, lMipmaps, lLinear); texture.LoadRawTextureData(pp, size); texture.Apply(updateMipmaps: false, makeNoLongerReadable: true); ret.Add((texture, timestamp)); } NativeLibwebpdemux.WebPAnimDecoderReset(dec); NativeLibwebpdemux.WebPAnimDecoderDelete(dec); } return(ret); }
unsafe List <(Texture2D, int)> LoadAnimation(string loadPath) { List <ValueTuple <Texture2D, int> > ret = new List <ValueTuple <Texture2D, int> >(); TextAsset textasset = Resources.Load <TextAsset>(loadPath); byte[] bytes = textasset.bytes; WebPAnimDecoderOptions option = new WebPAnimDecoderOptions { use_threads = 1, color_mode = WEBP_CSP_MODE.MODE_RGBA }; libwebpdemux.WebPAnimDecoderOptionsInit(ref option); fixed(byte *p = bytes) { IntPtr ptr = (IntPtr)p; WebPData webpdata = new WebPData { bytes = ptr, size = new UIntPtr((uint)bytes.Length) }; IntPtr dec = libwebpdemux.WebPAnimDecoderNew(ref webpdata, ref option); WebPAnimInfo anim_info = new WebPAnimInfo(); libwebpdemux.WebPAnimDecoderGetInfo(dec, ref anim_info); Debug.LogWarning($"{anim_info.frame_count} {anim_info.canvas_width}/{anim_info.canvas_height}"); int size = anim_info.canvas_width * 4 * anim_info.canvas_height; IntPtr unmanagedPointer = new IntPtr(); int timestamp = 0; for (int i = 0; i < anim_info.frame_count; ++i) { int result = libwebpdemux.WebPAnimDecoderGetNext(dec, ref unmanagedPointer, ref timestamp); int lWidth = anim_info.canvas_width; int lHeight = anim_info.canvas_height; bool lMipmaps = false; bool lLinear = false; Texture2D texture = new Texture2D(lWidth, lHeight, TextureFormat.RGBA32, lMipmaps, lLinear); texture.LoadRawTextureData(unmanagedPointer, size); {// Flip updown. // ref: https://github.com/netpyoung/unity.webp/issues/18 // ref: https://github.com/webmproject/libwebp/blob/master/src/demux/anim_decode.c#L309 Color[] pixels = texture.GetPixels(); Color[] pixelsFlipped = new Color[pixels.Length]; for (int y = 0; y < anim_info.canvas_height; y++) { Array.Copy(pixels, y * anim_info.canvas_width, pixelsFlipped, (anim_info.canvas_height - y - 1) * anim_info.canvas_width, anim_info.canvas_width); } texture.SetPixels(pixelsFlipped); } texture.Apply(); ret.Add((texture, timestamp)); } libwebpdemux.WebPAnimDecoderReset(dec); libwebpdemux.WebPAnimDecoderDelete(dec); } return(ret); }
private unsafe List <(Texture2D, int)> LoadAnimation(string loadPath) { List <(Texture2D, int)> ret = new List <(Texture2D, int)>(); TextAsset textasset = Resources.Load <TextAsset>(loadPath); byte[] bytes = textasset.bytes; WebPAnimDecoderOptions option = new WebPAnimDecoderOptions { use_threads = 1, color_mode = WEBP_CSP_MODE.MODE_RGBA, }; option.padding[5] = 1; NativeLibwebpdemux.WebPAnimDecoderOptionsInit(&option); fixed(byte *p = bytes) { WebPData webpdata = new WebPData { bytes = p, size = new UIntPtr((uint)bytes.Length) }; WebPAnimDecoder *dec = NativeLibwebpdemux.WebPAnimDecoderNew(&webpdata, &option); //dec->config_.options.flip = 1; WebPAnimInfo anim_info = new WebPAnimInfo(); NativeLibwebpdemux.WebPAnimDecoderGetInfo(dec, &anim_info); Debug.LogWarning($"{anim_info.frame_count} {anim_info.canvas_width}/{anim_info.canvas_height}"); uint size = anim_info.canvas_width * 4 * anim_info.canvas_height; int timestamp = 0; IntPtr pp = new IntPtr(); byte **unmanagedPointer = (byte **)&pp; for (int i = 0; i < anim_info.frame_count; ++i) { int result = NativeLibwebpdemux.WebPAnimDecoderGetNext(dec, unmanagedPointer, ×tamp); Assert.AreEqual(1, result); int lWidth = (int)anim_info.canvas_width; int lHeight = (int)anim_info.canvas_height; bool lMipmaps = false; bool lLinear = false; Texture2D texture = Texture2DExt.CreateWebpTexture2D(lWidth, lHeight, lMipmaps, lLinear); texture.LoadRawTextureData(pp, (int)size); {// Flip updown. // ref: https://github.com/netpyoung/unity.webp/issues/25 // ref: https://github.com/netpyoung/unity.webp/issues/21 // ref: https://github.com/webmproject/libwebp/blob/master/src/demux/anim_decode.c#L309 Color[] pixels = texture.GetPixels(); Color[] pixelsFlipped = new Color[pixels.Length]; for (int y = 0; y < anim_info.canvas_height; y++) { Array.Copy(pixels, y * anim_info.canvas_width, pixelsFlipped, (anim_info.canvas_height - y - 1) * anim_info.canvas_width, anim_info.canvas_width); } texture.SetPixels(pixelsFlipped); } texture.Apply(); ret.Add((texture, timestamp)); } NativeLibwebpdemux.WebPAnimDecoderReset(dec); NativeLibwebpdemux.WebPAnimDecoderDelete(dec); } return(ret); }
private unsafe List <(Texture2D, int)> LoadAnimation3(string loadPath) { List <ValueTuple <Texture2D, int> > ret = new List <ValueTuple <Texture2D, int> >(); TextAsset textasset = Resources.Load <TextAsset>(loadPath); byte[] bytes = textasset.bytes; WebPAnimDecoderOptions option = new WebPAnimDecoderOptions { use_threads = 1, color_mode = (unity.libwebp.Interop.WEBP_CSP_MODE)WEBP_CSP_MODE.MODE_RGBA }; unity.libwebp.Interop.WebPDecoderConfig config = new unity.libwebp.Interop.WebPDecoderConfig(); //if (Decode.WebPInitDecoderConfig(ref config) == 0) //{ // throw new Exception("WebPInitDecoderConfig failed. Wrong version?"); //} NativeLibwebpdemux.WebPAnimDecoderOptionsInit(&option); fixed(byte *p = bytes) { WebPData webpdata = new WebPData { bytes = p, size = new UIntPtr((uint)bytes.Length) }; WebPAnimDecoderOptions opt = new WebPAnimDecoderOptions(); NativeLibwebpdemux.WebPAnimDecoderOptionsInit(&opt); WebPAnimDecoder *webPAnimDecoderPtr = NativeLibwebpdemux.WebPAnimDecoderNewInternal(&webpdata, &opt, NativeLibwebpdemux.WEBP_DEMUX_ABI_VERSION); //int width = 400; //int height = 400; { //config.input.has_alpha = 1; //config.options.bypass_filtering = 1; //config.options.no_fancy_upsampling = 1; config.options.use_threads = 1; //config.options.no_fancy_upsampling = 0; //config.options.use_cropping = 0; //config.options.use_scaling = 1; //config.options.scaled_width = width; //config.options.scaled_height = height; config.options.flip = 1; //config.options.dithering_strength = 100; config.output.colorspace = (unity.libwebp.Interop.WEBP_CSP_MODE)WEBP_CSP_MODE.MODE_RGBA; //config.output.is_external_memory = 1; //config.output.width = width; //config.output.height = height; } webPAnimDecoderPtr->config_ = config; WebPAnimInfo anim_info = new WebPAnimInfo(); NativeLibwebpdemux.WebPAnimDecoderGetInfo(webPAnimDecoderPtr, &anim_info); Debug.LogWarning($"{anim_info.frame_count} {anim_info.canvas_width}/{anim_info.canvas_height}"); int size = (int)anim_info.canvas_width * 4 * (int)anim_info.canvas_height; int timestamp = 0; IntPtr pp = new IntPtr(); byte **unmanagedPointer = (byte **)&pp; for (int i = 0; i < anim_info.frame_count; ++i) { int result = NativeLibwebpdemux.WebPAnimDecoderGetNext(webPAnimDecoderPtr, unmanagedPointer, ×tamp); int lWidth = (int)anim_info.canvas_width; int lHeight = (int)anim_info.canvas_height; bool lMipmaps = false; bool lLinear = false; Texture2D texture = Texture2DExt.CreateWebpTexture2D(lWidth, lHeight, lMipmaps, lLinear); texture.LoadRawTextureData((IntPtr)unmanagedPointer, size); texture.Apply(updateMipmaps: false, makeNoLongerReadable: true); ret.Add((texture, timestamp)); } NativeLibwebpdemux.WebPAnimDecoderReset(webPAnimDecoderPtr); NativeLibwebpdemux.WebPAnimDecoderDelete(webPAnimDecoderPtr); } return(ret); }
unsafe List <(Texture2D, int)> LoadAnimation(string loadPath) { List <ValueTuple <Texture2D, int> > ret = new List <ValueTuple <Texture2D, int> >(); TextAsset textasset = Resources.Load <TextAsset>(loadPath); byte[] bytes = textasset.bytes; WebPAnimDecoderOptions option = new WebPAnimDecoderOptions { use_threads = 1, color_mode = WEBP_CSP_MODE.MODE_RGBA }; Demux.WebPAnimDecoderOptionsInit(ref option); fixed(byte *p = bytes) { IntPtr ptr = (IntPtr)p; WebPData webpdata = new WebPData { bytes = ptr, size = new UIntPtr((uint)bytes.Length) }; IntPtr dec = Demux.WebPAnimDecoderNew(ref webpdata, ref option); WebPAnimInfo anim_info = new WebPAnimInfo(); Demux.WebPAnimDecoderGetInfo(dec, ref anim_info); Debug.LogWarning($"{anim_info.frame_count} {anim_info.canvas_width}/{anim_info.canvas_height}"); int size = anim_info.canvas_width * 4 * anim_info.canvas_height; WebPAnimDecoder decoder = (WebPAnimDecoder)Marshal.PtrToStructure(dec, typeof(WebPAnimDecoder)); decoder.config_.options.flip = 1; decoder.config_.options.no_fancy_upsampling = 1; Marshal.StructureToPtr(decoder, dec, true); IntPtr unmanagedPointer = new IntPtr(); int timestamp = 0; for (int i = 0; i < anim_info.frame_count; ++i) { int result = Demux.WebPAnimDecoderGetNext(dec, ref unmanagedPointer, ref timestamp); if (result != 1) { Debug.LogError("WTF"); } int lWidth = anim_info.canvas_width; int lHeight = anim_info.canvas_height; bool lMipmaps = false; bool lLinear = false; Texture2D texture = new Texture2D(lWidth, lHeight, TextureFormat.RGBA32, lMipmaps, lLinear); texture.LoadRawTextureData(unmanagedPointer, size); texture.Apply(updateMipmaps: false, makeNoLongerReadable: true); ret.Add((texture, timestamp)); } Demux.WebPAnimDecoderReset(dec); Demux.WebPAnimDecoderDelete(dec); } return(ret); }
unsafe List <(Texture2D, int)> LoadAnimation3(string loadPath) { List <ValueTuple <Texture2D, int> > ret = new List <ValueTuple <Texture2D, int> >(); TextAsset textasset = Resources.Load <TextAsset>(loadPath); byte[] bytes = textasset.bytes; WebPAnimDecoderOptions option = new WebPAnimDecoderOptions { use_threads = 1, color_mode = WEBP_CSP_MODE.MODE_RGBA }; var config = new WebPDecoderConfig(); if (Decode.WebPInitDecoderConfig(ref config) == 0) { throw new Exception("WebPInitDecoderConfig failed. Wrong version?"); } Demux.WebPAnimDecoderOptionsInit(ref option); fixed(byte *p = bytes) { IntPtr ptr = (IntPtr)p; var webpdata = new WebPData { bytes = ptr, size = new UIntPtr((uint)bytes.Length) }; WebPAnimDecoderOptions opt = new WebPAnimDecoderOptions(); Demux.WebPAnimDecoderOptionsInit(ref opt); IntPtr webPAnimDecoderPtr = Demux.WebPAnimDecoderNewInternal(ref webpdata, ref opt, Demux.WEBP_DEMUX_ABI_VERSION); Debug.Log($"webPAnimDecoderPtr = {webPAnimDecoderPtr}"); WebPAnimDecoder decoder = (WebPAnimDecoder)Marshal.PtrToStructure(webPAnimDecoderPtr, typeof(WebPAnimDecoder)); //int width = 400; //int height = 400; { //config.input.has_alpha = 1; //config.options.bypass_filtering = 1; //config.options.no_fancy_upsampling = 1; config.options.use_threads = 1; //config.options.no_fancy_upsampling = 0; //config.options.use_cropping = 0; //config.options.use_scaling = 1; //config.options.scaled_width = width; //config.options.scaled_height = height; config.options.flip = 1; //config.options.dithering_strength = 100; config.output.colorspace = WEBP_CSP_MODE.MODE_RGBA; //config.output.is_external_memory = 1; //config.output.width = width; //config.output.height = height; } decoder.config_ = config; Marshal.StructureToPtr(decoder, webPAnimDecoderPtr, true); IntPtr dec = webPAnimDecoderPtr; WebPAnimInfo anim_info = new WebPAnimInfo(); Demux.WebPAnimDecoderGetInfo(dec, ref anim_info); Debug.LogWarning($"{anim_info.frame_count} {anim_info.canvas_width}/{anim_info.canvas_height}"); int size = anim_info.canvas_width * 4 * anim_info.canvas_height; IntPtr unmanagedPointer = new IntPtr(); int timestamp = 0; for (int i = 0; i < anim_info.frame_count; ++i) { int result = Demux.WebPAnimDecoderGetNext(dec, ref unmanagedPointer, ref timestamp); int lWidth = anim_info.canvas_width; int lHeight = anim_info.canvas_height; bool lMipmaps = false; bool lLinear = false; Texture2D texture = new Texture2D(lWidth, lHeight, TextureFormat.RGBA32, lMipmaps, lLinear); texture.LoadRawTextureData(unmanagedPointer, size); texture.Apply(updateMipmaps: false, makeNoLongerReadable: true); ret.Add((texture, timestamp)); } Demux.WebPAnimDecoderReset(dec); Demux.WebPAnimDecoderDelete(dec); } return(ret); }