diff --git a/src/android/CameraLauncher.java b/src/android/CameraLauncher.java index 4d15bdf..760d90b 100644 --- a/src/android/CameraLauncher.java +++ b/src/android/CameraLauncher.java @@ -26,13 +26,11 @@ import java.io.FileOutputStream; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; -import java.net.URI; import java.text.SimpleDateFormat; import java.util.Date; import org.apache.cordova.CallbackContext; import org.apache.cordova.CordovaPlugin; -import org.apache.cordova.CordovaResourceApi; import org.apache.cordova.LOG; import org.apache.cordova.PermissionHelper; import org.apache.cordova.PluginResult; @@ -40,27 +38,30 @@ import org.json.JSONArray; import org.json.JSONException; import android.Manifest; +import android.annotation.TargetApi; import android.app.Activity; import android.content.ActivityNotFoundException; import android.content.ContentValues; +import android.content.Context; import android.content.Intent; import android.database.Cursor; import android.graphics.Bitmap; import android.graphics.Bitmap.CompressFormat; import android.graphics.BitmapFactory; import android.graphics.Matrix; +import android.media.ExifInterface; import android.media.MediaScannerConnection; import android.media.MediaScannerConnection.MediaScannerConnectionClient; import android.net.Uri; import android.os.Build; import android.os.Bundle; import android.os.Environment; +import android.provider.DocumentsContract; import android.provider.MediaStore; import android.util.Base64; import android.util.Log; import android.content.pm.PackageManager; import android.content.pm.PackageManager.NameNotFoundException; -import android.content.pm.PermissionInfo; /** * This class launches the camera view, allows the user to take a picture, closes the camera view, @@ -117,6 +118,7 @@ public class CameraLauncher extends CordovaPlugin implements MediaScannerConnect private MediaScannerConnection conn; // Used to update gallery app with newly-written files private Uri scanMe; // Uri of image to be added to content store private Uri croppedUri; + private ExifHelper exifData; // Exif data from source /** @@ -168,7 +170,7 @@ public class CameraLauncher extends CordovaPlugin implements MediaScannerConnect this.encodingType = JPEG; } - try { + try { if (this.srcType == CAMERA) { this.callTakePicture(destType, encodingType); } @@ -230,8 +232,8 @@ public class CameraLauncher extends CordovaPlugin implements MediaScannerConnect * or to display URI in an img tag * img.src=result; * - * @param quality Compression quality hint (0-100: 0=low quality & high compression, 100=compress of max quality) * @param returnType Set the type of image to return. + * @param encodingType JPEG or PNG */ public void callTakePicture(int returnType, int encodingType) { boolean saveAlbumPermission = PermissionHelper.hasPermission(this, Manifest.permission.READ_EXTERNAL_STORAGE); @@ -339,7 +341,6 @@ public class CameraLauncher extends CordovaPlugin implements MediaScannerConnect /** * Get image from photo library. * - * @param quality Compression quality hint (0-100: 0=low quality & high compression, 100=compress of max quality) * @param srcType The album to get image from. * @param returnType Set the type of image to return. * @param encodingType @@ -373,17 +374,17 @@ public class CameraLauncher extends CordovaPlugin implements MediaScannerConnect intent.addCategory(Intent.CATEGORY_OPENABLE); } } else if (this.mediaType == VIDEO) { - intent.setType("video/*"); - title = GET_VIDEO; - intent.setAction(Intent.ACTION_GET_CONTENT); - intent.addCategory(Intent.CATEGORY_OPENABLE); + intent.setType("video/*"); + title = GET_VIDEO; + intent.setAction(Intent.ACTION_GET_CONTENT); + intent.addCategory(Intent.CATEGORY_OPENABLE); } else if (this.mediaType == ALLMEDIA) { - // I wanted to make the type 'image/*, video/*' but this does not work on all versions - // of android so I had to go with the wildcard search. - intent.setType("*/*"); - title = GET_All; - intent.setAction(Intent.ACTION_GET_CONTENT); - intent.addCategory(Intent.CATEGORY_OPENABLE); + // I wanted to make the type 'image/*, video/*' but this does not work on all versions + // of android so I had to go with the wildcard search. + intent.setType("*/*"); + title = GET_All; + intent.setAction(Intent.ACTION_GET_CONTENT); + intent.addCategory(Intent.CATEGORY_OPENABLE); } if (this.cordova != null) { this.cordova.startActivityForResult((CordovaPlugin) this, Intent.createChooser(intent, @@ -391,52 +392,52 @@ public class CameraLauncher extends CordovaPlugin implements MediaScannerConnect } } - /** - * Brings up the UI to perform crop on passed image URI - * - * @param picUri - */ - private void performCrop(Uri picUri, int destType, Intent cameraIntent) { - try { - Intent cropIntent = new Intent("com.android.camera.action.CROP"); - // indicate image type and Uri - cropIntent.setDataAndType(picUri, "image/*"); - // set crop properties - cropIntent.putExtra("crop", "true"); + /** + * Brings up the UI to perform crop on passed image URI + * + * @param picUri + */ + private void performCrop(Uri picUri, int destType, Intent cameraIntent) { + try { + Intent cropIntent = new Intent("com.android.camera.action.CROP"); + // indicate image type and Uri + cropIntent.setDataAndType(picUri, "image/*"); + // set crop properties + cropIntent.putExtra("crop", "true"); - // indicate output X and Y - if (targetWidth > 0) { - cropIntent.putExtra("outputX", targetWidth); - } - if (targetHeight > 0) { - cropIntent.putExtra("outputY", targetHeight); - } - if (targetHeight > 0 && targetWidth > 0 && targetWidth == targetHeight) { - cropIntent.putExtra("aspectX", 1); - cropIntent.putExtra("aspectY", 1); - } - // create new file handle to get full resolution crop - croppedUri = Uri.fromFile(createCaptureFile(this.encodingType, System.currentTimeMillis() + "")); - cropIntent.putExtra("output", croppedUri); + // indicate output X and Y + if (targetWidth > 0) { + cropIntent.putExtra("outputX", targetWidth); + } + if (targetHeight > 0) { + cropIntent.putExtra("outputY", targetHeight); + } + if (targetHeight > 0 && targetWidth > 0 && targetWidth == targetHeight) { + cropIntent.putExtra("aspectX", 1); + cropIntent.putExtra("aspectY", 1); + } + // create new file handle to get full resolution crop + croppedUri = Uri.fromFile(createCaptureFile(this.encodingType, System.currentTimeMillis() + "")); + cropIntent.putExtra("output", croppedUri); - // start the activity - we handle returning in onActivityResult + // start the activity - we handle returning in onActivityResult - if (this.cordova != null) { - this.cordova.startActivityForResult((CordovaPlugin) this, - cropIntent, CROP_CAMERA + destType); - } - } catch (ActivityNotFoundException anfe) { - Log.e(LOG_TAG, "Crop operation not supported on this device"); - try { - processResultFromCamera(destType, cameraIntent); - } - catch (IOException e) - { - e.printStackTrace(); - Log.e(LOG_TAG, "Unable to write to file"); - } + if (this.cordova != null) { + this.cordova.startActivityForResult((CordovaPlugin) this, + cropIntent, CROP_CAMERA + destType); + } + } catch (ActivityNotFoundException anfe) { + Log.e(LOG_TAG, "Crop operation not supported on this device"); + try { + processResultFromCamera(destType, cameraIntent); + } + catch (IOException e) + { + e.printStackTrace(); + Log.e(LOG_TAG, "Unable to write to file"); + } + } } - } /** * Applies all needed transformation to the image received from the camera. @@ -450,8 +451,8 @@ public class CameraLauncher extends CordovaPlugin implements MediaScannerConnect // Create an ExifHelper to save the exif data that is lost during compression ExifHelper exif = new ExifHelper(); String sourcePath = (this.allowEdit && this.croppedUri != null) ? - FileHelper.stripFileProtocol(this.croppedUri.toString()) : - FileHelper.stripFileProtocol(this.imageUri.toString()); + FileHelper.stripFileProtocol(this.croppedUri.toString()) : + FileHelper.stripFileProtocol(this.imageUri.toString()); if (this.encodingType == JPEG) { try { @@ -472,7 +473,7 @@ public class CameraLauncher extends CordovaPlugin implements MediaScannerConnect // in the gallery and the modified image is saved in the temporary // directory if (this.saveToPhotoAlbum) { - galleryUri = Uri.fromFile(new File(getPicutresPath())); + galleryUri = Uri.fromFile(new File(getPicturesPath())); if(this.allowEdit && this.croppedUri != null) { writeUncompressedImage(this.croppedUri, galleryUri); @@ -485,7 +486,7 @@ public class CameraLauncher extends CordovaPlugin implements MediaScannerConnect // If sending base64 image back if (destType == DATA_URL) { - bitmap = getScaledBitmap(sourcePath); + bitmap = getScaledAndRotatedBitmap(sourcePath); if (bitmap == null) { // Try to get the bitmap from intent. @@ -499,9 +500,6 @@ public class CameraLauncher extends CordovaPlugin implements MediaScannerConnect return; } - if (rotate != 0 && this.correctOrientation) { - bitmap = getRotatedBitmap(rotate, bitmap, exif); - } this.processPicture(bitmap, this.encodingType); @@ -533,7 +531,7 @@ public class CameraLauncher extends CordovaPlugin implements MediaScannerConnect } } else { Uri uri = Uri.fromFile(createCaptureFile(this.encodingType, System.currentTimeMillis() + "")); - bitmap = getScaledBitmap(sourcePath); + bitmap = getScaledAndRotatedBitmap(sourcePath); // Double-check the bitmap. if (bitmap == null) { @@ -542,9 +540,6 @@ public class CameraLauncher extends CordovaPlugin implements MediaScannerConnect return; } - if (rotate != 0 && this.correctOrientation) { - bitmap = getRotatedBitmap(rotate, bitmap, exif); - } // Add compressed version of captured image to returned media store Uri OutputStream os = this.cordova.getActivity().getContentResolver().openOutputStream(uri); @@ -575,33 +570,28 @@ public class CameraLauncher extends CordovaPlugin implements MediaScannerConnect bitmap = null; } -private String getPicutresPath() -{ - String timeStamp = new SimpleDateFormat("yyyyMMdd_HHmmss").format(new Date()); - String imageFileName = "IMG_" + timeStamp + (this.encodingType == JPEG ? ".jpg" : ".png"); - File storageDir = Environment.getExternalStoragePublicDirectory( - Environment.DIRECTORY_PICTURES); - String galleryPath = storageDir.getAbsolutePath() + "/" + imageFileName; - return galleryPath; -} + private String getPicturesPath() + { + String timeStamp = new SimpleDateFormat("yyyyMMdd_HHmmss").format(new Date()); + String imageFileName = "IMG_" + timeStamp + (this.encodingType == JPEG ? ".jpg" : ".png"); + File storageDir = Environment.getExternalStoragePublicDirectory( + Environment.DIRECTORY_PICTURES); + String galleryPath = storageDir.getAbsolutePath() + "/" + imageFileName; + return galleryPath; + } -private void refreshGallery(Uri contentUri) -{ - Intent mediaScanIntent = new Intent(Intent.ACTION_MEDIA_SCANNER_SCAN_FILE); - mediaScanIntent.setData(contentUri); - this.cordova.getActivity().sendBroadcast(mediaScanIntent); -} + private void refreshGallery(Uri contentUri) + { + Intent mediaScanIntent = new Intent(Intent.ACTION_MEDIA_SCANNER_SCAN_FILE); + mediaScanIntent.setData(contentUri); + this.cordova.getActivity().sendBroadcast(mediaScanIntent); + } -private String ouputModifiedBitmap(Bitmap bitmap, Uri uri) throws IOException { - // Some content: URIs do not map to file paths (e.g. picasa). - String realPath = FileHelper.getRealPath(uri, this.cordova); - - // Get filename from uri - String fileName = realPath != null ? - realPath.substring(realPath.lastIndexOf('/') + 1) : - "modified." + (this.encodingType == JPEG ? "jpg" : "png"); + private String outputModifiedBitmap(Bitmap bitmap, Uri uri) throws IOException { + String timeStamp = new SimpleDateFormat("yyyyMMdd_HHmmss").format(new Date()); + String fileName = "IMG_" + timeStamp + (this.encodingType == JPEG ? ".jpg" : ".png"); String modifiedPath = getTempDirectoryPath() + "/" + fileName; OutputStream os = new FileOutputStream(modifiedPath); @@ -612,18 +602,14 @@ private String ouputModifiedBitmap(Bitmap bitmap, Uri uri) throws IOException { bitmap.compress(compressFormat, this.mQuality, os); os.close(); - if (realPath != null && this.encodingType == JPEG) { - // Create an ExifHelper to save the exif data that is lost during compression - ExifHelper exif = new ExifHelper(); - + if (exifData != null && this.encodingType == JPEG) { try { - exif.createInFile(realPath); - exif.readExifData(); if (this.correctOrientation && this.orientationCorrected) { - exif.resetOrientation(); + exifData.resetOrientation(); } - exif.createOutFile(modifiedPath); - exif.writeExifData(); + exifData.createOutFile(modifiedPath); + exifData.writeExifData(); + exifData = null; } catch (IOException e) { e.printStackTrace(); } @@ -633,7 +619,7 @@ private String ouputModifiedBitmap(Bitmap bitmap, Uri uri) throws IOException { -/** + /** * Applies all needed transformation to the image received from the gallery. * * @param destType In which form should we return the image @@ -677,7 +663,7 @@ private String ouputModifiedBitmap(Bitmap bitmap, Uri uri) throws IOException { } Bitmap bitmap = null; try { - bitmap = getScaledBitmap(uriString); + bitmap = getScaledAndRotatedBitmap(uriString); } catch (IOException e) { e.printStackTrace(); } @@ -687,20 +673,6 @@ private String ouputModifiedBitmap(Bitmap bitmap, Uri uri) throws IOException { return; } - if (this.correctOrientation) { - rotate = getImageOrientation(uri); - if (rotate != 0) { - Matrix matrix = new Matrix(); - matrix.setRotate(rotate); - try { - bitmap = Bitmap.createBitmap(bitmap, 0, 0, bitmap.getWidth(), bitmap.getHeight(), matrix, true); - this.orientationCorrected = true; - } catch (OutOfMemoryError oom) { - this.orientationCorrected = false; - } - } - } - // If sending base64 image back if (destType == DATA_URL) { this.processPicture(bitmap, this.encodingType); @@ -712,7 +684,7 @@ private String ouputModifiedBitmap(Bitmap bitmap, Uri uri) throws IOException { if ( (this.targetHeight > 0 && this.targetWidth > 0) || (this.correctOrientation && this.orientationCorrected) ) { try { - String modifiedPath = this.ouputModifiedBitmap(bitmap, uri); + String modifiedPath = this.outputModifiedBitmap(bitmap, uri); // The modified image is cached by the app in order to get around this and not have to delete you // application cache I'm adding the current system time to the end of the file url. this.callbackContext.success("file://" + modifiedPath + "?" + System.currentTimeMillis()); @@ -822,69 +794,19 @@ private String ouputModifiedBitmap(Bitmap bitmap, Uri uri) throws IOException { } } - private int getImageOrientation(Uri uri) { - int rotate = 0; - String[] cols = { MediaStore.Images.Media.ORIENTATION }; - try { - Cursor cursor = cordova.getActivity().getContentResolver().query(uri, - cols, null, null, null); - if (cursor != null) { - cursor.moveToPosition(0); - rotate = cursor.getInt(0); - cursor.close(); - } - } catch (Exception e) { - // You can get an IllegalArgumentException if ContentProvider doesn't support querying for orientation. - } - return rotate; - } - + /** - * Figure out if the bitmap should be rotated. For instance if the picture was taken in - * portrait mode + * Write an inputstream to local disk * - * @param rotate - * @param bitmap - * @return rotated bitmap - */ - private Bitmap getRotatedBitmap(int rotate, Bitmap bitmap, ExifHelper exif) { - Matrix matrix = new Matrix(); - if (rotate == 180) { - matrix.setRotate(rotate); - } else { - matrix.setRotate(rotate, (float) bitmap.getWidth() / 2, (float) bitmap.getHeight() / 2); - } - - try - { - bitmap = Bitmap.createBitmap(bitmap, 0, 0, bitmap.getWidth(), bitmap.getHeight(), matrix, true); - exif.resetOrientation(); - } - catch (OutOfMemoryError oom) - { - // You can run out of memory if the image is very large: - // http://simonmacdonald.blogspot.ca/2012/07/change-to-camera-code-in-phonegap-190.html - // If this happens, simply do not rotate the image and return it unmodified. - // If you do not catch the OutOfMemoryError, the Android app crashes. - } - - return bitmap; - } - - /** - * In the special case where the default width, height and quality are unchanged - * we just write the file out to disk saving the expensive Bitmap.compress function. - * - * @param uri + * @param fis - The InputStream to write + * @param dest - Destination on disk to write to * @throws FileNotFoundException * @throws IOException */ - private void writeUncompressedImage(Uri src, Uri dest) throws FileNotFoundException, + private void writeUncompressedImage(InputStream fis, Uri dest) throws FileNotFoundException, IOException { - FileInputStream fis = null; OutputStream os = null; try { - fis = new FileInputStream(FileHelper.stripFileProtocol(src.toString())); os = this.cordova.getActivity().getContentResolver().openOutputStream(dest); byte[] buffer = new byte[4096]; int len; @@ -909,6 +831,21 @@ private String ouputModifiedBitmap(Bitmap bitmap, Uri uri) throws IOException { } } } + /** + * In the special case where the default width, height and quality are unchanged + * we just write the file out to disk saving the expensive Bitmap.compress function. + * + * @param src + * @throws FileNotFoundException + * @throws IOException + */ + private void writeUncompressedImage(Uri src, Uri dest) throws FileNotFoundException, + IOException { + + FileInputStream fis = new FileInputStream(FileHelper.stripFileProtocol(src.toString())); + writeUncompressedImage(fis, dest); + + } /** * Create entry in media store for image @@ -934,15 +871,15 @@ private String ouputModifiedBitmap(Bitmap bitmap, Uri uri) throws IOException { } /** - * Return a scaled bitmap based on the target width and height + * Return a scaled and rotated bitmap based on the target width and height * - * @param imagePath + * @param imageUrl * @return * @throws IOException */ - private Bitmap getScaledBitmap(String imageUrl) throws IOException { - // If no new width or height were specified return the original bitmap - if (this.targetWidth <= 0 && this.targetHeight <= 0) { + 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 { @@ -960,53 +897,147 @@ private String ouputModifiedBitmap(Bitmap bitmap, Uri uri) throws IOException { return image; } - // figure out the original width and height of the image - BitmapFactory.Options options = new BitmapFactory.Options(); - options.inJustDecodeBounds = true; - InputStream fileStream = null; + + /* 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 { - fileStream = FileHelper.getInputStreamFromUriString(imageUrl, cordova); - BitmapFactory.decodeStream(fileStream, null, options); - } finally { + InputStream fileStream = FileHelper.getInputStreamFromUriString(imageUrl, cordova); if (fileStream != null) { + // Generate a temporary file + String timeStamp = new SimpleDateFormat("yyyyMMdd_HHmmss").format(new Date()); + String fileName = "IMG_" + timeStamp + (this.encodingType == JPEG ? ".jpg" : ".png"); + localFile = new File(getTempDirectoryPath() + fileName); + galleryUri = Uri.fromFile(localFile); + writeUncompressedImage(fileStream, galleryUri); try { - fileStream.close(); - } catch (IOException e) { - LOG.d(LOG_TAG,"Exception while closing file input stream."); + String mimeType = FileHelper.getMimeType(imageUrl.toString(), cordova); + if ("image/jpeg".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); + // 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; } } } - - //CB-2292: WTF? Why is the width null? - if(options.outWidth == 0 || options.outHeight == 0) + catch (Exception e) { + LOG.e(LOG_TAG,"Exception while getting input stream: "+ e.toString()); return null; } - // determine the correct aspect ratio - int[] widthHeight = calculateAspectRatio(options.outWidth, options.outHeight); - // Load in the smallest bitmap possible that is closest to the size we want - options.inJustDecodeBounds = false; - options.inSampleSize = calculateSampleSize(options.outWidth, options.outHeight, this.targetWidth, this.targetHeight); - Bitmap unscaledBitmap = null; + try { - fileStream = FileHelper.getInputStreamFromUriString(imageUrl, 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."); + // 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; } - if (unscaledBitmap == null) { - return null; + finally { + // delete the temporary copy + if (localFile != null) { + localFile.delete(); + } } - return Bitmap.createScaledBitmap(unscaledBitmap, widthHeight[0], widthHeight[1], true); } /** @@ -1027,11 +1058,11 @@ private String ouputModifiedBitmap(Bitmap bitmap, Uri uri) throws IOException { } // Only the width was specified else if (newWidth > 0 && newHeight <= 0) { - newHeight = (newWidth * origHeight) / origWidth; + newHeight = (int)((double)(newWidth / (double)origWidth) * origHeight); } // only the height was specified else if (newWidth <= 0 && newHeight > 0) { - newWidth = (newHeight * origWidth) / origHeight; + newWidth = (int)((double)(newHeight / (double)origHeight) * origWidth); } // If the user specified both a positive width and height // (potentially different aspect ratio) then the width or height is @@ -1075,7 +1106,7 @@ private String ouputModifiedBitmap(Bitmap bitmap, Uri uri) throws IOException { } else { return srcHeight / dstHeight; } - } + } /** * Creates a cursor that can be used to determine how many images we have. @@ -1288,4 +1319,4 @@ private String ouputModifiedBitmap(Bitmap bitmap, Uri uri) throws IOException { this.callbackContext = callbackContext; } -} +} \ No newline at end of file