Add ability to control size by only specifying width + made orientation optionnal. see #768

This commit is contained in:
Michaël Villeneuve 2018-02-23 14:54:45 +01:00
parent e064bab7db
commit 983337d9f8

View File

@ -24,18 +24,18 @@ import java.io.FileOutputStream;
import java.io.IOException;
public class ResolveTakenPictureAsyncTask extends AsyncTask<Void, Void, WritableMap> {
private static final String ERROR_TAG = "E_TAKING_PICTURE_FAILED";
private Promise mPromise;
private byte[] mImageData;
private ReadableMap mOptions;
private File mCacheDirectory;
private Bitmap mBitmap;
private static final String ERROR_TAG = "E_TAKING_PICTURE_FAILED";
private Promise mPromise;
private byte[] mImageData;
private ReadableMap mOptions;
private File mCacheDirectory;
private Bitmap mBitmap;
public ResolveTakenPictureAsyncTask(byte[] imageData, Promise promise, ReadableMap options) {
mPromise = promise;
mOptions = options;
mImageData = imageData;
}
public ResolveTakenPictureAsyncTask(byte[] imageData, Promise promise, ReadableMap options) {
mPromise = promise;
mOptions = options;
mImageData = imageData;
}
public ResolveTakenPictureAsyncTask(byte[] imageData, Promise promise, ReadableMap options, File cacheDirectory) {
mPromise = promise;
@ -44,95 +44,97 @@ public class ResolveTakenPictureAsyncTask extends AsyncTask<Void, Void, Writable
mCacheDirectory = cacheDirectory;
}
private int getQuality() {
return (int) (mOptions.getDouble("quality") * 100);
}
private int getQuality() {
return (int) (mOptions.getDouble("quality") * 100);
}
@Override
protected WritableMap doInBackground(Void... voids) {
WritableMap response = Arguments.createMap();
ByteArrayInputStream inputStream = null;
@Override
protected WritableMap doInBackground(Void... voids) {
WritableMap response = Arguments.createMap();
ByteArrayInputStream inputStream = null;
// we need the stream only for photos from a device
if (mBitmap == null) {
mBitmap = BitmapFactory.decodeByteArray(mImageData, 0, mImageData.length);
inputStream = new ByteArrayInputStream(mImageData);
}
// we need the stream only for photos from a device
if (mBitmap == null) {
mBitmap = BitmapFactory.decodeByteArray(mImageData, 0, mImageData.length);
inputStream = new ByteArrayInputStream(mImageData);
}
try {
if (inputStream != null) {
if (mOptions.hasKey("width") && mOptions.hasKey("height")) {
mBitmap = resizeBitmap(mBitmap, mOptions.getInteger("width"), mOptions.getInteger("height"));
}
ExifInterface exifInterface = new ExifInterface(inputStream);
// Get orientation of the image from mImageData via inputStream
int orientation = exifInterface.getAttributeInt(
ExifInterface.TAG_ORIENTATION,
ExifInterface.ORIENTATION_UNDEFINED
);
try {
if (inputStream != null) {
ExifInterface exifInterface = new ExifInterface(inputStream);
// Rotate the bitmap to the proper orientation if needed
if (orientation != ExifInterface.ORIENTATION_UNDEFINED) {
mBitmap = rotateBitmap(mBitmap, getImageRotation(orientation));
}
// Get orientation of the image from mImageData via inputStream
int orientation = exifInterface.getAttributeInt(ExifInterface.TAG_ORIENTATION,
ExifInterface.ORIENTATION_UNDEFINED);
if (mOptions.hasKey("mirrorImage") && mOptions.getBoolean("mirrorImage")) {
mBitmap = flipHorizontally(mBitmap);
}
if (mOptions.hasKey("width")) {
mBitmap = resizeBitmap(mBitmap, mOptions.getInt("width"));
}
// Write Exif data to the response if requested
if (mOptions.hasKey("exif") && mOptions.getBoolean("exif")) {
WritableMap exifData = RNCameraViewHelper.getExifData(exifInterface);
response.putMap("exif", exifData);
}
}
// Rotate the bitmap to the proper orientation if needed and asked
if (mOptions.hasKey("fixOrientation") && mOptions.getBoolean("fixOrientation")
&& orientation != ExifInterface.ORIENTATION_UNDEFINED) {
mBitmap = rotateBitmap(mBitmap, getImageRotation(orientation));
}
// Upon rotating, write the image's dimensions to the response
response.putInt("width", mBitmap.getWidth());
response.putInt("height", mBitmap.getHeight());
if (mOptions.hasKey("mirrorImage") && mOptions.getBoolean("mirrorImage")) {
mBitmap = flipHorizontally(mBitmap);
}
// Cache compressed image in imageStream
ByteArrayOutputStream imageStream = new ByteArrayOutputStream();
mBitmap.compress(Bitmap.CompressFormat.JPEG, getQuality(), imageStream);
// Write Exif data to the response if requested
if (mOptions.hasKey("exif") && mOptions.getBoolean("exif")) {
WritableMap exifData = RNCameraViewHelper.getExifData(exifInterface);
response.putMap("exif", exifData);
}
// Write compressed image to file in cache directory
String filePath = writeStreamToFile(imageStream);
File imageFile = new File(filePath);
String fileUri = Uri.fromFile(imageFile).toString();
response.putString("uri", fileUri);
}
// Write base64-encoded image to the response if requested
if (mOptions.hasKey("base64") && mOptions.getBoolean("base64")) {
response.putString("base64", Base64.encodeToString(imageStream.toByteArray(), Base64.DEFAULT));
}
// Upon rotating, write the image's dimensions to the response
response.putInt("width", mBitmap.getWidth());
response.putInt("height", mBitmap.getHeight());
// Cleanup
imageStream.close();
if (inputStream != null) {
inputStream.close();
inputStream = null;
}
// Cache compressed image in imageStream
ByteArrayOutputStream imageStream = new ByteArrayOutputStream();
mBitmap.compress(Bitmap.CompressFormat.JPEG, getQuality(), imageStream);
return response;
} catch (Resources.NotFoundException e) {
mPromise.reject(ERROR_TAG, "Documents directory of the app could not be found.", e);
e.printStackTrace();
} catch (IOException e) {
mPromise.reject(ERROR_TAG, "An unknown I/O exception has occurred.", e);
e.printStackTrace();
} finally {
try {
if (inputStream != null) {
inputStream.close();
}
} catch (IOException e) {
e.printStackTrace();
}
}
// Write compressed image to file in cache directory
String filePath = writeStreamToFile(imageStream);
File imageFile = new File(filePath);
String fileUri = Uri.fromFile(imageFile).toString();
response.putString("uri", fileUri);
// An exception had to occur, promise has already been rejected. Do not try to resolve it again.
return null;
}
// Write base64-encoded image to the response if requested
if (mOptions.hasKey("base64") && mOptions.getBoolean("base64")) {
response.putString("base64", Base64.encodeToString(imageStream.toByteArray(), Base64.DEFAULT));
}
// Cleanup
imageStream.close();
if (inputStream != null) {
inputStream.close();
inputStream = null;
}
return response;
} catch (Resources.NotFoundException e) {
mPromise.reject(ERROR_TAG, "Documents directory of the app could not be found.", e);
e.printStackTrace();
} catch (IOException e) {
mPromise.reject(ERROR_TAG, "An unknown I/O exception has occurred.", e);
e.printStackTrace();
} finally {
try {
if (inputStream != null) {
inputStream.close();
}
} catch (IOException e) {
e.printStackTrace();
}
}
// An exception had to occur, promise has already been rejected. Do not try to resolve it again.
return null;
}
private Bitmap rotateBitmap(Bitmap source, int angle) {
Matrix matrix = new Matrix();
@ -140,18 +142,12 @@ public class ResolveTakenPictureAsyncTask extends AsyncTask<Void, Void, Writable
return Bitmap.createBitmap(source, 0, 0, source.getWidth(), source.getHeight(), matrix, true);
}
public Bitmap resizeBitmap(Bitmap bm, int newWidth, int newHeight) {
private Bitmap resizeBitmap(Bitmap bm, int newWidth) {
int width = bm.getWidth();
int height = bm.getHeight();
float scaleWidth = ((float) newWidth) / width;
float scaleHeight = ((float) newHeight) / height;
float scaleRatio = (float) newWidth / (float) width;
Matrix matrix = new Matrix();
matrix.postScale(scaleWidth, scaleHeight);
Bitmap resizedBitmap = Bitmap.createBitmap(bm, 0, 0, width, height, matrix, false);
bm.recycle();
return resizedBitmap;
return Bitmap.createScaledBitmap(bm, newWidth, (int) (height * scaleRatio), true);
}
private Bitmap flipHorizontally(Bitmap source) {
@ -165,56 +161,56 @@ public class ResolveTakenPictureAsyncTask extends AsyncTask<Void, Void, Writable
private int getImageRotation(int orientation) {
int rotationDegrees = 0;
switch (orientation) {
case ExifInterface.ORIENTATION_ROTATE_90:
rotationDegrees = 90;
break;
case ExifInterface.ORIENTATION_ROTATE_180:
rotationDegrees = 180;
break;
case ExifInterface.ORIENTATION_ROTATE_270:
rotationDegrees = 270;
break;
case ExifInterface.ORIENTATION_ROTATE_90:
rotationDegrees = 90;
break;
case ExifInterface.ORIENTATION_ROTATE_180:
rotationDegrees = 180;
break;
case ExifInterface.ORIENTATION_ROTATE_270:
rotationDegrees = 270;
break;
}
return rotationDegrees;
}
private String writeStreamToFile(ByteArrayOutputStream inputStream) throws IOException {
String outputPath = null;
IOException exception = null;
FileOutputStream outputStream = null;
private String writeStreamToFile(ByteArrayOutputStream inputStream) throws IOException {
String outputPath = null;
IOException exception = null;
FileOutputStream outputStream = null;
try {
outputPath = RNFileUtils.getOutputFilePath(mCacheDirectory, ".jpg");
outputStream = new FileOutputStream(outputPath);
inputStream.writeTo(outputStream);
} catch (IOException e) {
e.printStackTrace();
exception = e;
} finally {
try {
if (outputStream != null) {
outputStream.close();
}
outputPath = RNFileUtils.getOutputFilePath(mCacheDirectory, ".jpg");
outputStream = new FileOutputStream(outputPath);
inputStream.writeTo(outputStream);
} catch (IOException e) {
e.printStackTrace();
exception = e;
} finally {
try {
if (outputStream != null) {
outputStream.close();
}
} catch (IOException e) {
e.printStackTrace();
}
}
if (exception != null) {
throw exception;
}
return outputPath;
}
@Override
protected void onPostExecute(WritableMap response) {
super.onPostExecute(response);
// If the response is not null everything went well and we can resolve the promise.
if (response != null) {
mPromise.resolve(response);
}
}
if (exception != null) {
throw exception;
}
return outputPath;
}
@Override
protected void onPostExecute(WritableMap response) {
super.onPostExecute(response);
// If the response is not null everything went well and we can resolve the promise.
if (response != null) {
mPromise.resolve(response);
}
}
}