Titanium JIRA Archive
Appcelerator Community (AC)

[AC-6582] Android: Image orientation handling

GitHub Issuen/a
TypeImprovement
Priorityn/a
StatusClosed
ResolutionDuplicate
Resolution Date2020-09-08T23:42:21.000+0000
Affected Version/sn/a
Fix Version/sn/a
Componentsn/a
Labelsandroid, exif
ReporterMichael Gangolf
AssigneeJoshua Quick
Created2020-08-09T11:16:47.000+0000
Updated2020-09-08T23:42:21.000+0000

Description

In Ti 9.1.0 there was a change to the orientation handling of rotated images: https://github.com/appcelerator/titanium_mobile/pull/11679 https://github.com/appcelerator/titanium_mobile/blob/7ce3ae11f2c886864ed7713b1e88324b60fdf8f6/android/titanium/src/java/org/appcelerator/titanium/TiBlob.java#L756-L758 while this fixes the rotation of the images in the example it brings some problems using av.imageview: https://github.com/AndreaVitale/av.imageview/issues/92 One thing I see is that on my Android 10, Pixel 4 I always get the wrong orientation in e.media.width/height for portrait images when looking at images from camera or gallery but I don't know the orientation (e.g. a portrait image is exif orientation 6 (top, right) but the returned width value is higher). In my opinion the images that are returned to my app should always be in the correct orientation AND the width/height value should represent that too.
var window = Ti.UI.createWindow({
	title: "Image Test"
});

var AvImageview = require("av.imageview");
var img1 =AvImageview.createImageView({
	width: Ti.UI.FILL,
	height: 200,
	top: 0,
	contentMode: AvImageview.CONTENT_MODE_ASPECT_FILL,
});

var img2 =AvImageview.createImageView({
	width: Ti.UI.FILL,
	height: 200,
	top: 200,
	contentMode: AvImageview.CONTENT_MODE_ASPECT_FILL,
});
var img3 =Ti.UI.createImageView({
	width: Ti.UI.SIZE,
	height: 200,
	top: 400,
	autoRotate: true
});
var img4 =Ti.UI.createImageView({
	width: Ti.UI.SIZE,
	height: 200,
	top: 600,
	autoRotate: true
});
window.add(img1);
window.add(img2);
window.add(img3);
window.add(img4);
var dl = Ti.UI.createButton({
	title: "gal",
	bottom: 60,
});
dl.addEventListener("click", function(e) {
	Ti.Media.openPhotoGallery({
		success: function(e) {
			var w = e.media.width;
			var h = e.media.height;

			var r = h / w;
			w = 1024;
			h = r * w;

			var imageBlob = e.media.imageAsResized(w, h);
			img1.image = e.media;
			img2.image = imageBlob;
			img3.image = e.media;
			img4.image = imageBlob;
		}
	});
});

window.add(dl);
window.open();
Needs av.imageview (https://github.com/AndreaVitale/av.imageview/releases/tag/Android-5.0.1) 9.0.3.GA !ti903ga.jpg|thumbnail! 9.1.0.RC !ti910rc.jpg|thumbnail! 1st and 3rd image are straight from the Gallery 2nd and 4th image are resized images.

Attachments

FileDateSize
ti903ga.jpg2020-08-15T13:23:12.000+0000368794
ti910rc.jpg2020-08-15T13:19:49.000+0000447507

Comments

  1. Joshua Quick 2020-08-17

    [~michael], the real issue is that Google's image loading APIs ignore the JPEG's EXIF orientation when decoding it to a bitmap and simply load it as-is. Apple and Microsoft will pre-rotate it, but Google does not. The Titanium blob's "width" and "height" properties represent the actual width and height of the bitmap it wraps. In this case, it's for the unrotated image and it's technically correct. Titanium's ImageView.image property is the only image displaying API that will correctly rotate a JPEG. So, swapping the blob's width/height values would end up causing sizing issues in all of our other image displaying APIs such as "backgroundImage". I think a good *+interim+* solution would be to add a new "rotation" property to Ti.Blob which would provide the EXIF rotation. This is needed for people who are doing the math themselves, such as you. In your case, you know you need to swap width/height values when the rotation is 90 or 180 degrees. (On iOS, this new "rotation" property will always be zero since Apple pre-rotates it.) The BEST solution would be for us to load JPEGs ourselves via the "libjpeg" library and rotate it during the decoding process, but this would involve a major refactoring of our code (although I think it needs it). If we were to do this, then the blob's "rotation" property will always be zero, the blob's width/height properties would be what you expect, and then we can finally be done with this nonsense.
  2. Michael Gangolf 2020-08-17

    Thank you for the great explanation! I've tested it with a js exif library, have to give it another go. it is just that the change in 9.1.0 (swapping the values for rotated images) https://github.com/appcelerator/titanium_mobile/blob/7ce3ae11f2c886864ed7713b1e88324b60fdf8f6/android/titanium/src/java/org/appcelerator/titanium/TiBlob.java#L756-L758 broke it for me and 9.0.3.GA is working. Perhaps it is a combination of that PR (since it fixes other parts) and an exif check? Here is a test image: http://migaweb.de/IMG_20200802_151801.jpg I hate handling images on Android :-D Especially on Samsung phones.
  3. Joshua Quick 2020-08-17

  4. Joshua Quick 2020-08-20

    [~michael], I'm thinking about adding new properties "uprightWidth" and "uprightHeight" to Ti.Blob which will tell you the width/height of the JPEG after it's been rotated. This should make it more convenient to use. For iOS, theses properties will always match width and height since iOS always decodes JPEGs pre-rotated.
  5. Michael Gangolf 2020-08-20

    I was trying to find a spot to do that already but wasn't successful :) And I had some problems with cleanbuild failing on 9.2.0 at the end (had to manually install it, not sure yet why) but I'll give it another go at the weekend.
  6. Joshua Quick 2020-08-20

    [~michael], I have something working now. I just don't "love" the idea of adding these 2 new properties to Ti.Blob. Ideally you shouldn't have to worry about this in Titanium... but natively you do. Maybe a better solution might be to add a method to our "ti.imagefactory" module. Like an imageGetUprightSize() method? I'm a bit torn on this.
  7. Joshua Quick 2020-09-08

    Resolved by [TIMOB-28093]

JSON Source