[TIMOB-14559] Android: imageAsResized and imageAsThumbnail don't include EXIF data
GitHub Issue | n/a |
---|---|
Type | Bug |
Priority | Critical |
Status | Closed |
Resolution | Fixed |
Resolution Date | 2014-05-28T16:05:53.000+0000 |
Affected Version/s | n/a |
Fix Version/s | 2014 Sprint 07, 2014 Sprint 07 SDK, Release 3.3.0 |
Components | Android |
Labels | module_media, parity, qe-testadded |
Reporter | Dirlei DionĂsio |
Assignee | Sunila |
Created | 2013-06-28T23:16:16.000+0000 |
Updated | 2014-08-31T09:07:56.000+0000 |
Description
*Problem*
The picture is always recorded in landscape, but when the device is in portrait mode the orientation flag in EXIF indicates that the picture should be rotated to portrait whenever some app wants to shown pictures in the right orientation. That applies to Titanium apps too.
The thing is using either Ti.Blob.imageAsResized or imageAsThumbnail methods on Android removes the orientation flag from the resulting image. Thus any app that wants to show the new image will not be able to determine if the the image should be displayed in landscape or portrait mode and will default to landscape, causing portrait images to be seen sideways.
The included code sample shows that happening on Android.
The desired behaviour would be Android's implementation of Ti.Blob.imageAsResized and imageAsThumbnail keeping the orientation flag intact in the new image data. The iOS implementation of these methods works fine and it would be reasonable to have both platforms offering the same semantics for this use case.
I figure out that Titanium.Blob.imageAsResized and Titanium.Blob.imageAsThumbnail generate images that don't include exif data on Android. Thus, photos captured in portrait mode and resized with one of this methods are always displayed in landscape mode when using ImageView, even when autorotate = true.
I can do a workaround rotating the ImageView, but it doesn't work when we're using leftImage or rightImage of a TableViewRow.
The code bellow works fine on iOS, but not on Android.
*Test case*
var dir = Ti.Platform.osname === 'android' ? Ti.Filesystem.externalStorageDirectory : Ti.Filesystem.applicationDataDirectory, original = dir + 'original.jpg', resized = dir + 'resized.jpg';
var win = Titanium.UI.createWindow({
exitOnClose : true,
fullscreen : false
}), img1, img2;
var refreshImages = function() {
if (img1) {
win.remove(img1);
img1 = null;
}
img1 = Ti.UI.createImageView({
autorotate : true,
top : 10,
height : 150,
width : 150,
image : original
});
win.add(img1);
if (img2) {
win.remove(img2);
img2 = null;
}
img2 = Ti.UI.createImageView({
autorotate : true,
top : 170,
height : 150,
width : 150,
image : resized
});
win.add(img2);
/*
This is a workaround, but I can't do this on leftImage or rightImage of a TableViewRow
if (Ti.Platform.osname === 'android') {
var t = Titanium.UI.create2DMatrix();
t = t.rotate(90);
img2.animate({transform: t});
}
*/
};
refreshImages();
var b = Ti.UI.createButton({
bottom : 10,
left : 10,
right : 10,
height : 50,
width : Ti.UI.FILL,
title : 'camera'
});
b.addEventListener('click', function() {
var params = {
saveToPhotoGallery : false,
success : function(e) {
Ti.Filesystem.getFile(original).write(e.media);
//img1.image = original; does not refresh image on android
var blob = e.media.imageAsThumbnail(150, 1, 10);
//var blob = e.media.imageAsResized(150, 150); // same problem
Ti.Filesystem.getFile(resized).write(blob);
//img2.image = resized; does not refresh image on android
refreshImages();
},
error : function(e) {
Ti.API.error('Camera error: ' + JSON.stringify(e));
},
saveToPhotoGallery : false,
alowEditing : false,
mediaTypes : [Ti.Media.MEDIA_TYPE_PHOTO]
};
if (Ti.Platform.model === 'Simulator' || Ti.Platform.model.indexOf('sdk') !== -1) {
Ti.Media.openPhotoGallery(params);
} else {
Ti.Media.showCamera(params);
};
});
win.add(b);
win.open();
[Moved to main project]
[Moved to description]
This really needs to be fixed guys. Taking photos with Android cameras is useless now.
This Titanium modules fixes this problem: https://github.com/freshheads/fh.imagefactory Please steal this code and get it in the SDK ;)
Read Exif data and if needed rotate image. https://github.com/appcelerator/titanium_mobile/pull/5339
Verified the fix by using the code in the ticket. Now, after the pic has been taken both the images appear in landscape whereas in case of a failure the second image is in landscape mode. Closing as this is fixed. Environment: Appc Studio : 3.3.0.201405011408 Ti SDK : 3.3.0.v20140502133323 Mac OSX : 10.8.5 Alloy : 1.4.0-dev CLI - 3.3.0-dev Samsung Galaxy S4 running android 4.2.2 Nexus 5 - android 4.4.2
I've tested this on Android 4.4.4 with SDK 3.3.0, sgs2
landscape photo
imageAsResized didn't rotate the image in the portrait mode or it didn't include the exif so imageAsCropped knows that it needs to rotate it
BTW, on a Nexus 4 exif is undefined but the image width/height is according to the rotation: portrait: w:2448, h:3264, exif: undefined landscape: w:3264, h:2448, exif: undefined