private static int getRotationFromExifHelper( String path, Resources res, int resId, Context context, Uri uri) { ExifInterface ei = new ExifInterface(); InputStream is = null; BufferedInputStream bis = null; try { if (path != null) { ei.readExif(path); } else if (uri != null) { is = context.getContentResolver().openInputStream(uri); bis = new BufferedInputStream(is); ei.readExif(bis); } else { is = res.openRawResource(resId); bis = new BufferedInputStream(is); ei.readExif(bis); } Integer ori = ei.getTagIntValue(ExifInterface.TAG_ORIENTATION); if (ori != null) { return ExifInterface.getRotationForOrientationValue(ori.shortValue()); } } catch (IOException e) { Log.w(LOGTAG, "Getting exif data failed", e); } catch (NullPointerException e) { // Sometimes the ExifInterface has an internal NPE if Exif data isn't valid Log.w(LOGTAG, "Getting exif data failed", e); } finally { Utils.closeSilently(bis); Utils.closeSilently(is); } return 0; }
public Point getImageBounds() { InputStream is = regenerateInputStream(); if (is != null) { BitmapFactory.Options options = new BitmapFactory.Options(); options.inJustDecodeBounds = true; BitmapFactory.decodeStream(is, null, options); Utils.closeSilently(is); if (options.outWidth != 0 && options.outHeight != 0) { return new Point(options.outWidth, options.outHeight); } } return null; }
public boolean cropBitmap() { boolean failure = false; WallpaperManager wallpaperManager = null; if (mSetWallpaper) { wallpaperManager = WallpaperManager.getInstance(mContext.getApplicationContext()); } if (mSetWallpaper && mNoCrop) { try { InputStream is = regenerateInputStream(); if (is != null) { wallpaperManager.setStream(is); Utils.closeSilently(is); } } catch (IOException e) { Log.w(LOGTAG, "cannot write stream to wallpaper", e); failure = true; } return !failure; } else { // Find crop bounds (scaled to original image size) Rect roundedTrueCrop = new Rect(); Matrix rotateMatrix = new Matrix(); Matrix inverseRotateMatrix = new Matrix(); Point bounds = getImageBounds(); if (mRotation > 0) { rotateMatrix.setRotate(mRotation); inverseRotateMatrix.setRotate(-mRotation); mCropBounds.roundOut(roundedTrueCrop); mCropBounds = new RectF(roundedTrueCrop); if (bounds == null) { Log.w(LOGTAG, "cannot get bounds for image"); failure = true; return false; } float[] rotatedBounds = new float[] {bounds.x, bounds.y}; rotateMatrix.mapPoints(rotatedBounds); rotatedBounds[0] = Math.abs(rotatedBounds[0]); rotatedBounds[1] = Math.abs(rotatedBounds[1]); mCropBounds.offset(-rotatedBounds[0] / 2, -rotatedBounds[1] / 2); inverseRotateMatrix.mapRect(mCropBounds); mCropBounds.offset(bounds.x / 2, bounds.y / 2); } mCropBounds.roundOut(roundedTrueCrop); if (roundedTrueCrop.width() <= 0 || roundedTrueCrop.height() <= 0) { Log.w(LOGTAG, "crop has bad values for full size image"); failure = true; return false; } // See how much we're reducing the size of the image int scaleDownSampleSize = Math.max( 1, Math.min( roundedTrueCrop.width() / mOutWidth, roundedTrueCrop.height() / mOutHeight)); // Attempt to open a region decoder BitmapRegionDecoder decoder = null; InputStream is = null; try { is = regenerateInputStream(); if (is == null) { Log.w(LOGTAG, "cannot get input stream for uri=" + mInUri.toString()); failure = true; return false; } decoder = BitmapRegionDecoder.newInstance(is, false); Utils.closeSilently(is); } catch (IOException e) { Log.w(LOGTAG, "cannot open region decoder for file: " + mInUri.toString(), e); } finally { Utils.closeSilently(is); is = null; } Bitmap crop = null; if (decoder != null) { // Do region decoding to get crop bitmap BitmapFactory.Options options = new BitmapFactory.Options(); if (scaleDownSampleSize > 1) { options.inSampleSize = scaleDownSampleSize; } crop = decoder.decodeRegion(roundedTrueCrop, options); decoder.recycle(); } if (crop == null) { // BitmapRegionDecoder has failed, try to crop in-memory is = regenerateInputStream(); Bitmap fullSize = null; if (is != null) { BitmapFactory.Options options = new BitmapFactory.Options(); if (scaleDownSampleSize > 1) { options.inSampleSize = scaleDownSampleSize; } fullSize = BitmapFactory.decodeStream(is, null, options); Utils.closeSilently(is); } if (fullSize != null) { // Find out the true sample size that was used by the decoder scaleDownSampleSize = bounds.x / fullSize.getWidth(); mCropBounds.left /= scaleDownSampleSize; mCropBounds.top /= scaleDownSampleSize; mCropBounds.bottom /= scaleDownSampleSize; mCropBounds.right /= scaleDownSampleSize; mCropBounds.roundOut(roundedTrueCrop); // Adjust values to account for issues related to rounding if (roundedTrueCrop.width() > fullSize.getWidth()) { // Adjust the width roundedTrueCrop.right = roundedTrueCrop.left + fullSize.getWidth(); } if (roundedTrueCrop.right > fullSize.getWidth()) { // Adjust the left value int adjustment = roundedTrueCrop.left - Math.max(0, roundedTrueCrop.right - roundedTrueCrop.width()); roundedTrueCrop.left -= adjustment; roundedTrueCrop.right -= adjustment; } if (roundedTrueCrop.height() > fullSize.getHeight()) { // Adjust the height roundedTrueCrop.bottom = roundedTrueCrop.top + fullSize.getHeight(); } if (roundedTrueCrop.bottom > fullSize.getHeight()) { // Adjust the top value int adjustment = roundedTrueCrop.top - Math.max(0, roundedTrueCrop.bottom - roundedTrueCrop.height()); roundedTrueCrop.top -= adjustment; roundedTrueCrop.bottom -= adjustment; } crop = Bitmap.createBitmap( fullSize, roundedTrueCrop.left, roundedTrueCrop.top, roundedTrueCrop.width(), roundedTrueCrop.height()); } } if (crop == null) { Log.w(LOGTAG, "cannot decode file: " + mInUri.toString()); failure = true; return false; } if (mOutWidth > 0 && mOutHeight > 0 || mRotation > 0) { float[] dimsAfter = new float[] {crop.getWidth(), crop.getHeight()}; rotateMatrix.mapPoints(dimsAfter); dimsAfter[0] = Math.abs(dimsAfter[0]); dimsAfter[1] = Math.abs(dimsAfter[1]); if (!(mOutWidth > 0 && mOutHeight > 0)) { mOutWidth = Math.round(dimsAfter[0]); mOutHeight = Math.round(dimsAfter[1]); } RectF cropRect = new RectF(0, 0, dimsAfter[0], dimsAfter[1]); RectF returnRect = new RectF(0, 0, mOutWidth, mOutHeight); Matrix m = new Matrix(); if (mRotation == 0) { m.setRectToRect(cropRect, returnRect, Matrix.ScaleToFit.FILL); } else { Matrix m1 = new Matrix(); m1.setTranslate(-crop.getWidth() / 2f, -crop.getHeight() / 2f); Matrix m2 = new Matrix(); m2.setRotate(mRotation); Matrix m3 = new Matrix(); m3.setTranslate(dimsAfter[0] / 2f, dimsAfter[1] / 2f); Matrix m4 = new Matrix(); m4.setRectToRect(cropRect, returnRect, Matrix.ScaleToFit.FILL); Matrix c1 = new Matrix(); c1.setConcat(m2, m1); Matrix c2 = new Matrix(); c2.setConcat(m4, m3); m.setConcat(c2, c1); } Bitmap tmp = Bitmap.createBitmap( (int) returnRect.width(), (int) returnRect.height(), Bitmap.Config.ARGB_8888); if (tmp != null) { Canvas c = new Canvas(tmp); Paint p = new Paint(); p.setFilterBitmap(true); c.drawBitmap(crop, m, p); crop = tmp; } } if (mSaveCroppedBitmap) { mCroppedBitmap = crop; } // Get output compression format CompressFormat cf = convertExtensionToCompressFormat(getFileExtension(mOutputFormat)); // Compress to byte array ByteArrayOutputStream tmpOut = new ByteArrayOutputStream(2048); if (crop.compress(cf, DEFAULT_COMPRESS_QUALITY, tmpOut)) { // If we need to set to the wallpaper, set it if (mSetWallpaper && wallpaperManager != null) { try { byte[] outByteArray = tmpOut.toByteArray(); wallpaperManager.setStream(new ByteArrayInputStream(outByteArray)); if (mOnBitmapCroppedHandler != null) { mOnBitmapCroppedHandler.onBitmapCropped(outByteArray); } } catch (IOException e) { Log.w(LOGTAG, "cannot write stream to wallpaper", e); failure = true; } } } else { Log.w(LOGTAG, "cannot compress bitmap"); failure = true; } } return !failure; // True if any of the operations failed }