netpyoung / unity.webp

:art: WebP made easy for Unity3d
https://netpyoung.github.io/unity.webp/
MIT License
237 stars 28 forks source link

How to resolve an issue that decodes correctly on iPad but not on Windows? #55

Closed Maru-prono closed 1 year ago

Maru-prono commented 1 year ago

Hi,

I'm trying to encode Texture2D from a photo taken on an iPad, communicate to a PC with Windows and decode the byte array data.

On the iPad, the image can be decoded correctly, but on the Windows side, is failed. The failed image's pixel information is (205,205,205,205).

I want to decode correctly the data received on the Windows side.

commuImage

I programed to encode and decode Texture2D.

[ iPad side ]

// Source Texture to Encode WebP.
            Texture2D srcTexture = capturedTexture;
            /// srcTexture's infomation
            /// width :960
            /// height:720
            /// format:RGBA32
            /// GraphicsFormat:R8G8B8A8_UNorm
            /// wrapMode:Repeat

            // Encode srcTexture.
            byte[] byteArray = srcTexture.EncodeToWebP(80, out Error lError);
            if (lError != Error.Success)
            {
                Debug.LogError("Webp EncodeToWebP Error : " + lError.ToString());
                yield return null;
            }

            // Communicate byteArray to WindowsPC.
            client.Send(byteArray);

            // Decode byteArray on iPad.
            Texture2D decodeTexture_iPad = Texture2DExt.CreateTexture2DFromWebP(byteArray, false, false, out Error decodeError);
            if (decodeError != Error.Success)
            {
                Debug.LogError("Webp EncodeToWebP Error : " + decodeError.ToString());
                yield return null;
            }
            Texture2D colorTexture = new Texture2D(decodeTexture_iPad.width, decodeTexture_iPad.height);
            colorTexture.ReadPixels(new UnityEngine.Rect(0, 0, colorTexture.width, colorTexture.height), 0, 0);
            colorTexture.Apply();

            // Show texture.
            rawImage.texture = colorTexture;
            /// Success Decode.
            /// Texture's Information
            /// width :960
            /// height:720
            /// format:RGBA32
            /// GraphicsFormat:R8G8B8A8_UNorm
            /// wrapMode:Repeat

[ Windows Side ]

// Receive byteArray from iPad.
        byte[] receivedByteArray = client.Receive(byteArray);

        //  Decode byteArray on Windows.
        Texture2D decodeTexture_Windows = Texture2DExt.CreateTexture2DFromWebP(receivedByteArray, false, false, out var colorError);
        Texture2D colorTexture = new Texture2D(decodeTexture_Windows.width, decodeTexture_Windows.height);
        colorTexture.ReadPixels(new UnityEngine.Rect(0, 0, colorTexture.width, colorTexture.height), 0, 0);
        colorTexture.Apply();

        // Show texture.
        rawImage.texture = colorTexture;
        /// Failed Decode.
        /// Pixel Data:[205, 205, 205, 205]
        /// Texture's Information
        /// width :960
        /// height:720
        /// format:RGBA32
        /// GraphicsFormat:R8G8B8A8_UNorm
        /// wrapMode:Repeat

I attempted to decode using the same approach, but it fails only on Windows.

The following was confirmed.

  1. Encoded data is being sent and received without loss.
  2. Width, height, and format matched whichever decoded.

If information is missing, I will add it. Please can someone help with this.

Thanks,

Maru

netpyoung commented 1 year ago

To reproduce and testing that butg on my windows pc, I need following data. Could you attech that files on via comment?

  1. iPad side - srcTexture's bytes via GetRawTextureData
  2. iPad side - byteArray's bytes
  3. Windows Side - receivedByteArray bytes
  4. Windows Side - decodeTexture_Windows 's bytes via GetRawTextureData
Maru-prono commented 1 year ago

Thanks for your reply.

They are output files. The output byte array is output to a text file separated by ",".

[iPad side - srcTexture's bytes via GetRawTextureData (636KB)] 1_ipadSide_RawData.txt

[iPad side - byteArray's bytes (5KB)] 2_ipadSide_encodeData.txt

[Windows Side - receivedByteArray bytes (5KB)] 3_WindowsSide_byteData.txt

[Windows Side - decodeTexture_Windows 's bytes via GetRawTextureData (14,344KB)] 4_WindowsSide_RawData.txt

netpyoung commented 1 year ago

I checked images except 1

I failed to check 1_ipadSide_RawData's image via unity. (UnityException: LoadRawTextureData: not enough data provided (will result in overread).)

Could you attach original image what you want to convert webp?

// here is what i used for test

    public RawImage RawImage;
    Texture2D texture;

    // Start is called before the first frame update
    void Start()
    {
        TextAsset RawData = Resources.Load<TextAsset>("1_ipadSide_RawData");
        // TextAsset RawData = Resources.Load<TextAsset>("4_WindowsSide_RawData");

        string text = RawData.text;
        string[] splited = text.Split(",");
        byte[] srcTextureBytes = splited.Select(x => byte.Parse(x)).ToArray();
        // texture = new Texture2D(960, 720, TextureFormat.RGBA32, mipChain: false, linear: true);
        texture = new Texture2D(960, 720, format: GraphicsFormat.R8G8B8A8_UNorm, flags: TextureCreationFlags.None);

        texture.LoadRawTextureData(srcTextureBytes);
        texture.Apply();
        RawImage.texture = texture;
    }
Maru-prono commented 1 year ago

Attach both the photo you want to retrieve and 4 new data. When the 2 image is decoded on the iPad, it will be displayed in RawImage.

webp_sample.zip

netpyoung commented 1 year ago

I'm not sure but what suspicious thing is Texture2D srcTexture = capturedTexture;

I don't know why rawImage.texture = colorTexture; rendered well. but I think srcTexture's GetPixels32 function returns gray image.

If capturedTexture created by renderTexture, It can be bring incorrect color without apply.

Maru-prono commented 1 year ago

I solved this problem. It was not with the WebP encoding, but with the input image.

It was that the image had been scaled before encoding, and the RawData was incorrectly processed. When we ran the program without the scaling process, it decoded correctly. It was not a WebP issue.

I'm sorry for taking up so much of your time, and thank you for the great tips. I will use this plugin in the future.

Best regards,

Maru