只是为了测试我(从通过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
增长由要素59kb
到1,475
左右。这同样适用于更大的文件,这样一844kb
growed到1,02Mb
。
所以我的问题是
为什么EncodeToPNG()
比原始图像后上传的图片更大?
和
是否有可能/应该在PNG数据,以便存档相同的压缩级别(如果压缩是问题的话)所使用的任何压缩?
首先,我想,也许不同的颜色深度,但两个图像RGBA,32位
更新
这里有两个图像
原始(40KB)(来自here截取)
重新上传(59KB)
更新2
我反复试了JPG文件和EncodeToJPG()
和结果似乎更糟糕:
顶部的原始图像;在底部重新上传一个。
这一次,它从27kb
去98kb
这样的因素2,63
。奇怪的文件大小也是恒定的98kb
不管我把作为quality
参数EncodeToJPG()
。
如果你正是这两个检查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
流给出了以下结果:
这就解释了在二进制数据和数据大小的差异。
看来你有过统一的PNG编码器无法控制,所以很遗憾你不能强迫它选择另一个zlib
算法。
我想,同样的情况与JPEG文件 - 编码器只是选择了一个更快的算法,产生较大的文件。
如果你想在PNG编码在统一的完全控制,你需要实现自己的PNG编码器。例如。 here on Unity forum,有这样一个使用zlib.net
库PNG编码器的样品。您可以微调的编码如通过指定zlib
压缩算法。
阅读here看来,虽然您可以导入PNG,你实际上在你的项目中成为一个纹理或精灵文件根据,而这增加的数据增加它的大小。你所看到的来附加字节由编辑器连接到PNG信息,以简化统一; S加载过程,并允许您设置导入不同的选项。文件大小可以在此基础上设置您选择彻底改变。