30
30
import android .os .Bundle ;
31
31
import android .os .Handler ;
32
32
import android .provider .MediaStore ;
33
+ import android .util .Pair ;
33
34
import android .view .View ;
34
35
import android .view .Window ;
35
36
import android .view .WindowManager ;
@@ -56,6 +57,7 @@ public class CropImageActivity extends MonitoredActivity {
56
57
private int maxX ;
57
58
private int maxY ;
58
59
private int exifRotation ;
60
+ private int exifScale ;
59
61
private boolean saveAsPng ;
60
62
61
63
private Uri sourceUri ;
@@ -64,7 +66,7 @@ public class CropImageActivity extends MonitoredActivity {
64
66
private boolean isSaving ;
65
67
66
68
private int sampleSize ;
67
- private RotateBitmap rotateBitmap ;
69
+ private Bitmap srcBitmap ;
68
70
private CropImageView imageView ;
69
71
private HighlightView cropView ;
70
72
@@ -75,7 +77,7 @@ public void onCreate(Bundle icicle) {
75
77
setupViews ();
76
78
77
79
loadInput ();
78
- if (rotateBitmap == null ) {
80
+ if (srcBitmap == null ) {
79
81
finish ();
80
82
return ;
81
83
}
@@ -120,6 +122,7 @@ public void onClick(View v) {
120
122
private void loadInput () {
121
123
Intent intent = getIntent ();
122
124
Bundle extras = intent .getExtras ();
125
+ Bitmap initialBitmap ;
123
126
124
127
if (extras != null ) {
125
128
aspectX = extras .getInt (Crop .Extra .ASPECT_X );
@@ -132,15 +135,32 @@ private void loadInput() {
132
135
133
136
sourceUri = intent .getData ();
134
137
if (sourceUri != null ) {
135
- exifRotation = CropUtil .getExifRotation (CropUtil .getFromMediaUri (this , getContentResolver (), sourceUri ));
136
-
138
+ Pair <Integer ,Integer > exifRotationTrans =
139
+ CropUtil .getExifRotationTranslation (
140
+ CropUtil .getFromMediaUri (this , getContentResolver (), sourceUri ));
141
+ exifRotation = exifRotationTrans .first ;
142
+ exifScale = exifRotationTrans .second ;
137
143
InputStream is = null ;
138
144
try {
139
145
sampleSize = calculateBitmapSampleSize (sourceUri );
140
146
is = getContentResolver ().openInputStream (sourceUri );
141
147
BitmapFactory .Options option = new BitmapFactory .Options ();
142
148
option .inSampleSize = sampleSize ;
143
- rotateBitmap = new RotateBitmap (BitmapFactory .decodeStream (is , null , option ), exifRotation );
149
+ initialBitmap = BitmapFactory .decodeStream (is , null , option );
150
+ int drawHeight = initialBitmap .getHeight ();
151
+ int drawWidth = initialBitmap .getWidth ();
152
+ if ((exifRotation != 0 ) || (exifScale != 1 )) {
153
+ Matrix matrix = new Matrix () ;
154
+ if (exifRotation != 0 ) {
155
+ matrix .preRotate (exifRotation );
156
+ }
157
+ if (exifScale != 1 ) {
158
+ matrix .postScale (exifScale , 1 );
159
+ }
160
+ srcBitmap = Bitmap .createBitmap (initialBitmap , 0 , 0 , drawWidth , drawHeight , matrix , true );
161
+ } else {
162
+ srcBitmap = initialBitmap ;
163
+ }
144
164
} catch (IOException e ) {
145
165
Log .e ("Error reading image: " + e .getMessage (), e );
146
166
setResultException (e );
@@ -151,6 +171,9 @@ private void loadInput() {
151
171
CropUtil .closeSilently (is );
152
172
}
153
173
}
174
+ else {
175
+ Log .e ("Source URI is null" );
176
+ }
154
177
}
155
178
156
179
private int calculateBitmapSampleSize (Uri bitmapUri ) throws IOException {
@@ -192,7 +215,7 @@ private void startCrop() {
192
215
if (isFinishing ()) {
193
216
return ;
194
217
}
195
- imageView .setImageRotateBitmapResetBase ( rotateBitmap , true );
218
+ imageView .setImageBitmapResetBase ( srcBitmap , true );
196
219
CropUtil .startBackgroundJob (this , null , getResources ().getString (R .string .crop__wait ),
197
220
new Runnable () {
198
221
public void run () {
@@ -219,13 +242,13 @@ public void run() {
219
242
private class Cropper {
220
243
221
244
private void makeDefault () {
222
- if (rotateBitmap == null ) {
245
+ if (srcBitmap == null ) {
223
246
return ;
224
247
}
225
248
226
249
HighlightView hv = new HighlightView (imageView );
227
- final int width = rotateBitmap .getWidth ();
228
- final int height = rotateBitmap .getHeight ();
250
+ final int width = srcBitmap .getWidth ();
251
+ final int height = srcBitmap .getHeight ();
229
252
230
253
Rect imageRect = new Rect (0 , 0 , width , height );
231
254
@@ -277,6 +300,8 @@ private void onSaveClicked() {
277
300
278
301
int outWidth = width ;
279
302
int outHeight = height ;
303
+ Log .e ("Crop Width = " + width );
304
+ Log .e ("Crop Height = " + height );
280
305
if (maxX > 0 && maxY > 0 && (width > maxX || height > maxY )) {
281
306
float ratio = (float ) width / (float ) height ;
282
307
if ((float ) maxX / (float ) maxY > ratio ) {
@@ -297,7 +322,7 @@ private void onSaveClicked() {
297
322
}
298
323
299
324
if (croppedImage != null ) {
300
- imageView .setImageRotateBitmapResetBase ( new RotateBitmap ( croppedImage , exifRotation ) , true );
325
+ imageView .setImageBitmapResetBase ( croppedImage , true );
301
326
imageView .center ();
302
327
imageView .highlightViews .clear ();
303
328
}
@@ -320,22 +345,20 @@ public void run() {
320
345
}
321
346
322
347
private Bitmap decodeRegionCrop (Rect rect , int outWidth , int outHeight ) {
323
- // Release memory now
324
- clearImageView ();
325
-
348
+ Matrix matrix = new Matrix ();
326
349
InputStream is = null ;
327
350
Bitmap croppedImage = null ;
351
+ boolean transformed = false ;
328
352
try {
329
353
is = getContentResolver ().openInputStream (sourceUri );
330
354
BitmapRegionDecoder decoder = BitmapRegionDecoder .newInstance (is , false );
331
355
final int width = decoder .getWidth ();
332
356
final int height = decoder .getHeight ();
333
357
334
- if (exifRotation != 0 ) {
335
- // Adjust crop area to account for image rotation
336
- Matrix matrix = new Matrix ();
337
- matrix .setRotate (-exifRotation );
338
-
358
+ if ((exifRotation != 0 ) || (exifScale != 1 )) {
359
+ // Adjust crop area to account for EXIF transformation so what you crop is what you get
360
+ matrix .preRotate (-exifRotation );
361
+ matrix .postScale (exifScale , 1 );
339
362
RectF adjusted = new RectF ();
340
363
matrix .mapRect (adjusted , new RectF (rect ));
341
364
@@ -345,11 +368,20 @@ private Bitmap decodeRegionCrop(Rect rect, int outWidth, int outHeight) {
345
368
}
346
369
347
370
try {
371
+ matrix .reset ();
348
372
croppedImage = decoder .decodeRegion (rect , new BitmapFactory .Options ());
349
- if (croppedImage != null && (rect .width () > outWidth || rect .height () > outHeight )) {
350
- Matrix matrix = new Matrix ();
351
- matrix .postScale ((float ) outWidth / rect .width (), (float ) outHeight / rect .height ());
352
- croppedImage = Bitmap .createBitmap (croppedImage , 0 , 0 , croppedImage .getWidth (), croppedImage .getHeight (), matrix , true );
373
+ if ((exifRotation != 0 ) || (exifScale != 1 )) {
374
+ transformed = true ;
375
+ // Remove the EXIF transformation from the cropped image so we can dispense with it altogether
376
+ matrix .preRotate (exifRotation );
377
+ matrix .postScale (exifScale , 1 );
378
+ }
379
+ if (rect .width () > outWidth || rect .height () > outHeight ) {
380
+ transformed = true ;
381
+ matrix .postScale (((float )outWidth )/((float )rect .width ()), ((float )outHeight )/((float )rect .height ()));
382
+ }
383
+ if (transformed ) {
384
+ croppedImage = Bitmap .createBitmap (croppedImage , 0 , 0 , croppedImage .getWidth (), croppedImage .getHeight (), matrix , true );
353
385
}
354
386
} catch (IllegalArgumentException e ) {
355
387
// Rethrow with some extra information
@@ -365,14 +397,16 @@ private Bitmap decodeRegionCrop(Rect rect, int outWidth, int outHeight) {
365
397
setResultException (e );
366
398
} finally {
367
399
CropUtil .closeSilently (is );
400
+ // Release memory now
401
+ clearImageView ();
368
402
}
369
403
return croppedImage ;
370
404
}
371
405
372
406
private void clearImageView () {
373
407
imageView .clear ();
374
- if (rotateBitmap != null ) {
375
- rotateBitmap .recycle ();
408
+ if (srcBitmap != null ) {
409
+ srcBitmap .recycle ();
376
410
}
377
411
System .gc ();
378
412
}
@@ -393,12 +427,6 @@ private void saveOutput(Bitmap croppedImage) {
393
427
} finally {
394
428
CropUtil .closeSilently (outputStream );
395
429
}
396
-
397
- CropUtil .copyExifRotation (
398
- CropUtil .getFromMediaUri (this , getContentResolver (), sourceUri ),
399
- CropUtil .getFromMediaUri (this , getContentResolver (), saveUri )
400
- );
401
-
402
430
setResultUri (saveUri );
403
431
}
404
432
@@ -416,8 +444,8 @@ public void run() {
416
444
@ Override
417
445
protected void onDestroy () {
418
446
super .onDestroy ();
419
- if (rotateBitmap != null ) {
420
- rotateBitmap .recycle ();
447
+ if (srcBitmap != null ) {
448
+ srcBitmap .recycle ();
421
449
}
422
450
}
423
451
0 commit comments