4747import com .facebook .react .bridge .JSApplicationIllegalArgumentException ;
4848import com .facebook .react .bridge .ReadableMap ;
4949import com .facebook .infer .annotation .Assertions ;
50+ import com .facebook .react .bridge .WritableMap ;
51+ import com .facebook .react .bridge .WritableNativeMap ;
5052import com .facebook .react .common .ReactConstants ;
5153
5254/**
@@ -65,7 +67,7 @@ public class ImageEditorModule extends ReactContextBaseJavaModule {
6567 private static final String TEMP_FILE_PREFIX = "ReactNative_cropped_image_" ;
6668
6769 /** Compress quality of the output file. */
68- private static final int COMPRESS_QUALITY = 90 ;
70+ private static final int COMPRESS_QUALITY = 100 ;
6971
7072 @ SuppressLint ("InlinedApi" ) private static final String [] EXIF_ATTRIBUTES = new String [] {
7173 ExifInterface .TAG_APERTURE ,
@@ -182,20 +184,25 @@ public void cropImage(
182184 throw new JSApplicationIllegalArgumentException ("Please specify a URI" );
183185 }
184186
187+ double quality = options .hasKey ("quality" ) ? options .getDouble ("quality" ) : 1 ;
188+
185189 CropTask cropTask = new CropTask (
186190 getReactApplicationContext (),
187191 uri ,
188192 (int ) offset .getDouble ("x" ),
189193 (int ) offset .getDouble ("y" ),
190194 (int ) size .getDouble ("width" ),
191195 (int ) size .getDouble ("height" ),
196+ quality ,
192197 promise );
198+
193199 if (options .hasKey ("displaySize" )) {
194200 ReadableMap targetSize = options .getMap ("displaySize" );
195201 cropTask .setTargetSize (
196202 (int ) targetSize .getDouble ("width" ),
197203 (int ) targetSize .getDouble ("height" ));
198204 }
205+
199206 cropTask .executeOnExecutor (AsyncTask .THREAD_POOL_EXECUTOR );
200207 }
201208
@@ -208,6 +215,7 @@ private static class CropTask extends GuardedAsyncTask<Void, Void> {
208215 final int mHeight ;
209216 int mTargetWidth = 0 ;
210217 int mTargetHeight = 0 ;
218+ double mQuality = 1 ;
211219 final Promise mPromise ;
212220
213221 private CropTask (
@@ -217,6 +225,7 @@ private CropTask(
217225 int y ,
218226 int width ,
219227 int height ,
228+ double quality ,
220229 Promise promise ) {
221230 super (context );
222231 if (x < 0 || y < 0 || width <= 0 || height <= 0 ) {
@@ -230,6 +239,7 @@ private CropTask(
230239 mWidth = width ;
231240 mHeight = height ;
232241 mPromise = promise ;
242+ mQuality = quality ;
233243 }
234244
235245 public void setTargetSize (int width , int height ) {
@@ -276,13 +286,17 @@ protected void doInBackgroundGuarded(Void... params) {
276286 }
277287
278288 File tempFile = createTempFile (mContext , mimeType );
279- writeCompressedBitmapToFile (cropped , mimeType , tempFile );
289+ writeCompressedBitmapToFile (cropped , mimeType , tempFile , mQuality );
280290
281291 if (mimeType .equals ("image/jpeg" )) {
282292 copyExif (mContext , Uri .parse (mUri ), tempFile );
283293 }
284294
285- mPromise .resolve (Uri .fromFile (tempFile ).toString ());
295+ WritableMap response = new WritableNativeMap ();
296+ response .putString ("uri" , Uri .fromFile (tempFile ).toString ());
297+ response .putInt ("width" , cropped .getWidth ());
298+ response .putInt ("height" , cropped .getHeight ());
299+ mPromise .resolve (response );
286300 } catch (Exception e ) {
287301 mPromise .reject (e );
288302 }
@@ -449,11 +463,11 @@ private static Bitmap.CompressFormat getCompressFormatForType(String type) {
449463 return Bitmap .CompressFormat .JPEG ;
450464 }
451465
452- private static void writeCompressedBitmapToFile (Bitmap cropped , String mimeType , File tempFile )
466+ private static void writeCompressedBitmapToFile (Bitmap cropped , String mimeType , File tempFile , double quality )
453467 throws IOException {
454468 OutputStream out = new FileOutputStream (tempFile );
455469 try {
456- cropped .compress (getCompressFormatForType (mimeType ), COMPRESS_QUALITY , out );
470+ cropped .compress (getCompressFormatForType (mimeType ), ( int ) quality * COMPRESS_QUALITY , out );
457471 } finally {
458472 if (out != null ) {
459473 out .close ();
0 commit comments