예제 #1
0
        public static string GetDecoderVersion()
        {
            uint v        = (uint)NativeLibwebp.WebPGetDecoderVersion();
            uint revision = v % 256;
            uint minor    = (v >> 8) % 256;
            uint major    = (v >> 16) % 256;

            return($"{major}.{minor}.{revision}");
        }
예제 #2
0
        /// <summary>
        ///
        /// </summary>
        /// <param name="lTexture2D"></param>
        /// <param name="lError"></param>
        /// <returns></returns>
        public static unsafe byte[] EncodeToWebP(this Texture2D lTexture2D, float lQuality, out Error lError)
        {
            lError = 0;

            if (lQuality < -1)
            {
                lQuality = -1;
            }
            if (lQuality > 100)
            {
                lQuality = 100;
            }

            Color32[] lRawColorData = lTexture2D.GetPixels32();
            int       lWidth        = lTexture2D.width;
            int       lHeight       = lTexture2D.height;

            IntPtr   lResult      = new IntPtr();
            byte **  pResult      = (byte **)&lResult;
            GCHandle lPinnedArray = GCHandle.Alloc(lRawColorData, GCHandleType.Pinned);
            IntPtr   lRawDataPtr  = lPinnedArray.AddrOfPinnedObject();

            byte[] lOutputBuffer = null;

            try
            {
                int lLength;

                if (lQuality == -1)
                {
                    lLength = (int)NativeLibwebp.WebPEncodeLosslessRGBA((byte *)lRawDataPtr, lWidth, lHeight, 4 * lWidth, pResult);
                }
                else
                {
                    lLength = (int)NativeLibwebp.WebPEncodeRGBA((byte *)lRawDataPtr, lWidth, lHeight, 4 * lWidth, lQuality, pResult);
                }

                if (lLength == 0)
                {
                    throw new Exception("WebP encode failed!");
                }

                lOutputBuffer = new byte[lLength];
                Marshal.Copy(lResult, lOutputBuffer, 0, lLength);
            }
            finally
            {
                NativeLibwebp.WebPSafeFree(*pResult);
            }

            lPinnedArray.Free();

            return(lOutputBuffer);
        }
예제 #3
0
        /// <summary>
        /// Gets dimensions from a webp format block of data.
        /// </summary>
        /// <param name="lData">L data.</param>
        /// <param name="lWidth">L width.</param>
        /// <param name="lHeight">L height.</param>
        public static unsafe void GetWebPDimensions(byte[] lData, out int lWidth, out int lHeight)
        {
            fixed(byte *lDataPtr = lData)
            {
                int w;
                int h;

                lWidth  = 0;
                lHeight = 0;
                if (NativeLibwebp.WebPGetInfo(lDataPtr, (UIntPtr)lData.Length, &w, &h) == 0)
                {
                    throw new Exception("Invalid WebP header detected");
                }
                lWidth  = w;
                lHeight = h;
            }
        }
예제 #4
0
        public static unsafe void LoadTexture2DFromWebP(byte[] webpBytes, Texture2D texture, bool lMipmaps, bool lLinear, byte[] bytePool, int numBytesRequired, ScalingFunction scalingFunction = null)
        {
            Debug.Assert(bytePool.Length >= numBytesRequired);
            Array.Clear(bytePool, 0, numBytesRequired);

            int width  = texture.width;
            int height = texture.height;

            fixed(byte *lDataPtr = webpBytes)
            {
                fixed(byte *lRawDataPtr = bytePool)
                {
                    int lStride = 4 * width;

                    // As we have to reverse the y order of the data, we pass through a negative stride and
                    // pass through a pointer to the last line of the data.
                    byte *lTmpDataPtr = lRawDataPtr + (height - 1) * lStride;

                    WebPDecoderConfig config = new WebPDecoderConfig();

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

                    // Set up decode options
                    config.options.use_threads = 1;
                    if (scalingFunction != null)
                    {
                        config.options.use_scaling = 1;
                    }
                    config.options.scaled_width  = width;
                    config.options.scaled_height = height;

                    // read the .webp input file information
                    VP8StatusCode result = NativeLibwebp.WebPGetFeatures(lDataPtr, (UIntPtr)webpBytes.Length, &config.input);

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

                    // specify the output format
                    config.output.colorspace         = WEBP_CSP_MODE.MODE_RGBA;
                    config.output.u.RGBA.rgba        = lTmpDataPtr;
                    config.output.u.RGBA.stride      = -lStride;
                    config.output.u.RGBA.size        = (UIntPtr)(height * lStride);
                    config.output.height             = height;
                    config.output.width              = width;
                    config.output.is_external_memory = 1;

                    // Decode
                    result = NativeLibwebp.WebPDecode(lDataPtr, (UIntPtr)webpBytes.Length, &config);
                    if (result != VP8StatusCode.VP8_STATUS_OK)
                    {
                        throw new Exception(string.Format("Failed WebPDecode with error {0}.", result.ToString()));
                    }

                    texture.LoadRawTextureData((IntPtr)lRawDataPtr, numBytesRequired);
                    texture.Apply(lMipmaps, true);
                }
            }
        }
예제 #5
0
        /// <summary>
        /// Loads an image from webp into a byte array in RGBA format.
        /// </summary>
        /// <returns>The RGBA from web p.</returns>
        /// <param name="lData">L data.</param>
        /// <param name="lWidth">L width.</param>
        /// <param name="lHeight">L height.</param>
        /// <param name="lMipmaps">If set to <c>true</c> l mipmaps.</param>
        /// <param name="lError">L error.</param>
        /// <param name="scalingFunction">Scaling function.</param>
        public static unsafe byte[] LoadRGBAFromWebP(byte[] lData, ref int lWidth, ref int lHeight, bool lMipmaps, out Error lError, ScalingFunction scalingFunction = null)
        {
            lError = 0;
            byte[] lRawData = null;
            int    lLength  = lData.Length;

            fixed(byte *lDataPtr = lData)
            {
                // If we've been supplied a function to alter the width and height, use that now.
                scalingFunction?.Invoke(ref lWidth, ref lHeight);

                // If mipmaps are requested we need to create 1/3 more memory for the mipmaps to be generated in.
                int numBytesRequired = lWidth * lHeight * 4;

                if (lMipmaps)
                {
                    numBytesRequired = Mathf.CeilToInt((numBytesRequired * 4.0f) / 3.0f);
                }

                lRawData = new byte[numBytesRequired];
                fixed(byte *lRawDataPtr = lRawData)
                {
                    int lStride = 4 * lWidth;

                    // As we have to reverse the y order of the data, we pass through a negative stride and
                    // pass through a pointer to the last line of the data.
                    byte *lTmpDataPtr = lRawDataPtr + (lHeight - 1) * lStride;

                    WebPDecoderConfig config = new WebPDecoderConfig();

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

                    // Set up decode options
                    config.options.use_threads = 1;
                    if (scalingFunction != null)
                    {
                        config.options.use_scaling = 1;
                    }
                    config.options.scaled_width  = lWidth;
                    config.options.scaled_height = lHeight;

                    // read the .webp input file information
                    VP8StatusCode result = NativeLibwebp.WebPGetFeatures(lDataPtr, (UIntPtr)lLength, &config.input);

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

                    // specify the output format
                    config.output.colorspace         = WEBP_CSP_MODE.MODE_RGBA;
                    config.output.u.RGBA.rgba        = lTmpDataPtr;
                    config.output.u.RGBA.stride      = -lStride;
                    config.output.u.RGBA.size        = (UIntPtr)(lHeight * lStride);
                    config.output.height             = lHeight;
                    config.output.width              = lWidth;
                    config.output.is_external_memory = 1;

                    // Decode
                    result = NativeLibwebp.WebPDecode(lDataPtr, (UIntPtr)lLength, &config);
                    if (result != VP8StatusCode.VP8_STATUS_OK)
                    {
                        throw new Exception(string.Format("Failed WebPDecode with error {0}.", result.ToString()));
                    }
                }

                lError = Error.Success;
            }

            return(lRawData);
        }
예제 #6
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);
    }