Skip to content

Instantly share code, notes, and snippets.

@skypanther
Created July 14, 2016 13:49
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save skypanther/268623df3cb30143e03a49f0e9ffda5f to your computer and use it in GitHub Desktop.
Save skypanther/268623df3cb30143e03a49f0e9ffda5f to your computer and use it in GitHub Desktop.
Crop and resize an image in Titanium, working around image rotation bug (TIMOB-4865)
/*
Our library function to resize and crop a photo -- for our needs, we are
cropping to a square. Uses the ImageFactory for iOS and ImageUtility module
for Android to avoid rotation issues, memory leaks, and some crashes due to
Titanium bugs. Also, we use https://github.com/skypanther/picatsize on Android
to take the initial photo at or close to the target size to work around
memory management (out of memory crashes) issues on Android.
*/
var Module = function Class() {};
var ImageFactory = (OS_IOS) ? require('ti.imagefactory') : require('com.alcoapps.imageutility');
var jpgQuality = (OS_IOS) ? ImageFactory.QUALITY_MEDIUM : 60;
var targetPhotoSize = parseInt(Alloy.CFG.photoSize); // e.g. 1200
Module.prototype.LoadImage = function (event) {
var blob = event.data.blob;
if (!blob || blob.apiName !== 'Ti.Blob') {
return false;
}
var origW = blob.width;
var origH = blob.height;
var croppedSquareSize = Math.min(origW, origH);
// defined in our orig code based on device type & orientation -- iOS only because offsets crash Android
var cropOffsetX = 0;
var cropOffsetY = 0;
var imgBlob;
var fn = 'photo' + guid() + '.jpg';
var file = Titanium.Filesystem.getFile(Ti.Filesystem.applicationDataDirectory, fn);
// resize and crop to a square
if (OS_IOS) {
// Due to a Titanium bug, if we don't resize with ImageFactory
// first, then cropping will rotate the image 90 degrees. So, we resize
// to its original size here first.
blob = ImageFactory.imageAsResized(blob, {
width: origW,
height: origH,
quality: ImageFactory.QUALITY_HIGH
});
blob = ImageFactory.imageAsCropped(blob, {
x: cropOffsetX,
y: cropOffsetY,
width: croppedSquareSize,
height: croppedSquareSize
});
blob = ImageFactory.imageAsResized(blob, {
width: targetPhotoSize,
height: targetPhotoSize,
quality: jpgQuality
});
if (!blob) {
blob = imgBlob = file = undefined;
return false;
}
imgBlob = ImageFactory.compress(blob, 0.6);
blob = undefined;
file.write(imgBlob);
} else if (OS_ANDROID) {
// need to crop first, crop to shortest height or width
blob = blob.imageAsCropped({
x: 0,
y: 0,
width: croppedSquareSize,
height: croppedSquareSize
});
if (!blob) {
blob = imgBlob = file = undefined;
return false;
}
file.write(blob);
blob = undefined;
// Rotate photo in file, resize, and adjust quality.
ImageFactory.rotateResizeImage(file.nativePath, targetPhotoSize, jpgQuality);
file = Ti.Filesystem.getFile(file.nativePath);
imgBlob = file.read();
}
if (!imgBlob) {
blob = imgBlob = file = undefined;
return false;
} else {
return {
blob: imgBlob,
nativePath: fn
};
}
};
// GUID generator, using e7() from http://stackoverflow.com/a/21963136/292947
var lut = [];
for (var i = 0; i < 256; i++) {
lut[i] = (i < 16 ? '0' : '') + (i).toString(16);
}
function guid() {
var d0 = Math.random() * 0xffffffff | 0;
var d1 = Math.random() * 0xffffffff | 0;
var d2 = Math.random() * 0xffffffff | 0;
var d3 = Math.random() * 0xffffffff | 0;
return lut[d0 & 0xff] + lut[d0 >> 8 & 0xff] + lut[d0 >> 16 & 0xff] + lut[d0 >> 24 & 0xff] + '-' +
lut[d1 & 0xff] + lut[d1 >> 8 & 0xff] + '-' + lut[d1 >> 16 & 0x0f | 0x40] + lut[d1 >> 24 & 0xff] + '-' +
lut[d2 & 0x3f | 0x80] + lut[d2 >> 8 & 0xff] + '-' + lut[d2 >> 16 & 0xff] + lut[d2 >> 24 & 0xff] +
lut[d3 & 0xff] + lut[d3 >> 8 & 0xff] + lut[d3 >> 16 & 0xff] + lut[d3 >> 24 & 0xff];
}
module.exports = new Module();
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment