2
\$\begingroup\$

If you import an image into the Unity inspector, the image will be encoded in Unity's own format. Usually the resulting image is much bigger than the original (from 100kb to 1MB). Of course, you can do stuff like compress and change the texture max size to reduce the image's size, but at the end it will almost always be bigger.

I noticed that you can create a Texture2D if you got the necessary bytes. As an experiment, I took my 100kb image and imported it to Unity as a .bytes file. Then I read the bytes and created my Texture2D:

    Texture2D texture = new Texture2D(100, 100);
    texture.LoadImage(myTextAsset.bytes);
    Sprite sprite = Sprite.Create(texture, new Rect(0,0,350, 288));

And it works. And it is smaller (100kb).

So my question is: what's the difference between Unity's builtin way of handling images and my way of loading them using their bytes? Because I'm saving tons of memory with this method. I imagine that it is a bit slower. But if that's the only difference, I can live with that.

\$\endgroup\$
7
  • \$\begingroup\$ I disagree with the entire premise of this question, that images get bigger after importing into Unity. That certainly doesn't happen to me. It's possible that what you're seeing is a compressed image becoming uncompressed within Unity; Unity recompresses images when you import them, including the possibility of no compression. You can adjust this in the Import Settings for a texture. \$\endgroup\$ – jhocking Jan 29 '15 at 22:48
  • \$\begingroup\$ @jhocking this image (i.imgur.com/9zJGGav.png) is a 2KB file. When I import it to Unity (drag & drop), this is what I see: i.imgur.com/Se8d4Oi.png. It is now 52KB large. You can play with the settings, such as Max Size or Format 16 bits, which reduce the size, but the file is still bigger than 2KB or the quality is so extremely reduced that it makes no sense to be doing this. Perhaps you are using a very particular setting? I'd like to know it. Because at the moment the file is most definitely bigger than 2KB. \$\endgroup\$ – Oxide Jan 30 '15 at 1:02
  • \$\begingroup\$ Well in terms of that 52kb, that's the situation I was describing, of the image being uncompressed within Unity (ARGB 32 means an uncompressed 32 bit image). However even with compression turned on and mip-maps turned off, it's larger within Unity (the exact compression algorithm and thus filesize used by Unity varies depending on the platform); I'm guessing that's because png is better than other compression algorithms at handling this specific image, a flat red single color circle. I'd be curious about the image you describe in your question (100kb/1mb) \$\endgroup\$ – jhocking Jan 30 '15 at 13:33
  • \$\begingroup\$ @jhocking this image (i.imgur.com/2s7BGOv.png) is 81KB and becomes 1MB in Unity. One would expect that the final build (for say, iPhone) would have 81KB occupied, but it actually takes up the whole 1MB of storage. \$\endgroup\$ – Oxide Jan 30 '15 at 16:02
  • \$\begingroup\$ When I try importing that image, it's around 128kb. Which is a lot less than 1MB, although more than 81kb. I don't have time to play with the settings right now, I'll see in a bit. \$\endgroup\$ – jhocking Jan 30 '15 at 17:43
1
\$\begingroup\$

Unity is a black box. Nobody outside Unity can tell how it really works without doing a lot of reverse engineering.

My educated guess is that Unity saves some sort of metadata along with the raw bytes in a file, and then loads that data straight to GPU memory. I did this with my own engine, with addition that I gzipped the binary data before saving, and then unzipped it when loading. I do that for all assets regardless if they are textures or anything else, so it is not really texture-spesific thing.

Loading compressed data will be quite a bit faster than reading larger amount of data. If Unity do not apply some sort of compression on the raw binary data, then it surely will be slower to read the data from a disc drive. But if the compression algorithm is too complex uncompressing might take more time, and usually it will always take more memory than just copying the raw bytes straight to the GPU. Choosing between these is a design decision they have made.

As it says in the documentation of Texture2D.LoadImage() the function takes PNG or JPG compressed bytes. Loading these images will prbably be faster, but it will get more complicated since you have to set the texture parameters every time you load the images. Also if you want to store compressed image in the GPU memory, you'll have to call Texture2D.Compress() on each texture you want to compress, which will probably make the process slower. That is a tradeoff that you might want to consider; using compressed textures will usually make your frames render faster since less texture reading is needed, but the image quality is then also a little bit lower.

Also mipmapping should be taken in to account, but I did not find any API calls regarding to manually controlling them. So I have to make another guess that unity generates mipmaps for the texture when you use Texture2D.LoadImage(), you wanted them or not. If you did not want them, then it is about 1/3 wasted texture memory. Loading textures using the standard pipeline of Unity, you can control mipmaps a lot better.

\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.