Пример #1
0
        /// <summary>
        /// 从指向非托管内存空间的WebPData指针解码
        /// </summary>
        /// <param name="webPDataPointer"></param>
        /// <returns></returns>
        public WebPAnimation DecodeFromWebPDataPointer(IntPtr webPDataPointer)
        {
            //解调WebP数据以提取所有帧、ICC配置文件和EXIF / XMP元数据
            IntPtr demux = LibwebpdemuxUtils.WebPDemuxInternal(webPDataPointer, 0, IntPtr.Zero, Version);

            //创建迭代器,用来遍历动画的每一帧
            WebPIterator iter = new WebPIterator();
            //创建指向迭代器的指针
            IntPtr ptrIter = Marshal.AllocHGlobal(Marshal.SizeOf(iter));

            //给迭代器指针赋初值
            Marshal.StructureToPtr(iter, ptrIter, true);
            //初始化WebP动画结构体,这是本函数要返回的结果
            WebPAnimation animation = new WebPAnimation();

            //遍历所有帧
            if (LibwebpdemuxUtils.WebPDemuxGetFrame(demux, 1, ptrIter) != 0)
            {
                //如果成功获取了第一帧,就创建一个简单解码器
                SimpleDecoder simpleDecoder = new SimpleDecoder();
                do
                {
                    //解引用迭代器指针,恢复出迭代器对象
                    iter = Marshal.PtrToStructure <WebPIterator>(ptrIter);
                    //创建一个动画帧对象
                    WebPAnimationFrame frame = new WebPAnimationFrame();
                    //将迭代器中获得的数据存入动画帧对象中
                    frame.Complete = Convert.ToBoolean(iter.complete);
                    frame.Duration = iter.duration;
                    frame.HasAlpha = Convert.ToBoolean(iter.has_alpha);
                    frame.Height   = iter.height;
                    frame.Width    = iter.width;
                    frame.XOffset  = iter.x_offset;
                    frame.YOffset  = iter.y_offset;
                    frame.Image    = simpleDecoder.DecodeFromPointer(iter.fragment.bytes, (long)iter.fragment.size);
                    //将动画帧添加到动画对象中
                    animation.Frames.Add(frame);
                } while (LibwebpdemuxUtils.WebPDemuxNextFrame(ptrIter) != 0);
                //释放迭代器
                LibwebpdemuxUtils.WebPDemuxReleaseIterator(ptrIter);
            }
            //释放之前申请的非托管内存空间
            Marshal.FreeHGlobal(ptrIter);
            //指针置为0
            ptrIter = IntPtr.Zero;
            //返回动画对象
            return(animation);
        }
Пример #2
0
    private unsafe List <(Texture2D, int)> LoadAnimation2(string loadPath)
    {
        List <ValueTuple <Texture2D, int> > ret = new List <ValueTuple <Texture2D, int> >();

        TextAsset textasset = Resources.Load <TextAsset>(loadPath);

        byte[] bytes = textasset.bytes;

        WebPDecoderConfig config = new WebPDecoderConfig();

        if (NativeLibwebp.WebPInitDecoderConfig(&config) == 0)
        {
            throw new Exception("WebPInitDecoderConfig failed. Wrong version?");
        }

        WebPIterator iter = new WebPIterator();

        fixed(byte *p = bytes)
        {
            WebPData webpdata = new WebPData
            {
                bytes = p,
                size  = new UIntPtr((uint)bytes.Length)
            };
            WebPDemuxer *webPDemuxer = NativeLibwebpdemux.WebPDemuxInternal(&webpdata, 0, (WebPDemuxState *)IntPtr.Zero, NativeLibwebpdemux.WEBP_DEMUX_ABI_VERSION);

            VP8StatusCode result = NativeLibwebp.WebPGetFeatures(webpdata.bytes, webpdata.size, &config.input);

            if (result != VP8StatusCode.VP8_STATUS_OK)
            {
                throw new Exception(string.Format("Failed WebPGetFeatures with error {0}.", result.ToString()));
            }

            int height = config.input.height;
            int width  = config.input.height;

            config.options.bypass_filtering    = 0;
            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 = 0;
            config.output.colorspace          = WEBP_CSP_MODE.MODE_RGBA;
            config.output.width  = width;
            config.output.height = height;

            //byte[] bbb = new byte[width * height];
            //fixed (byte* ppp = bbb)
            //{
            //    config.output.u.RGBA.rgba = (IntPtr)ppp;
            //}
            //config.output.u.RGBA.stride = width * 4;
            //config.output.u.RGBA.size = (UIntPtr)(width * height);
            //config.output.is_external_memory = 1;
            //config.output.is_external_memory = 1;

            int success = NativeLibwebpdemux.WebPDemuxGetFrame(webPDemuxer, 1, &iter);

            if (success != 1)
            {
                return(ret);
            }

            int timestamp = 0;
            int size      = width * height * 4;

            do
            {
                WebPData      frame  = iter.fragment;
                VP8StatusCode status = NativeLibwebp.WebPDecode(frame.bytes, frame.size, &config);
                if (status != VP8StatusCode.VP8_STATUS_OK)
                {
                    Debug.LogError(status);
                    break;
                }

                Texture2D texture = Texture2DExt.CreateWebpTexture2D(width, height, isUseMipmap: false, isLinear: false);
                texture.LoadRawTextureData((IntPtr)config.output.u.RGBA.rgba, size);
                texture.Apply(updateMipmaps: false, makeNoLongerReadable: true);
                timestamp += iter.duration;
                ret.Add((texture, timestamp));
            }while (NativeLibwebpdemux.WebPDemuxNextFrame(&iter) == 1);

            NativeLibwebpdemux.WebPDemuxDelete(webPDemuxer);
            NativeLibwebpdemux.WebPDemuxReleaseIterator(&iter);
        }

        return(ret);
    }
Пример #3
0
 public static extern void WebPDemuxReleaseIterator(ref WebPIterator dec);
Пример #4
0
    private unsafe List <(Texture2D, int)> LoadAnimation2(string loadPath)
    {
        List <ValueTuple <Texture2D, int> > ret = new List <ValueTuple <Texture2D, int> >();

        TextAsset textasset = Resources.Load <TextAsset>(loadPath);

        byte[] bytes = textasset.bytes;

        var config = new WebPDecoderConfig();

        if (Decode.WebPInitDecoderConfig(ref config) == 0)
        {
            throw new Exception("WebPInitDecoderConfig failed. Wrong version?");
        }

        var    iter        = new WebPIterator();
        IntPtr webpDataPtr = Marshal.AllocHGlobal(sizeof(WebPData));
        IntPtr configPtr   = Marshal.AllocHGlobal(Marshal.SizeOf(config));
        IntPtr iterPtr     = Marshal.AllocHGlobal(Marshal.SizeOf(iter));

        try
        {
            fixed(byte *p = bytes)
            {
                IntPtr   ptr      = (IntPtr)p;
                WebPData webpdata = new WebPData
                {
                    bytes = ptr,
                    size  = new UIntPtr((uint)bytes.Length)
                };

                Marshal.StructureToPtr(webpdata, webpDataPtr, false);
                Marshal.StructureToPtr(config, configPtr, false);
                Marshal.StructureToPtr(iter, iterPtr, false);
                IntPtr webPDemuxer = Demux.WebPDemuxInternal(webpDataPtr, 0, (IntPtr)0, Demux.WEBP_DEMUX_ABI_VERSION);

                VP8StatusCode result = Decode.WebPGetFeatures(webpdata.bytes, webpdata.size, ref config.input);

                if (result != VP8StatusCode.VP8_STATUS_OK)
                {
                    throw new Exception(string.Format("Failed WebPGetFeatures with error {0}.", result.ToString()));
                }

                var height = config.input.height;
                var width  = config.input.height;

                config.options.bypass_filtering    = 0;
                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 = 0;
                config.output.colorspace          = WEBP_CSP_MODE.MODE_RGBA;
                config.output.width  = width;
                config.output.height = height;

                //byte[] bbb = new byte[width * height];
                //fixed (byte* ppp = bbb)
                //{
                //    config.output.u.RGBA.rgba = (IntPtr)ppp;
                //}
                //config.output.u.RGBA.stride = width * 4;
                //config.output.u.RGBA.size = (UIntPtr)(width * height);
                //config.output.is_external_memory = 1;
                //config.output.is_external_memory = 1;

                int success = Demux.WebPDemuxGetFrame(webPDemuxer, 1, ref iter);

                if (success != 1)
                {
                    return(ret);
                }

                int timestamp = 0;
                int size      = width * height * 4;

                do
                {
                    WebPData      frame  = iter.fragment;
                    VP8StatusCode status = Decode.WebPDecode(frame.bytes, frame.size, ref config);
                    if (status != VP8StatusCode.VP8_STATUS_OK)
                    {
                        Debug.LogError(status);
                        break;
                    }

                    var texture = new Texture2D(width, height, TextureFormat.RGBA32, mipChain: false, linear: false);
                    texture.LoadRawTextureData(config.output.u.RGBA.rgba, size);
                    texture.Apply(updateMipmaps: false, makeNoLongerReadable: true);
                    timestamp += iter.duration;
                    ret.Add((texture, timestamp));
                }while (Demux.WebPDemuxNextFrame(ref iter) == 1);

                Demux.WebPDemuxDelete(webPDemuxer);
                Demux.WebPDemuxReleaseIterator(ref iter);
            }
        }
        finally
        {
            Marshal.FreeHGlobal(webpDataPtr);
            Marshal.FreeHGlobal(configPtr);
            Marshal.FreeHGlobal(iterPtr);
        }

        return(ret);
    }