Load jpeg without converting to texture.

Hi. I need to write an application that will load a .jpeg at the beginning of a level. Since we are expecting about 1000 images, we would like to keep them in the original format. However, from what I know, Unity automatically converts any image into a texture, that takes up a lot more space that the original. Is there a way to avoid the conversion and keep the original jpeg file?

Solution:

  1. Have your images in the ‘Resources’ folder
  2. Rename all .jpg files to .bytes
    (see: Unity - Scripting API: TextAsset.bytes)
  3. Use this code:
TextAsset tmp = Resources.Load("TestCar2", typeof(TextAsset)) as TextAsset;
imgTexture = new Texture2D(732, 549);
imgTexture.LoadImage(tmp.bytes);
carImageMaterial.mainTexture = imgTexture;
3 Likes

Not really. The WWW object can load the bytes. Then you can convert the bytes later on to a texture

http://unity3d.com/support/documentation/ScriptReference/Texture2D.LoadImage.html

So you load them up, save the bytes read, then when you need it, load it into a texture. This process though, looks very memory intensive.

Thanks for the info.
I still am unclear where I need to store the .jpg files so they remain in the original format in the final solution. I should mention that this will be a mobile application (Android, iOS), so I am unable to simply copy/paste the files in a destination folder.

I tried the ‘Resources’ folder, but these images are still converted to textures. Any ideas?

look for a jpg loader (or write your own one) and load the desired file during runtime with it from the file system. maybe there is already a solution for loading jpgs in the net/mono framework available. have a look. when you only load one file per level this should not be a hard impact on memory/performance.
the files can be given along with the application into a separate folder not managed by unity (read not in the assets folder).

I’ve seen some folks talk about getting a performance boost from loading a texture and containing its pixel information in a Color[ ] instead of a Texture or Texture2D. However - I’ve also heard that Unity is notoriously bad at letting go of texture data once its been loaded. I can’t speak to either one but I’d be curious to see what you come up with.

As already mentioned, WWW does that.

The texture needs to be a Texture if it’s ever going to be displayed; storing it as Color[ ] won’t give any performance boots or do any good, except for image manipulation done with GetPixels/SetPixels, and furthermore would significantly increase memory usage, since each pixel in Color is 16 bytes rather than 4. (Although that issue is negated if you use Color32[ ].)

–Eric

Right - I was speaking in terms of image manipulation via Get/SetPixels where you could simply save the Color data as a Collection, do some kind of manipulation, and use the result as a Texture that is displayed. I assumed that was what the OP was trying to do but I may have read too much into it. :slight_smile:

Thanks for all the feedback. Still I don’t have an answer, where I can store several jpg files in an iPhone/Android project so they are not converted to textures.

The OP wants to save raw JPG data in memory instead of Color[ ]. to save space.

If I read you correctly, you want to have your jpegs in your project without having Unity see them as images. If this is the case, change the extension to .txt or the like and toss them into the Resources folder. Then you can use Resources.Load with a TextAsset, then grab the bytes, and use Texture2D.LoadImage to read it into an image.

EDIT: Oddly enough, the docs have a similar usage case: http://unity3d.com/support/documentation/ScriptReference/Texture2D.LoadImage.html

Regards,

-Lincoln Green

Yep, that’s exactly what I need. I’ll give it a try and post some feedback if it works or not. Thanks!

It didn’t work. I renamed the .jpg to .txt

Here is the code I used:

And the image is all messed up

Any idea where I am going wrong?

jpg is a compressed format so simply assigning the bytes will not work. thats why i suggested to look for a jpg loader which could do the decompression for you. if you would want to assign the bytes directly you need to use bmp and skip the file header.
also i think interpreting the files as text may cause problems as textbytes can be converted if they are not printable. i would suggest using normal file io for that (binary reader).
and afaik png is a better suited image format as there are no compression artifacts.

The .jpg is a must, since we are talking 1000+ images.

Ok, I managed to load the image from my web server using the WWW object, and it works:

	WWW imageSource;
	Texture2D imgTexture;

	void Awake ()
	{		
		imgTexture = new Texture2D(732, 549, TextureFormat.ARGB32, false);		
		imageSource = new WWW("http://mySite.com/Images/TestCar1.jpg");
		
		StartCoroutine("loadImageUrl");
	}
	
	IEnumerator loadImageUrl()
	{
	    while(!imageSource.isDone)
		{
			yield return new WaitForSeconds(0.5f);
		}
		
		imageSource.LoadImageIntoTexture(imgTexture);
		carImageMaterial.mainTexture = imgTexture;
	}

The problem is that i need to do this with local files, something like new WWW(“file://[…]/TestCar1.jpg”);
The problem is I don’t know how to do this for both iOS and Android. My guess is that I need something like Application.persistentDataPath. But I am unclear how to add the images there.

1 Like

Anyone?

File:// works for iOS, you can use Application.dataPath + “…/Documents/” as a nice writeable/readable location.

Wrong. The docs for Texture2D.LoadImage explicitly state that

I am somewhat curious as to what went wrong with the original code - it looks pretty much the same as the example in the docs.

WWW class already does this, so does LoadImage.

The file extension is arbitrary and has no effect on the contents. Loading TextAsset.bytes is always just bytes.

–Eric

I wonder if this is actually a feasible solution - is there a way to have the image files be placed in the Documents folder?