Skip to content

Commit c4ab880

Browse files
committed
Add image auto rotate beta fearure.
1 parent 4659cd7 commit c4ab880

File tree

7 files changed

+140
-29
lines changed

7 files changed

+140
-29
lines changed

demo/res/values/arrays.xml

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -119,7 +119,8 @@
119119

120120
<item>Round Corner</item>
121121

122-
<item>Image Zoom (WebView)</item>
122+
<item>Image Zoom (WebView)</item>
123+
<item>Auto Rotate</item>
123124

124125
<item>List Items</item>
125126
<item>List Items (Aspect Ratio)</item>
@@ -182,6 +183,8 @@
182183
<item>com.androidquery.test.image.ImageLoadingActivity:image_round:new</item>
183184
<item>com.androidquery.test.image.ImageZoomActivity:image_zoom</item>
184185

186+
<item>com.androidquery.test.image.ImageLoadingActivity:image_auto_rotate:new</item>
187+
185188
<item>com.androidquery.test.image.ImageLoadingListActivity:image_list</item>
186189
<item>com.androidquery.test.image.ImageLoadingList2Activity:image_list2</item>
187190
<item>com.androidquery.test.image.ImageLoadingList3Activity:image_list3</item>
@@ -311,6 +314,7 @@
311314
<item>image_ratio_anchor</item>
312315
<item>image_round</item>
313316
<item>image_zoom</item>
317+
<item>image_auto_rotate</item>
314318

315319
<item>image_list</item>
316320
<item>image_list2</item>
@@ -429,6 +433,8 @@
429433

430434
<item>Zoom enables image with WebView</item>
431435

436+
<item>Auto rotate images taken with camera</item>
437+
432438
<item>Loading Image in List View Items</item>
433439
<item>Loading Image in List View with Aspect Ratio</item>
434440
<item>Loading Image in List View Items with ViewHolder Pattern</item>

demo/src/com/androidquery/test/AdhocActivity.java

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -52,7 +52,13 @@ protected void onCreate(Bundle savedInstanceState) {
5252

5353
private void work() throws IOException{
5454

55+
String url = "";
5556

57+
BitmapAjaxCallback cb = new BitmapAjaxCallback();
58+
59+
cb.url(url).ratio(AQuery.RATIO_PRESERVE).expire(3600*1000);
60+
61+
aq.id(R.id.image).image(cb);
5662

5763
}
5864

demo/src/com/androidquery/test/image/ImageLoadingActivity.java

Lines changed: 11 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,10 @@
1111
import android.app.ProgressDialog;
1212
import android.content.Intent;
1313
import android.graphics.Bitmap;
14+
import android.graphics.BitmapFactory;
15+
import android.graphics.Matrix;
1416
import android.graphics.PorterDuff;
17+
import android.media.ExifInterface;
1518
import android.net.Uri;
1619
import android.os.Bundle;
1720
import android.os.Environment;
@@ -20,6 +23,7 @@
2023

2124
import com.androidquery.AQuery;
2225
import com.androidquery.R;
26+
import com.androidquery.callback.AjaxCallback;
2327
import com.androidquery.callback.AjaxStatus;
2428
import com.androidquery.callback.BitmapAjaxCallback;
2529
import com.androidquery.callback.ImageOptions;
@@ -455,20 +459,16 @@ public void image_chart(){
455459

456460
}
457461

458-
/*
459-
private static String patchUrl(String url){
462+
public void image_auto_rotate(){
460463

461-
String result = url;
464+
String imageUrl = "http://res.dbkon.co.kr/resource/201302091360376386575001.jpg";
462465

463-
if(url.indexOf('%') == -1){
466+
BitmapAjaxCallback cb = new BitmapAjaxCallback();
467+
cb.url(imageUrl).targetWidth(300).rotate(true);
464468

465-
Uri uri = Uri.parse(url);
466-
result = uri.getScheme() + "://" + uri.getAuthority() + uri.getPath() + "?" + Uri.encode(uri.getQuery(), "&=");
467-
String fragment = uri.getFragment();
468-
if(fragment != null) result += "#" + fragment;
469-
}
469+
aq.id(R.id.image).image(cb);
470470

471-
return result;
472471
}
473-
*/
472+
473+
474474
}

src/com/androidquery/AbstractAQuery.java

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1629,6 +1629,8 @@ public T setLayerType11(int type, Paint paint){
16291629
return self();
16301630
}
16311631

1632+
1633+
16321634
/**
16331635
* Invoke the method on the current view.
16341636
*

src/com/androidquery/callback/BitmapAjaxCallback.java

Lines changed: 93 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -38,12 +38,14 @@
3838
import android.graphics.Canvas;
3939
import android.graphics.Paint;
4040
import android.graphics.PorterDuff.Mode;
41+
import android.graphics.Matrix;
4142
import android.graphics.PorterDuffXfermode;
4243
import android.graphics.Rect;
4344
import android.graphics.RectF;
4445
import android.graphics.drawable.BitmapDrawable;
4546
import android.graphics.drawable.Drawable;
4647
import android.graphics.drawable.TransitionDrawable;
48+
import android.media.ExifInterface;
4749
import android.view.View;
4850
import android.view.animation.AlphaAnimation;
4951
import android.view.animation.Animation;
@@ -90,6 +92,7 @@ public class BitmapAjaxCallback extends AbstractAjaxCallback<Bitmap, BitmapAjaxC
9092
private boolean targetDim = true;
9193
private float anchor = AQuery.ANCHOR_DYNAMIC;
9294
private boolean invalid;
95+
private boolean rotate;
9396

9497

9598
/**
@@ -191,6 +194,17 @@ public BitmapAjaxCallback ratio(float ratio){
191194
return this;
192195
}
193196

197+
/**
198+
* Set auto rotate to respect image Exif orientation.
199+
*
200+
* @param rotate rotate
201+
* @return self
202+
*/
203+
public BitmapAjaxCallback rotate(boolean rotate){
204+
this.rotate = rotate;
205+
return this;
206+
}
207+
194208

195209
/**
196210
* Set the image aspect ratio anchor.
@@ -228,19 +242,17 @@ public BitmapAjaxCallback round(int radius){
228242
}
229243

230244

231-
private static Bitmap decode(String path, byte[] data, BitmapFactory.Options options){
245+
private static Bitmap decode(String path, byte[] data, BitmapFactory.Options options, boolean rotate){
232246

233247
Bitmap result = null;
234248

235249

236250
if(path != null){
237251

238-
result = decodeFile(path, options);
252+
result = decodeFile(path, options, rotate);
239253

240254
}else if(data != null){
241255

242-
//AQUtility.debug("decoding byte[]");
243-
244256
result = BitmapFactory.decodeByteArray(data, 0, data.length, options);
245257

246258
}
@@ -252,7 +264,7 @@ private static Bitmap decode(String path, byte[] data, BitmapFactory.Options opt
252264
return result;
253265
}
254266

255-
private static Bitmap decodeFile(String path, BitmapFactory.Options options){
267+
private static Bitmap decodeFile(String path, BitmapFactory.Options options, boolean rotate){
256268

257269
Bitmap result = null;
258270

@@ -263,22 +275,18 @@ private static Bitmap decodeFile(String path, BitmapFactory.Options options){
263275
options.inInputShareable = true;
264276
options.inPurgeable = true;
265277

266-
267-
268278
FileInputStream fis = null;
269279

270280
try{
271281

272282
fis = new FileInputStream(path);
273-
274283
FileDescriptor fd = fis.getFD();
275-
276-
//AQUtility.debug("decoding file");
277-
//AQUtility.time("decode file");
278-
279284
result = BitmapFactory.decodeFileDescriptor(fd, null, options);
285+
286+
if(result != null && rotate){
287+
result = rotate(path, result);
288+
}
280289

281-
//AQUtility.timeEnd("decode file", 0);
282290
}catch(IOException e){
283291
AQUtility.report(e);
284292
}finally{
@@ -289,6 +297,73 @@ private static Bitmap decodeFile(String path, BitmapFactory.Options options){
289297

290298
}
291299

300+
private static Bitmap rotate(String path, Bitmap bm){
301+
302+
Bitmap result = bm;
303+
304+
int ori = ExifInterface.ORIENTATION_NORMAL;
305+
306+
try{
307+
ExifInterface ei = new ExifInterface(path);
308+
ori = ei.getAttributeInt(ExifInterface.TAG_ORIENTATION, ExifInterface.ORIENTATION_NORMAL);
309+
}catch(Exception e){
310+
//simply fallback to normal orientation
311+
AQUtility.debug(e);
312+
}
313+
314+
if(ori > 0){
315+
316+
Matrix matrix = getRotateMatrix(ori);
317+
result = Bitmap.createBitmap(bm, 0, 0, bm.getWidth(), bm.getHeight(), matrix, true);
318+
319+
AQUtility.debug("before", bm.getWidth() + ":" + bm.getHeight());
320+
AQUtility.debug("after", result.getWidth() + ":" + result.getHeight());
321+
322+
bm.recycle();
323+
}
324+
325+
326+
return result;
327+
}
328+
329+
private static Matrix getRotateMatrix(int ori){
330+
331+
Matrix matrix = new Matrix();
332+
switch (ori) {
333+
case 2:
334+
matrix.setScale(-1, 1);
335+
break;
336+
case 3:
337+
matrix.setRotate(180);
338+
break;
339+
case 4:
340+
matrix.setRotate(180);
341+
matrix.postScale(-1, 1);
342+
break;
343+
case 5:
344+
matrix.setRotate(90);
345+
matrix.postScale(-1, 1);
346+
break;
347+
case 6:
348+
matrix.setRotate(90);
349+
break;
350+
case 7:
351+
matrix.setRotate(-90);
352+
matrix.postScale(-1, 1);
353+
break;
354+
case 8:
355+
matrix.setRotate(-90);
356+
break;
357+
358+
}
359+
360+
return matrix;
361+
362+
}
363+
364+
public static Bitmap getResizedImage(String path, byte[] data, int target, boolean width, int round){
365+
return getResizedImage(path, data, target, width, round, false);
366+
}
292367

293368
/**
294369
* Utility method for downsampling images.
@@ -298,9 +373,10 @@ private static Bitmap decodeFile(String path, BitmapFactory.Options options){
298373
* @param target the target dimension
299374
* @param width use width as target, otherwise use the higher value of height or width
300375
* @param round corner radius
376+
* @param rotate auto rotate with exif data
301377
* @return the resized image
302378
*/
303-
public static Bitmap getResizedImage(String path, byte[] data, int target, boolean width, int round){
379+
public static Bitmap getResizedImage(String path, byte[] data, int target, boolean width, int round, boolean rotate){
304380

305381
Options options = null;
306382

@@ -309,7 +385,7 @@ public static Bitmap getResizedImage(String path, byte[] data, int target, boole
309385
Options info = new Options();
310386
info.inJustDecodeBounds = true;
311387

312-
decode(path, data, info);
388+
decode(path, data, info, rotate);
313389

314390
int dim = info.outWidth;
315391
if(!width) dim = Math.max(dim, info.outHeight);
@@ -322,7 +398,7 @@ public static Bitmap getResizedImage(String path, byte[] data, int target, boole
322398

323399
Bitmap bm = null;
324400
try{
325-
bm = decode(path, data, options);
401+
bm = decode(path, data, options, rotate);
326402
}catch(OutOfMemoryError e){
327403
clearCache();
328404
AQUtility.report(e);
@@ -356,7 +432,7 @@ private static int sampleSize(int width, int target){
356432
}
357433

358434
private Bitmap bmGet(String path, byte[] data){
359-
return getResizedImage(path, data, targetWidth, targetDim, round);
435+
return getResizedImage(path, data, targetWidth, targetDim, round, rotate);
360436

361437
}
362438

tests/src/com/androidquery/test/AQueryAsyncTest.java

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -79,6 +79,7 @@ public void done(String url, Object result, AjaxStatus status){
7979

8080
done();
8181

82+
8283
}
8384

8485
private void checkStatus(AjaxStatus status){

tests/src/com/androidquery/test/AQueryImageTest.java

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@
1717
import android.graphics.Bitmap;
1818
import android.graphics.BitmapFactory;
1919
import android.graphics.drawable.Drawable;
20+
import android.media.ExifInterface;
2021
import android.test.ActivityInstrumentationTestCase2;
2122
import android.test.UiThreadTest;
2223
import android.view.View;
@@ -506,4 +507,23 @@ public void testIfModified() {
506507

507508
}
508509

510+
public void testAutoRotate() throws IOException{
511+
512+
513+
String imageUrl = "http://res.dbkon.co.kr/resource/201302091360376386575001.jpg";
514+
515+
BitmapAjaxCallback cb = new BitmapAjaxCallback();
516+
cb.url(imageUrl).targetWidth(300).rotate(true);
517+
518+
aq.id(R.id.image).image(cb);
519+
520+
cb.block();
521+
522+
Bitmap bm = cb.getResult();
523+
AjaxStatus status = cb.getStatus();
524+
525+
assertNotNull(bm);
526+
527+
}
528+
509529
}

0 commit comments

Comments
 (0)