in src/android/CameraLauncher.java [948:1109]
private Bitmap getScaledAndRotatedBitmap(String imageUrl) throws IOException {
// If no new width or height were specified, and orientation is not needed return the original bitmap
if (this.targetWidth <= 0 && this.targetHeight <= 0 && !(this.correctOrientation)) {
InputStream fileStream = null;
Bitmap image = null;
try {
fileStream = FileHelper.getInputStreamFromUriString(imageUrl, cordova);
image = BitmapFactory.decodeStream(fileStream);
} catch (OutOfMemoryError e) {
callbackContext.error(e.getLocalizedMessage());
} catch (Exception e){
callbackContext.error(e.getLocalizedMessage());
}
finally {
if (fileStream != null) {
try {
fileStream.close();
} catch (IOException e) {
LOG.d(LOG_TAG, "Exception while closing file input stream.");
}
}
}
return image;
}
/* Copy the inputstream to a temporary file on the device.
We then use this temporary file to determine the width/height/orientation.
This is the only way to determine the orientation of the photo coming from 3rd party providers (Google Drive, Dropbox,etc)
This also ensures we create a scaled bitmap with the correct orientation
We delete the temporary file once we are done
*/
File localFile = null;
Uri galleryUri = null;
int rotate = 0;
try {
InputStream fileStream = FileHelper.getInputStreamFromUriString(imageUrl, cordova);
if (fileStream != null) {
// Generate a temporary file
String timeStamp = new SimpleDateFormat(TIME_FORMAT).format(new Date());
String fileName = "IMG_" + timeStamp + (getExtensionForEncodingType());
localFile = new File(getTempDirectoryPath() + fileName);
galleryUri = Uri.fromFile(localFile);
writeUncompressedImage(fileStream, galleryUri);
try {
String mimeType = FileHelper.getMimeType(imageUrl.toString(), cordova);
if (JPEG_MIME_TYPE.equalsIgnoreCase(mimeType)) {
// ExifInterface doesn't like the file:// prefix
String filePath = galleryUri.toString().replace("file://", "");
// read exifData of source
exifData = new ExifHelper();
exifData.createInFile(filePath);
exifData.readExifData();
// Use ExifInterface to pull rotation information
if (this.correctOrientation) {
ExifInterface exif = new ExifInterface(filePath);
rotate = exifToDegrees(exif.getAttributeInt(ExifInterface.TAG_ORIENTATION, ExifInterface.ORIENTATION_UNDEFINED));
}
}
} catch (Exception oe) {
LOG.w(LOG_TAG,"Unable to read Exif data: "+ oe.toString());
rotate = 0;
}
}
} catch (Exception e) {
LOG.e(LOG_TAG,"Exception while getting input stream: "+ e.toString());
return null;
}
try {
// figure out the original width and height of the image
BitmapFactory.Options options = new BitmapFactory.Options();
options.inJustDecodeBounds = true;
InputStream fileStream = null;
try {
fileStream = FileHelper.getInputStreamFromUriString(galleryUri.toString(), cordova);
BitmapFactory.decodeStream(fileStream, null, options);
} finally {
if (fileStream != null) {
try {
fileStream.close();
} catch (IOException e) {
LOG.d(LOG_TAG, "Exception while closing file input stream.");
}
}
}
//CB-2292: WTF? Why is the width null?
if (options.outWidth == 0 || options.outHeight == 0) {
return null;
}
// User didn't specify output dimensions, but they need orientation
if (this.targetWidth <= 0 && this.targetHeight <= 0) {
this.targetWidth = options.outWidth;
this.targetHeight = options.outHeight;
}
// Setup target width/height based on orientation
int rotatedWidth, rotatedHeight;
boolean rotated= false;
if (rotate == 90 || rotate == 270) {
rotatedWidth = options.outHeight;
rotatedHeight = options.outWidth;
rotated = true;
} else {
rotatedWidth = options.outWidth;
rotatedHeight = options.outHeight;
}
// determine the correct aspect ratio
int[] widthHeight = calculateAspectRatio(rotatedWidth, rotatedHeight);
// Load in the smallest bitmap possible that is closest to the size we want
options.inJustDecodeBounds = false;
options.inSampleSize = calculateSampleSize(rotatedWidth, rotatedHeight, widthHeight[0], widthHeight[1]);
Bitmap unscaledBitmap = null;
try {
fileStream = FileHelper.getInputStreamFromUriString(galleryUri.toString(), cordova);
unscaledBitmap = BitmapFactory.decodeStream(fileStream, null, options);
} finally {
if (fileStream != null) {
try {
fileStream.close();
} catch (IOException e) {
LOG.d(LOG_TAG, "Exception while closing file input stream.");
}
}
}
if (unscaledBitmap == null) {
return null;
}
int scaledWidth = (!rotated) ? widthHeight[0] : widthHeight[1];
int scaledHeight = (!rotated) ? widthHeight[1] : widthHeight[0];
Bitmap scaledBitmap = Bitmap.createScaledBitmap(unscaledBitmap, scaledWidth, scaledHeight, true);
if (scaledBitmap != unscaledBitmap) {
unscaledBitmap.recycle();
unscaledBitmap = null;
}
if (this.correctOrientation && (rotate != 0)) {
Matrix matrix = new Matrix();
matrix.setRotate(rotate);
try {
scaledBitmap = Bitmap.createBitmap(scaledBitmap, 0, 0, scaledBitmap.getWidth(), scaledBitmap.getHeight(), matrix, true);
this.orientationCorrected = true;
} catch (OutOfMemoryError oom) {
this.orientationCorrected = false;
}
}
return scaledBitmap;
} finally {
// delete the temporary copy
if (localFile != null) {
localFile.delete();
}
}
}