Просто для тестирования я скачал файл PNG через http (в данном случае с сервера JIRA через API)
Для запроса 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
вырос до 1,02Mb
.
Итак, мой вопрос
Почему загруженное изображение больше EncodeToPNG()
, чем исходное изображение?
и
Существует ли какое-либо сжатие, которое можно / нужно использовать для данных PNG для архивирования того же уровня сжатия (если сжатие является проблемой вообще)?
Сначала я подумал, что может быть разная глубина цвета, но оба изображения RGBA-32bit
Update
Вот два изображения
оригинал (40 КБ) (взят из здесь )
повторно загружено (59kb)
Обновление 2
Я повторил тест с файлом JPG и EncodeToJPG()
, и результат кажется еще хуже:
вверху оригинальное изображение; внизу перезагруженный.
На этот раз оно увеличилось с 27kb
до 98kb
, так что множитель 2,63
. Как ни странно, размер файла также был постоянным 98kb
независимо от того, что я указывал в качестве параметра quality
для EncodeToJPG()
.