Phonegap camera plugin orientation issue in Android
Posted By : Deepak Rawat | 16-Jun-2016
Hi guys,
For using camera in our phonegap application we use official phonegap-camera-plugin, which allow us to capture photo and video using our phone and also allow us to pick photo/video from our phone’s photo gallery.
But when i test this plugin in Samsung Galaxy S6 with Android v5.1.1, i found that there is one issue in this plugin, and the issue is that when we pick any image from phone’s gallery, any third party app or from its internal storage then this plugin return the image with wrong orientation, i.e if the image is in portrait it returns it in landscape orientation(although it works for landscape oriented images).
When i did some investigation on it then i found that this issue is because this plugin does not rotate that image before returning and it's because when plugin try to get the orientation of that image then it returns nothing hence plugin return the image without rotating it.
The reason for not getting image’s orientation is that their paths are different, so for resolving this issue what I have done is that first get that selected image and copy it to my own folder and then get its orientation and rotate the image accordingly, this copied image is temporary after everything is done,i remove that image, due to this change many issue of the plugins also gets resolved.
Here is the code for this change:
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); } 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("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 { 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; } } } 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."); } } } 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(); } } }
THANKS
Cookies are important to the proper functioning of a site. To improve your experience, we use cookies to remember log-in details and provide secure log-in, collect statistics to optimize site functionality, and deliver content tailored to your interests. Click Agree and Proceed to accept cookies and go directly to the site or click on View Cookie Settings to see detailed descriptions of the types of cookies and choose whether to accept certain cookies while on the site.
About Author
Deepak Rawat
Deepak is a Web and Mobile application Sr. Lead Frontend developer and good working experience with JQuery , AngularJS , Javascript and PhoneGap. His hobbies are listening to music and photography.