PNG文件增长在Unity应用下载质感后转换回PNG通过EncodeToPNG

问题描述 投票:8回答:2

只是为了测试我(从通过API一个JIRA服务器在这种情况下)下载通过HTTP PNG文件

对于HTTP请求我有一个相当“非标准”类HttpFileManager我只需要添加的完整性:

public static class HttpFileManager
{

    public void DownloadImage(string url, Action<Texture> successCallback = null, Credentials credentials = null, Action<UnityWebRequest> errorCallback = null)
    {
        StartCoroutine(DownloadImageProcess(url, successCallback, credentials, errorCallback));
    }

    private static IEnumerator DownloadImageProcess(string url, Action<Texture> successCallback, Credentials credentials, Action<UnityWebRequest> errorCallback)
    {
        var www = UnityWebRequestTexture.GetTexture(url);

        if (credentials != null)
        {
            // This simply adds some headers to the request required for JIRA api
            // it is not relevant for this question
            AddCredentials(www, credentials);
        }

        yield return www.SendWebRequest();

        if (www.isNetworkError || www.isHttpError)
        {
            Debug.LogErrorFormat("Download from {0} failed with {1}", url, www.error);
            errorCallback?.Invoke(www);
        }
        else
        {
            Debug.LogFormat("Download from {0} complete!", url);
            successCallback?.Invoke(((DownloadHandlerTexture) www.downloadHandler).texture);
        }
    }

    public static void UploadFile(byte[] rawData, string url, Action<UnityWebRequest> successcallback, Credentials credentials, Action<UnityWebRequest> errorCallback)

    private static IEnumerator UploadFileProcess(byte[] rawData, string url, Action<UnityWebRequest> successCallback, Credentials credentials, Action<UnityWebRequest> errorCallback)
    {
        var form = new WWWForm();
        form.AddBinaryData("file",rawData,"Test.png");

        var www = UnityWebRequest.Post(url, form);

        www.SetRequestHeader("Accept", "application/json");

        if (credentials != null)
        {
            // This simply adds some headers to the request required for JIRA api
            // it is not relevant for this question
            AddCredentials(www, credentials);
        }

        yield return www.SendWebRequest();

        if (www.isNetworkError || www.isHttpError)
        {
            Debug.LogErrorFormat("Upload to {0} failed with code {1} {2}", url, www.responseCode, www.error);
            errorCallback?.Invoke(www);
        }
        else
        {
            Debug.LogFormat("Upload to {0} complete!", url);
            successCallback?.Invoke(www);
        }
    }
}

后来在我的剧本我做

public Texture TestTexture;

// Begin the download
public void DownloadTestImage()
{
    _httpFileManager.DownloadImage(ImageGetURL, DownloadImageSuccessCallback, _credentials);
}

// After Download store the Texture
private void DownloadImageSuccessCallback(Texture newTexture)
{
    TestTexture = newTexture;
}

// Start the upload
public void UploadTestImage()
{
    var data = ((Texture2D) TestTexture).EncodeToPNG();

    _httpFileManager.UploadFile(data, ImagePostUrl, UploadSuccessCallback, _credentials);
}

// After Uploading
private static void UploadSuccessCallback(UnityWebRequest www)
{
    Debug.Log("Upload worked!");
}

在简历的问题就出在了后面,并在转换

(DownloadHandlerTexture) www.downloadHandler).texture

((Texture2D) TestTexture).EncodeToPNG();

结果看起来是这样的

顶部的原始图像;在底部重新上传一个。

正如你可以看到它从40kb增长由要素59kb1,475左右。这同样适用于更大的文件,这样一844kb growed到1,02Mb

所以我的问题是

为什么EncodeToPNG()比原始图像后上传的图片更大?

是否有可能/应该在PNG数据,以便存档相同的压缩级别(如果压缩是问题的话)所使用的任何压缩?

首先,我想,也许不同的颜色深度,但两个图像RGBA,32位

enter image description here


更新

这里有两个图像

原始(40KB)(来自here截取)

enter image description here

重新上传(59KB)

enter image description here


更新2

我反复试了JPG文件和EncodeToJPG()和结果似乎更糟糕:

enter image description here

顶部的原始图像;在底部重新上传一个。

这一次,它从27kb98kb这样的因素2,63。奇怪的文件大小也是恒定的98kb不管我把作为quality参数EncodeToJPG()

c# image unity3d encoding
2个回答
9
投票

如果你正是这两个检查PNG文件,你会发现其中的差别。他们都具有相同的分辨率,相同的位深度,一些数量的通道,并且都没有交错。

然而,在原始图像中只包含一个保持41370个字节的编码数据的IDAT section

图像从Unity始发包含8个IDAT部分:7×8192字节,一个字节2860,共60204个字节。

在PNG规范,还有一张纸条:

多个IDAT组块被允许,从而编码器可在存储器的固定量工作;典型地,块大小将对应于编码器的缓冲器大小。

此外,包含在那些IDAT部分中的数据不一定精确对于相同的源图像中的相同。那些IDAT部分保持这是第一pre-filtered然后encoded使用zlib压缩原始字节的数据。

所以,PNG编码器可以选择5级,可用的前置滤波算法:

Type    Name

0       None
1       Sub
2       Up
3       Average
4       Paeth

此外,该压缩zlib可以被配置为压缩窗口大小,这也可以通过在编码器PNG选择。

检查zlib流给出了以下结果:

  • 这两个文件使用“放气”有相同的窗口大小32K压缩
  • 压缩标志,然而,不同的 - 原始文件具有压缩级别1(快速算法),而统一编码文件具有压缩级别0(最快的算法)。

这就解释了在二进制数据和数据大小的差异。

看来你有过统一的PNG编码器无法控制,所以很遗憾你不能强迫它选择另一个zlib算法。

我想,同样的情况与JPEG文件 - 编码器只是选择了一个更快的算法,产生较大的文件。

如果你想在PNG编码在统一的完全控制,你需要实现自己的PNG编码器。例如。 here on Unity forum,有这样一个使用zlib.net库PNG编码器的样品。您可以微调的编码如通过指定zlib压缩算法。


0
投票

阅读here看来,虽然您可以导入PNG,你实际上在你的项目中成为一个纹理或精灵文件根据,而这增加的数据增加它的大小。你所看到的来附加字节由编辑器连接到PNG信息,以简化统一; S加载过程,并允许您设置导入不同的选项。文件大小可以在此基础上设置您选择彻底改变。

© www.soinside.com 2019 - 2024. All rights reserved.