package com.fastebro.androidrgbtool.rgb; import android.Manifest; import android.graphics.Bitmap; import android.graphics.BitmapFactory; import android.graphics.Matrix; import android.media.ExifInterface; import android.support.annotation.NonNull; import android.support.annotation.RequiresPermission; import com.fastebro.androidrgbtool.model.entities.ScaledPicture; import com.fastebro.androidrgbtool.utils.ImageUtils; import java.io.File; import java.io.FileInputStream; import java.io.FileOutputStream; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; import rx.Observable; import rx.Subscriber; /** * Created by danielealtomare on 5/10/15. * Project: rgb-tool */ class PictureScalingManager { @RequiresPermission(Manifest.permission.WRITE_EXTERNAL_STORAGE) public static Observable<ScaledPicture> scalePictureObservable(@NonNull final String sourcePath, @NonNull final String destinationPath) { return Observable.create(new Observable.OnSubscribe<ScaledPicture>() { @Override public void call(Subscriber<? super ScaledPicture> subscriber) { try { boolean useTempFile = !sourcePath.equals(destinationPath); if (useTempFile) { copyFile(sourcePath, destinationPath); } savePrescaledBitmap(destinationPath); ScaledPicture scaledPicture = new ScaledPicture(destinationPath, useTempFile); if (!subscriber.isUnsubscribed()) { subscriber.onNext(scaledPicture); subscriber.onCompleted(); } } catch (IOException e) { if (!subscriber.isUnsubscribed()) { subscriber.onError(e); } } } }); } private static void copyFile(String inputPath, String destinationPath) { InputStream in; OutputStream out; try { in = new FileInputStream(inputPath); out = new FileOutputStream(destinationPath); byte[] buffer = new byte[4096]; int read; while ((read = in.read(buffer)) != -1) { out.write(buffer, 0, read); } in.close(); out.flush(); out.close(); } catch (Exception e) { } } private static void savePrescaledBitmap(String filename) throws IOException { File file; FileInputStream fis; BitmapFactory.Options opts; int resizeScale; Bitmap bmp; file = new File(filename); // This bit determines only the width/height of the bitmap without loading the contents opts = new BitmapFactory.Options(); opts.inJustDecodeBounds = true; fis = new FileInputStream(file); BitmapFactory.decodeStream(fis, null, opts); fis.close(); // Find the correct scale value. It should be a power of 2 resizeScale = 1; if (opts.outHeight > ImageUtils.JPEG_FILE_IMAGE_MAX_SIZE || opts.outWidth > ImageUtils.JPEG_FILE_IMAGE_MAX_SIZE) { resizeScale = (int) Math.pow(2, (int) Math.round( Math.log(ImageUtils.JPEG_FILE_IMAGE_MAX_SIZE / (double) Math.max(opts.outHeight, opts.outWidth)) / Math.log(0.5) )); } // Load pre-scaled bitmap opts = new BitmapFactory.Options(); opts.inSampleSize = resizeScale; opts.inPreferredConfig = Bitmap.Config.ARGB_8888; fis = new FileInputStream(file); bmp = BitmapFactory.decodeStream(fis, null, opts); fis.close(); // Adjust image orientation BitmapFactory.Options bounds = new BitmapFactory.Options(); bounds.inJustDecodeBounds = true; BitmapFactory.decodeFile(filename, bounds); ExifInterface exif = new ExifInterface(filename); String orientString = exif.getAttribute(ExifInterface.TAG_ORIENTATION); int orientation = orientString != null ? Integer.parseInt(orientString) : ExifInterface.ORIENTATION_NORMAL; int rotationAngle = 0; if (orientation == ExifInterface.ORIENTATION_UNDEFINED) { rotationAngle = 0; } if (orientation == ExifInterface.ORIENTATION_ROTATE_90) { rotationAngle = 90; } if (orientation == ExifInterface.ORIENTATION_ROTATE_180) { rotationAngle = 180; } if (orientation == ExifInterface.ORIENTATION_ROTATE_270) { rotationAngle = 270; } // Android BUG: fix orientation if value is equal to 0. if (orientation == 0) { // set orientation to portrait if (bmp.getHeight() > bmp.getWidth()) { rotationAngle = 0; } else { rotationAngle = 90; } } Matrix matrix = new Matrix(); matrix.setRotate(rotationAngle); Bitmap rotatedBitmap = Bitmap.createBitmap(bmp, 0, 0, bmp.getWidth(), bmp.getHeight(), matrix, true); // Compress image File scaledImageFile = new File(filename); OutputStream outStream = new FileOutputStream(scaledImageFile); rotatedBitmap.compress(Bitmap.CompressFormat.JPEG, 90, outStream); outStream.flush(); outStream.close(); } }