Search Unity

Storing images in an efficient format like JPG

Discussion in 'General Graphics' started by AlanGameDev, Dec 23, 2015.

  1. AlanGameDev

    AlanGameDev

    Joined:
    Jun 30, 2012
    Posts:
    437
    Hello there.

    I'm working on a game that uses one 1024x1024px rgba image for each level. The compression methods for Texture2Ds aren't very good, they degrade the quality considerable without saving too much disk space. Also, there's a risk of incompatibility I guess, since they work in a gpu-level.

    I know JPG is outdated and there are other newer compression formats based on it, but it's more than enough for my needs and I'm planning to use a 16-color PNG8 image for the alpha channel which is the only one who needs high precision on a pixel level.

    I could think of two ways of using an rgb JPG image and a grayscale PNG image to create a rgba Texture2D object at runtime, the first one is renaming their extensions or zipping them (so Unity won't use the Texture Importer) and loading from "Resources", the other is using the "Assets Streaming" feature, which allows me to work directly with JPG/PNG images without further problems.

    Obviously on runtime I'd need to retrieve the data and create a Texture2D on-the-fly; I know how to do that, that's not a problem. I'm going to use them in raw 'truecolor' format, so it won't be necessary to compress them to a gpu-compatible compressed format at runtime, what certainly would be an expensive operation.

    I would like to know however if there's another option to store the images in an efficient format besides what was mentioned above.

    Thank you.
     
  2. Aras

    Aras

    Unity Technologies

    Joined:
    Nov 7, 2005
    Posts:
    4,770
    Currently, that's what you generally use - store textures in PNG/JPG formats, and load into uncompressed format at runtime via Texture2D.LoadImage or similar.

    If you're targeting PC-like platform (PC/consoles/WebGL) and DXT5-like compression quality is acceptable for you, then using Crunch formats might be good (added in Unity 5.1). These offer JPG-like compression and they are DXT1/DXT5 on the GPU, so a win both in storage space and GPU bandwidth.

    We're looking at ways of compressing on-disk game data files in various ways, but nothing ready to ship yet.
     
    karl_jones and AlanGameDev like this.
  3. AlanGameDev

    AlanGameDev

    Joined:
    Jun 30, 2012
    Posts:
    437
    Thank you for the timely reply :).
    That's totally fine, the LoadImage function will surely come in handy.
    I'm not targeting PCs nor using version 5 at the moment, but thank you for the tips, I'm sure I'll make good use of them in the future.
    It's good to know you are looking for ways to provide that functionality. Especially for mobile it's an important one in my opinion.
    Again, thank you for the reply. I really appreciate it.
     
  4. AlanGameDev

    AlanGameDev

    Joined:
    Jun 30, 2012
    Posts:
    437
    Hello there, I'm having a problem with that way of storing the images (as JPEGs+PNG8s):

    The whole "Streaming Assets" folder is less than 20MB, and I'm trying to keep the game under 100MB. Each level has only very few data, since most stuff is loaded from prefabs at runtime, however, each level has a different image, which is loaded from the JPEGs in the "Streaming Assets" folder.

    I've made an in-editor loader to load the images when you're editing the scenes, so you can see what you're doing. Everything is working pretty well, but for some reason it seems that Unity is storing the Texture2Ds loaded from JPEGs in the scenes files. That's not what I want, since the images are going to be loaded at runtime anyway, so every scene is 10MB+ instead of a few KBs.

    It seems that's also affecting the build size. I know the report from the editor log isn't precise, but when I sum all the assets under "Used Assets, sorted by uncompressed size:", they are well below 90MB, while the APK is 150MB. It also shows this:

    Code (text):
    1. Textures      32.2 mb     4.8%
    2. Meshes        119.5 kb     0.0%
    3. Animations    546.3 kb     0.1%
    4. Sounds        51.7 mb     7.7%
    5. Shaders       195.3 kb     0.0%
    6. Other Assets  3.4 mb     0.5%
    7. Levels        575.6 mb     85.7%
    8. Scripts       1.2 mb     0.2%
    9. Included DLLs 5.2 mb     0.8%
    10. File headers  1.2 mb     0.2%
    11. Complete size 671.4 mb     100.0%
    So my guess is that somehow the extra data from the scenes are 'leaking' into the build file.

    I could just erase all the textures before saving the scenes, perhaps that's the way to go... I could make a custom script to save the scene so it destroys the Texture2Ds loaded from the JPEGs before saving, and obviously automatically loads them the next time the scene is open in the editor, but I'd like to have some word on that issue.

    Thank you in advance.
     
    Last edited: Jan 22, 2016
  5. AlanGameDev

    AlanGameDev

    Joined:
    Jun 30, 2012
    Posts:
    437
    Update: I've destroyed all the data loaded from JPEGs and saved my scenes, which now are around 50KB, and the APK magically went to 85 MB :).

    Perhaps you guys want to look into it... basically, when a Texture2D is created in the editor, Unity saves it in the ".unity" files, that's OK in my opinion, since obviously when you have something that's loaded dynamically from some external resource, you want to be able to have it in the editor too, the problem is that somehow that data is leaking into the final build files.

    At the moment when the scene is open in the editor it automatically loads the Texture2Ds from the JPEGs, and I made a custom "Save" button that destroys these textures and then saves the file, because using the default "Save" button will save all that data into the scene file.

    I'm not sure if I'm explaining the problem properly, but it's surely a bug/undesirable_behavior imho.