| // Copyright 2019 The Flutter Authors. All rights reserved. |
| // Use of this source code is governed by a BSD-style license that can be |
| // found in the LICENSE file. |
| |
| package io.flutter.plugins.imagepicker; |
| |
| import android.graphics.Bitmap; |
| import android.graphics.BitmapFactory; |
| import android.util.Log; |
| import java.io.ByteArrayOutputStream; |
| import java.io.File; |
| import java.io.FileOutputStream; |
| import java.io.IOException; |
| |
| class ImageResizer { |
| private final File externalFilesDirectory; |
| private final ExifDataCopier exifDataCopier; |
| |
| ImageResizer(File externalFilesDirectory, ExifDataCopier exifDataCopier) { |
| this.externalFilesDirectory = externalFilesDirectory; |
| this.exifDataCopier = exifDataCopier; |
| } |
| |
| /** |
| * If necessary, resizes the image located in imagePath and then returns the path for the scaled |
| * image. |
| * |
| * <p>If no resizing is needed, returns the path for the original image. |
| */ |
| String resizeImageIfNeeded( |
| String imagePath, Double maxWidth, Double maxHeight, int imageQuality) { |
| boolean shouldScale = |
| maxWidth != null || maxHeight != null || (imageQuality > -1 && imageQuality < 101); |
| |
| if (!shouldScale) { |
| return imagePath; |
| } |
| |
| try { |
| File scaledImage = resizedImage(imagePath, maxWidth, maxHeight, imageQuality); |
| exifDataCopier.copyExif(imagePath, scaledImage.getPath()); |
| |
| return scaledImage.getPath(); |
| } catch (IOException e) { |
| throw new RuntimeException(e); |
| } |
| } |
| |
| private File resizedImage(String path, Double maxWidth, Double maxHeight, int imageQuality) |
| throws IOException { |
| Bitmap bmp = BitmapFactory.decodeFile(path); |
| double originalWidth = bmp.getWidth() * 1.0; |
| double originalHeight = bmp.getHeight() * 1.0; |
| |
| if (imageQuality < 0 || imageQuality > 100) { |
| imageQuality = 100; |
| } |
| |
| boolean hasMaxWidth = maxWidth != null; |
| boolean hasMaxHeight = maxHeight != null; |
| |
| Double width = hasMaxWidth ? Math.min(originalWidth, maxWidth) : originalWidth; |
| Double height = hasMaxHeight ? Math.min(originalHeight, maxHeight) : originalHeight; |
| |
| boolean shouldDownscaleWidth = hasMaxWidth && maxWidth < originalWidth; |
| boolean shouldDownscaleHeight = hasMaxHeight && maxHeight < originalHeight; |
| boolean shouldDownscale = shouldDownscaleWidth || shouldDownscaleHeight; |
| |
| if (shouldDownscale) { |
| double downscaledWidth = (height / originalHeight) * originalWidth; |
| double downscaledHeight = (width / originalWidth) * originalHeight; |
| |
| if (width < height) { |
| if (!hasMaxWidth) { |
| width = downscaledWidth; |
| } else { |
| height = downscaledHeight; |
| } |
| } else if (height < width) { |
| if (!hasMaxHeight) { |
| height = downscaledHeight; |
| } else { |
| width = downscaledWidth; |
| } |
| } else { |
| if (originalWidth < originalHeight) { |
| width = downscaledWidth; |
| } else if (originalHeight < originalWidth) { |
| height = downscaledHeight; |
| } |
| } |
| } |
| |
| Bitmap scaledBmp = Bitmap.createScaledBitmap(bmp, width.intValue(), height.intValue(), false); |
| ByteArrayOutputStream outputStream = new ByteArrayOutputStream(); |
| boolean saveAsPNG = bmp.hasAlpha(); |
| if (saveAsPNG) { |
| Log.d( |
| "ImageResizer", |
| "image_picker: compressing is not supported for type PNG. Returning the image with original quality"); |
| } |
| scaledBmp.compress( |
| saveAsPNG ? Bitmap.CompressFormat.PNG : Bitmap.CompressFormat.JPEG, |
| imageQuality, |
| outputStream); |
| |
| String[] pathParts = path.split("/"); |
| String imageName = pathParts[pathParts.length - 1]; |
| |
| File imageFile = new File(externalFilesDirectory, "/scaled_" + imageName); |
| FileOutputStream fileOutput = new FileOutputStream(imageFile); |
| fileOutput.write(outputStream.toByteArray()); |
| fileOutput.close(); |
| return imageFile; |
| } |
| } |