I am loading images from the internet, and some of them are coming in with incorrect rotations.
I have ported some .NET code to sniff the EXIF information from the files, and sure enough, the images that come in ‘wrong’ all have EXIF tags that want the rotation to be some other way.
Because the images are security sandboxed, I can’t fix them on load by moving the pixels around. I have managed to rotate them by some very ugly code using GUIUtility.RotateAroundPivot calculations, but I need to know when and how to display them rotated and without the EXIF information I went around Unity to get, I wouldn’t know how to do the rotation.
I suppose if you were using them as textures, you would mangle the UV coordinates to flip them around but that’s still an ugly thing to have to do when the simplest solution is to reorient the images on load to be right side up, and thereby match all of the assumptions built in to Unity and most everything else.
So it seems there ought to be a way to ask for images to be loaded correctly when you get them, and/or the EXIF information from the image should be made available after it’s loaded so it’s easy to figure out if it needs to be displayed in a different orientation.
It also seems that if I can get at the EXIF data, I could in fact drop in a full blown JPEG decoder here and have myself a non-sandboxed image loaded from the interwebz… but that’s a different matter ![]()
NOTE: Go here to get a mostly working EXIF reading library for .NET
http://www.codeproject.com/Articles/47486/Understanding-and-Reading-Exif-Data
Once you have this, take ExifIds.cs, ExifIO.cs, ExifReader.cs, ExifTag.cs and JpegInfo.cs from the ExifLib folder into your project. There will be an error on the public static JpegInfo ReadJpeg(FileInfo fi) function … clone the function and comment out the original, then alter the clone like so:
public static JpegInfo ReadJpeg(byte[] fiBYTES, string Name)
{
DateTime then = DateTime.Now;
using (MemoryStream fs = new MemoryStream(fiBYTES))
{
ExifReader reader = new ExifReader(fs);
reader.info.FileSize = (int)fs.Length;
reader.info.FileName = Name;
reader.info.LoadTime = (DateTime.Now - then);
return reader.info;
}
}
You can use this like so:
IEnumerator GetImage(string url)
{
WWW www = new WWW(url);
Debug.Log ("Fetching image " + url);
yield return www;
if (!System.String.IsNullOrEmpty(www.error))
Debug.Log(www.error);
else
{
Debug.Log("Finished Getting Image -> SIZE: " + www.bytes.Length.ToString ());
ExifLib.JpegInfo jpi = ExifLib.ExifReader.ReadJpeg(www.bytes, "Foo");
Debug.Log ("EXIF: " + jpi.Orientation.ToString());
}
}