diff --git a/android/build.gradle b/android/build.gradle index ef13912..06841c0 100644 --- a/android/build.gradle +++ b/android/build.gradle @@ -4,18 +4,18 @@ version '1.0-SNAPSHOT' buildscript { repositories { google() - jcenter() + mavenCentral() } dependencies { - classpath 'com.android.tools.build:gradle:3.3.1' + classpath 'com.android.tools.build:gradle:3.3.3' } } rootProject.allprojects { repositories { google() - jcenter() + mavenCentral() } } @@ -33,3 +33,7 @@ android { abortOnError false } } + +dependencies { + implementation 'androidx.exifinterface:exifinterface:1.3.5' +} diff --git a/android/src/main/java/com/example/flutternativeimage/MethodCallHandlerImpl.java b/android/src/main/java/com/example/flutternativeimage/MethodCallHandlerImpl.java index 41e7234..010a3f2 100644 --- a/android/src/main/java/com/example/flutternativeimage/MethodCallHandlerImpl.java +++ b/android/src/main/java/com/example/flutternativeimage/MethodCallHandlerImpl.java @@ -3,7 +3,7 @@ import android.content.Context; import android.graphics.Bitmap; import android.graphics.BitmapFactory; -import android.media.ExifInterface; +import androidx.exifinterface.media.ExifInterface; import android.util.Log; import java.io.ByteArrayOutputStream; @@ -22,158 +22,195 @@ public class MethodCallHandlerImpl implements MethodChannel.MethodCallHandler { private final Context context; + static final List ExifAttributes = Arrays.asList( + "FNumber", + "ExposureTime", + "ISOSpeedRatings", + "GPSAltitude", + "GPSAltitudeRef", + "FocalLength", + "GPSDateStamp", + "WhiteBalance", + "GPSProcessingMethod", + "GPSTimeStamp", + "DateTime", + "Flash", + "GPSLatitude", + "GPSLatitudeRef", + "GPSLongitude", + "GPSLongitudeRef", + "Make", + "Model", + "Orientation"); + MethodCallHandlerImpl(Context context) { this.context = context; } @Override public void onMethodCall(MethodCall call, MethodChannel.Result result) { - if(call.method.equals("compressImage")) { + if (call.method.equals("compressImage")) { String fileName = call.argument("file"); int resizePercentage = call.argument("percentage"); int targetWidth = call.argument("targetWidth") == null ? 0 : (int) call.argument("targetWidth"); int targetHeight = call.argument("targetHeight") == null ? 0 : (int) call.argument("targetHeight"); int quality = call.argument("quality"); - File file = new File(fileName); + compressImage(result, fileName, resizePercentage, targetWidth, targetHeight, quality); + } else if (call.method.equals("getImageProperties")) { + String fileName = call.argument("file"); - if(!file.exists()) { - result.error("file does not exist", fileName, null); - return; - } + getImageProperties(result, fileName); + } else if (call.method.equals("cropImage")) { + String fileName = call.argument("file"); + int originX = call.argument("originX"); + int originY = call.argument("originY"); + int width = call.argument("width"); + int height = call.argument("height"); - Bitmap bmp = BitmapFactory.decodeFile(fileName); - ByteArrayOutputStream bos = new ByteArrayOutputStream(); + cropImage(result, fileName, originX, originY, width, height); + } else if (call.method.equals("getPlatformVersion")) { + result.success("Android " + android.os.Build.VERSION.RELEASE); + } else { + result.notImplemented(); + } + } - int newWidth = targetWidth == 0 ? (bmp.getWidth() / 100 * resizePercentage) : targetWidth; - int newHeight = targetHeight == 0 ? (bmp.getHeight() / 100 * resizePercentage) : targetHeight; + private void compressImage(MethodChannel.Result result, String fileName, int resizePercentage, int targetWidth, int targetHeight, int quality) { + File file = new File(fileName); - bmp = Bitmap.createScaledBitmap( - bmp, newWidth, newHeight, true); + if (!file.exists()) { + result.error("file does not exist", fileName, null); + return; + } - // reconfigure bitmap to use RGB_565 before compressing - // fixes https://github.com/btastic/flutter_native_image/issues/47 - Bitmap newBmp = bmp.copy(Bitmap.Config.RGB_565, false); - newBmp.compress(Bitmap.CompressFormat.JPEG, quality, bos); + Bitmap bmp = BitmapFactory.decodeFile(fileName); + if (bmp == null) { + result.error("File could not be decoded by BitmapFactory", fileName, null); + return; + } - try { - String outputFileName = File.createTempFile( - getFilenameWithoutExtension(file).concat("_compressed"), - ".jpg", - context.getExternalCacheDir() - ).getPath(); + int newWidth = targetWidth == 0 ? (bmp.getWidth() / 100 * resizePercentage) : targetWidth; + int newHeight = targetHeight == 0 ? (bmp.getHeight() / 100 * resizePercentage) : targetHeight; - OutputStream outputStream = new FileOutputStream(outputFileName); - bos.writeTo(outputStream); + bmp = Bitmap.createScaledBitmap(bmp, newWidth, newHeight, true); - copyExif(fileName, outputFileName); + // reconfigure bitmap to use RGB_565 before compressing + // fixes https://github.com/btastic/flutter_native_image/issues/47 + Bitmap newBmp = bmp.copy(Bitmap.Config.RGB_565, false); + ByteArrayOutputStream bos = new ByteArrayOutputStream(); + newBmp.compress(Bitmap.CompressFormat.JPEG, quality, bos); - result.success(outputFileName); - } catch (FileNotFoundException e) { - e.printStackTrace(); - result.error("file does not exist", fileName, null); - } catch (IOException e) { - e.printStackTrace(); - result.error("something went wrong", fileName, null); + OutputStream outputStream = null; + try { + String outputFileName = File.createTempFile( + getFilenameWithoutExtension(file).concat("_compressed"), + ".jpg", + context.getExternalCacheDir() + ).getPath(); + + outputStream = new FileOutputStream(outputFileName); + bos.writeTo(outputStream); + + copyExif (fileName, outputFileName); + + result.success(outputFileName); + } catch (FileNotFoundException e) { + e.printStackTrace(); + result.error("file does not exist", fileName, null); + } catch (IOException e) { + e.printStackTrace(); + result.error("something went wrong", fileName, null); + } finally { + if (outputStream != null) { + try { + outputStream.close(); + } catch (IOException e) { + e.printStackTrace(); + } } + } + } + + private void getImageProperties(MethodChannel.Result result, String fileName) { + File file = new File(fileName); + if (!file.exists()) { + result.error("file does not exist", fileName, null); return; } - if(call.method.equals("getImageProperties")) { - String fileName = call.argument("file"); - File file = new File(fileName); - if(!file.exists()) { - result.error("file does not exist", fileName, null); - return; - } + BitmapFactory.Options options = new BitmapFactory.Options(); + options.inJustDecodeBounds = true; + BitmapFactory.decodeFile(fileName,options); + HashMap properties = new HashMap(); + properties.put("width", options.outWidth); + properties.put("height", options.outHeight); - BitmapFactory.Options options = new BitmapFactory.Options(); - options.inJustDecodeBounds = true; - BitmapFactory.decodeFile(fileName,options); - HashMap properties = new HashMap(); - properties.put("width", options.outWidth); - properties.put("height", options.outHeight); - - int orientation = ExifInterface.ORIENTATION_UNDEFINED; - try { - ExifInterface exif = new ExifInterface(fileName); - orientation = exif.getAttributeInt(ExifInterface.TAG_ORIENTATION, ExifInterface.ORIENTATION_UNDEFINED); - } catch(IOException ex) { - // EXIF could not be read from the file; ignore - } - properties.put("orientation", orientation); + int orientation = ExifInterface.ORIENTATION_UNDEFINED; + try { + ExifInterface exif = new ExifInterface(fileName); + orientation = exif.getAttributeInt(ExifInterface.TAG_ORIENTATION, ExifInterface.ORIENTATION_UNDEFINED); + } catch (IOException ex) { + // EXIF could not be read from the file; ignore + } + properties.put("orientation", orientation); + + result.success(properties); + } + + private void cropImage(MethodChannel.Result result, String fileName, int originX, int originY, int width, int height) { + File file = new File(fileName); - result.success(properties); + if (!file.exists()) { + result.error("file does not exist", fileName, null); return; } - if(call.method.equals("cropImage")) { - String fileName = call.argument("file"); - int originX = call.argument("originX"); - int originY = call.argument("originY"); - int width = call.argument("width"); - int height = call.argument("height"); - File file = new File(fileName); + Boolean isPNG = fileName.toLowerCase().endsWith(".png"); + Bitmap.CompressFormat format = isPNG ? Bitmap.CompressFormat.PNG : Bitmap.CompressFormat.JPEG; + String extension = isPNG ? ".png" : ".jpg"; - if(!file.exists()) { - result.error("file does not exist", fileName, null); - return; - } - Boolean isPNG = fileName.toLowerCase().endsWith(".png"); - Bitmap.CompressFormat format = isPNG ? Bitmap.CompressFormat.PNG : Bitmap.CompressFormat.JPEG; - String extension = isPNG ? ".png" : ".jpg"; - - Bitmap bmp = BitmapFactory.decodeFile(fileName); - ByteArrayOutputStream bos = new ByteArrayOutputStream(); - try { - bmp = Bitmap.createBitmap(bmp, originX, originY, width, height); - } catch(IllegalArgumentException e) { - e.printStackTrace(); - result.error("bounds are outside of the dimensions of the source image", fileName, null); - } + Bitmap bmp = BitmapFactory.decodeFile(fileName); + ByteArrayOutputStream bos = new ByteArrayOutputStream(); + try { + bmp = Bitmap.createBitmap(bmp, originX, originY, width, height); + } catch (IllegalArgumentException e) { + e.printStackTrace(); + result.error("bounds are outside of the dimensions of the source image", fileName, null); + } - bmp.compress(format, 100, bos); - bmp.recycle(); - OutputStream outputStream = null; - try { - String outputFileName = File.createTempFile( - getFilenameWithoutExtension(file).concat("_cropped"), - extension, - context.getExternalCacheDir() - ).getPath(); - - - outputStream = new FileOutputStream(outputFileName); - bos.writeTo(outputStream); - - copyExif(fileName, outputFileName); - - result.success(outputFileName); - } catch (FileNotFoundException e) { - e.printStackTrace(); - result.error("file does not exist", fileName, null); - } catch (IOException e) { - e.printStackTrace(); - result.error("something went wrong", fileName, null); - }finally { - if (outputStream != null) { - try { - outputStream.close(); - } catch (IOException e) { - e.printStackTrace(); - } + bmp.compress(format, 100, bos); + bmp.recycle(); + + OutputStream outputStream = null; + try { + String outputFileName = File.createTempFile( + getFilenameWithoutExtension(file).concat("_cropped"), + extension, + context.getExternalCacheDir() + ).getPath(); + + outputStream = new FileOutputStream(outputFileName); + bos.writeTo(outputStream); + + copyExif(fileName, outputFileName); + + result.success(outputFileName); + } catch (FileNotFoundException e) { + e.printStackTrace(); + result.error("file does not exist", fileName, null); + } catch (IOException e) { + e.printStackTrace(); + result.error("something went wrong", fileName, null); + } finally { + if (outputStream != null) { + try { + outputStream.close(); + } catch (IOException e) { + e.printStackTrace(); } } - - - - return; - } - if (call.method.equals("getPlatformVersion")) { - result.success("Android " + android.os.Build.VERSION.RELEASE); - } else { - result.notImplemented(); } } @@ -182,28 +219,7 @@ private void copyExif(String filePathOri, String filePathDest) { ExifInterface oldExif = new ExifInterface(filePathOri); ExifInterface newExif = new ExifInterface(filePathDest); - List attributes = - Arrays.asList( - "FNumber", - "ExposureTime", - "ISOSpeedRatings", - "GPSAltitude", - "GPSAltitudeRef", - "FocalLength", - "GPSDateStamp", - "WhiteBalance", - "GPSProcessingMethod", - "GPSTimeStamp", - "DateTime", - "Flash", - "GPSLatitude", - "GPSLatitudeRef", - "GPSLongitude", - "GPSLongitudeRef", - "Make", - "Model", - "Orientation"); - for (String attribute : attributes) { + for (String attribute : ExifAttributes) { setIfNotNull(oldExif, newExif, attribute); } @@ -220,11 +236,6 @@ private void setIfNotNull(ExifInterface oldExif, ExifInterface newExif, String p } } - private static String pathComponent(String filename) { - int i = filename.lastIndexOf(File.separator); - return (i > -1) ? filename.substring(0, i) : filename; - } - private static String getFilenameWithoutExtension(File file) { String fileName = file.getName();