55import android .graphics .Canvas ;
66import android .graphics .Matrix ;
77import android .graphics .Paint ;
8+ import android .media .ExifInterface ;
9+ import android .net .Uri ;
810import android .util .Base64 ;
911
1012import com .facebook .react .bridge .ReactApplicationContext ;
1113import com .reactnativecompressor .Image .utils .ImageCompressorOptions ;
1214import com .reactnativecompressor .Image .utils .ImageSize ;
1315
1416import java .io .ByteArrayOutputStream ;
17+ import java .io .File ;
18+ import java .io .FileNotFoundException ;
1519import java .io .FileOutputStream ;
20+ import java .io .IOException ;
21+ import java .net .MalformedURLException ;
22+
1623import static com .reactnativecompressor .Utils .Utils .generateCacheFilePath ;
1724
1825
1926public class ImageCompressor {
27+ private static final float autoCompressMaxHeight = 1280.0f ;
28+ private static final float audoCompressMaxWidth = 1280.0f ;
29+
30+ public static String getRNFileUrl (String filePath ) {
31+ File returnAbleFile = new File (filePath );
32+ try {
33+ filePath = returnAbleFile .toURL ().toString ();
34+ } catch (MalformedURLException e ) {
35+ e .printStackTrace ();
36+ }
37+ return filePath ;
38+ }
39+
2040 public static ImageSize findActualSize (Bitmap image , int maxWidth , int maxHeight ) {
2141 final float width = (float ) image .getWidth ();
2242 final float height = (float ) image .getHeight ();
@@ -40,11 +60,8 @@ public static Bitmap decodeImage(String value) {
4060 }
4161
4262 public static Bitmap loadImage (String value ) {
43- String filePath =value ;
44- if (value .indexOf ("file:/" )>-1 )
45- {
46- filePath =value .substring ( value .indexOf ( ':' ) + 1 );
47- }
63+ Uri uri = Uri .parse (value );
64+ String filePath = uri .getPath ();
4865 Bitmap bitmap = BitmapFactory .decodeFile (filePath );
4966 return bitmap ;
5067 }
@@ -63,7 +80,7 @@ public static String encodeImage(ByteArrayOutputStream imageDataByteArrayOutputS
6380 try {
6481 FileOutputStream fos =new FileOutputStream (outputUri );
6582 imageDataByteArrayOutputStream .writeTo (fos );
66- return "file:/" + outputUri ;
83+ return getRNFileUrl ( outputUri ) ;
6784 } catch (Exception e ) {
6885 e .printStackTrace ();
6986 }
@@ -99,4 +116,136 @@ public static ByteArrayOutputStream compress(Bitmap image, ImageCompressorOption
99116 image .compress (format , Math .round (100 * quality ), stream );
100117 return stream ;
101118 }
119+
120+ public static String manualCompressImage (String imagePath ,ImageCompressorOptions options , ReactApplicationContext reactContext ) {
121+ final Bitmap image = options .input == ImageCompressorOptions .InputType .base64
122+ ? ImageCompressor .decodeImage (imagePath )
123+ : ImageCompressor .loadImage (imagePath );
124+
125+ final Bitmap resizedImage = ImageCompressor .resize (image , options .maxWidth , options .maxHeight );
126+ final ByteArrayOutputStream imageDataByteArrayOutputStream = ImageCompressor .compress (resizedImage , options .output , options .quality );
127+ Boolean isBase64 =options .returnableOutputType ==ImageCompressorOptions .ReturnableOutputType .base64 ;
128+
129+ String returnableResult = ImageCompressor .encodeImage (imageDataByteArrayOutputStream ,isBase64 ,image ,options .output .toString (),reactContext );
130+ return returnableResult ;
131+ }
132+
133+
134+ public static String autoCompressImage (String imagePath ,String outputExtension , ReactApplicationContext reactContext ) {
135+
136+ Uri uri = Uri .parse (imagePath );
137+ imagePath = uri .getPath ();
138+ Bitmap scaledBitmap = null ;
139+
140+ BitmapFactory .Options options = new BitmapFactory .Options ();
141+ options .inJustDecodeBounds = true ;
142+ Bitmap bmp = BitmapFactory .decodeFile (imagePath , options );
143+
144+ int actualHeight = options .outHeight ;
145+ int actualWidth = options .outWidth ;
146+
147+ float imgRatio = (float ) actualWidth / (float ) actualHeight ;
148+ float maxRatio = audoCompressMaxWidth / autoCompressMaxHeight ;
149+
150+ if (actualHeight > autoCompressMaxHeight || actualWidth > audoCompressMaxWidth ) {
151+ if (imgRatio < maxRatio ) {
152+ imgRatio = autoCompressMaxHeight / actualHeight ;
153+ actualWidth = (int ) (imgRatio * actualWidth );
154+ actualHeight = (int ) autoCompressMaxHeight ;
155+ } else if (imgRatio > maxRatio ) {
156+ imgRatio = audoCompressMaxWidth / actualWidth ;
157+ actualHeight = (int ) (imgRatio * actualHeight );
158+ actualWidth = (int ) audoCompressMaxWidth ;
159+ } else {
160+ actualHeight = (int ) autoCompressMaxHeight ;
161+ actualWidth = (int ) audoCompressMaxWidth ;
162+
163+ }
164+ }
165+
166+ options .inSampleSize = calculateInSampleSize (options , actualWidth , actualHeight );
167+ options .inJustDecodeBounds = false ;
168+ options .inDither = false ;
169+ options .inPurgeable = true ;
170+ options .inInputShareable = true ;
171+ options .inTempStorage = new byte [16 * 1024 ];
172+
173+ try {
174+ bmp = BitmapFactory .decodeFile (imagePath , options );
175+ } catch (OutOfMemoryError exception ) {
176+ exception .printStackTrace ();
177+
178+ }
179+ try {
180+ scaledBitmap = Bitmap .createBitmap (actualWidth , actualHeight , Bitmap .Config .RGB_565 );
181+ } catch (OutOfMemoryError exception ) {
182+ exception .printStackTrace ();
183+ }
184+
185+ float ratioX = actualWidth / (float ) options .outWidth ;
186+ float ratioY = actualHeight / (float ) options .outHeight ;
187+ float middleX = actualWidth / 2.0f ;
188+ float middleY = actualHeight / 2.0f ;
189+
190+ Matrix scaleMatrix = new Matrix ();
191+ scaleMatrix .setScale (ratioX , ratioY , middleX , middleY );
192+
193+ Canvas canvas = new Canvas (scaledBitmap );
194+ canvas .setMatrix (scaleMatrix );
195+ canvas .drawBitmap (bmp , middleX - bmp .getWidth () / 2 , middleY - bmp .getHeight () / 2 , new Paint (Paint .FILTER_BITMAP_FLAG ));
196+
197+ if (bmp !=null )
198+ {
199+ bmp .recycle ();
200+ }
201+
202+ ExifInterface exif ;
203+ try {
204+ exif = new ExifInterface (imagePath );
205+ int orientation = exif .getAttributeInt (ExifInterface .TAG_ORIENTATION , 0 );
206+ Matrix matrix = new Matrix ();
207+ if (orientation == 6 ) {
208+ matrix .postRotate (90 );
209+ } else if (orientation == 3 ) {
210+ matrix .postRotate (180 );
211+ } else if (orientation == 8 ) {
212+ matrix .postRotate (270 );
213+ }
214+ scaledBitmap = Bitmap .createBitmap (scaledBitmap , 0 , 0 , scaledBitmap .getWidth (), scaledBitmap .getHeight (), matrix , true );
215+ } catch (IOException e ) {
216+ e .printStackTrace ();
217+ }
218+ FileOutputStream out = null ;
219+ String filepath = generateCacheFilePath (outputExtension ,reactContext );;
220+ try {
221+ out = new FileOutputStream (filepath );
222+
223+ //write the compressed bitmap at the destination specified by filename.
224+ scaledBitmap .compress (Bitmap .CompressFormat .JPEG , 80 , out );
225+
226+ } catch (FileNotFoundException e ) {
227+ e .printStackTrace ();
228+ }
229+ return getRNFileUrl (filepath );
230+ }
231+
232+ public static int calculateInSampleSize (BitmapFactory .Options options , int reqWidth , int reqHeight ) {
233+ final int height = options .outHeight ;
234+ final int width = options .outWidth ;
235+ int inSampleSize = 1 ;
236+
237+ if (height > reqHeight || width > reqWidth ) {
238+ final int heightRatio = Math .round ((float ) height / (float ) reqHeight );
239+ final int widthRatio = Math .round ((float ) width / (float ) reqWidth );
240+ inSampleSize = heightRatio < widthRatio ? heightRatio : widthRatio ;
241+ }
242+ final float totalPixels = width * height ;
243+ final float totalReqPixelsCap = reqWidth * reqHeight * 2 ;
244+
245+ while (totalPixels / (inSampleSize * inSampleSize ) > totalReqPixelsCap ) {
246+ inSampleSize ++;
247+ }
248+
249+ return inSampleSize ;
250+ }
102251}
0 commit comments