package ryan.org.wordpress.android.util; import android.graphics.Bitmap; import android.graphics.BitmapFactory; import android.graphics.Matrix; import android.graphics.drawable.BitmapDrawable; import android.media.ExifInterface; import android.net.http.AndroidHttpClient; import android.os.AsyncTask; import android.util.Log; import android.widget.ImageView; import java.io.ByteArrayOutputStream; import java.io.InputStream; import java.lang.ref.WeakReference; import java.lang.reflect.Constructor; import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; import java.net.URL; import org.apache.http.HttpEntity; import org.apache.http.HttpResponse; import org.apache.http.HttpStatus; import org.apache.http.client.methods.HttpGet; public class ImageHelper{ public byte[] createThumbnail(byte[] bytes, String sMaxImageWidth, String orientation, boolean tiny) { //creates a thumbnail and returns the bytes int finalHeight = 0; BitmapFactory.Options opts = new BitmapFactory.Options(); opts.inJustDecodeBounds = true; Bitmap bm = BitmapFactory.decodeByteArray(bytes, 0, bytes.length, opts); int width = opts.outWidth; int height = opts.outHeight; int finalWidth = 500; //default to this if there's a problem //Change dimensions of thumbnail if (tiny){ finalWidth = 150; } byte[] finalBytes; if (sMaxImageWidth.equals("Original Size")){ if (bytes.length > 2000000) //it's a biggie! don't want out of memory crash { float finWidth = 1000; int sample = 0; float fWidth = width; sample= new Double(Math.ceil(fWidth / finWidth)).intValue(); if(sample == 3){ sample = 4; } else if(sample > 4 && sample < 8 ){ sample = 8; } opts.inSampleSize = sample; opts.inJustDecodeBounds = false; float percentage = (float) finalWidth / width; float proportionateHeight = height * percentage; finalHeight = (int) Math.rint(proportionateHeight); bm = BitmapFactory.decodeByteArray(bytes, 0, bytes.length, opts); ByteArrayOutputStream baos = new ByteArrayOutputStream(); bm.compress(Bitmap.CompressFormat.JPEG, 90, baos); bm.recycle(); //free up memory finalBytes = baos.toByteArray(); } else { finalBytes = bytes; } } else { finalWidth = Integer.parseInt(sMaxImageWidth); if (finalWidth > width){ //don't resize finalBytes = bytes; } else { int sample = 0; float fWidth = width; sample= new Double(Math.ceil(fWidth / 1200)).intValue(); if(sample == 3){ sample = 4; } else if(sample > 4 && sample < 8 ){ sample = 8; } opts.inSampleSize = sample; opts.inJustDecodeBounds = false; bm = BitmapFactory.decodeByteArray(bytes, 0, bytes.length, opts); float percentage = (float) finalWidth / bm.getWidth(); float proportionateHeight = bm.getHeight() * percentage; finalHeight = (int) Math.rint(proportionateHeight); float scaleWidth = ((float) finalWidth) / bm.getWidth(); float scaleHeight = ((float) finalHeight) / bm.getHeight(); float scaleBy = Math.min(scaleWidth, scaleHeight); // Create a matrix for the manipulation Matrix matrix = new Matrix(); // Resize the bitmap matrix.postScale(scaleBy, scaleBy); if ((orientation != null) && (orientation.equals("90") || orientation.equals("180") || orientation.equals("270"))){ matrix.postRotate(Integer.valueOf(orientation)); } Bitmap resized = Bitmap.createBitmap(bm, 0, 0, bm.getWidth(), bm.getHeight(), matrix, true); ByteArrayOutputStream baos = new ByteArrayOutputStream(); resized.compress(Bitmap.CompressFormat.JPEG, 85, baos); bm.recycle(); //free up memory resized.recycle(); finalBytes = baos.toByteArray(); } } return finalBytes; } public String getExifOrientation(String path, String orientation) { //get image EXIF orientation if Android 2.0 or higher, using reflection //http://developer.android.com/resources/articles/backward-compatibility.html Method exif_getAttribute; Constructor<ExifInterface> exif_construct; String exifOrientation = ""; int sdk_int = 0; try { sdk_int = Integer.valueOf(android.os.Build.VERSION.SDK); } catch (Exception e1) { sdk_int = 3; //assume they are on cupcake } if (sdk_int >= 5){ try { exif_construct = android.media.ExifInterface.class.getConstructor(new Class[] { String.class } ); Object exif = exif_construct.newInstance(path); exif_getAttribute = android.media.ExifInterface.class.getMethod("getAttribute", new Class[] { String.class } ); try { exifOrientation = (String) exif_getAttribute.invoke(exif, android.media.ExifInterface.TAG_ORIENTATION); if (exifOrientation != null){ if (exifOrientation.equals("1")){ orientation = "0"; } else if (exifOrientation.equals("3")){ orientation = "180"; } else if (exifOrientation.equals("6")){ orientation = "90"; } else if (exifOrientation.equals("8")){ orientation = "270"; } } else{ orientation = "0"; } } catch (InvocationTargetException ite) { /* unpack original exception when possible */ orientation = "0"; } catch (IllegalAccessException ie) { System.err.println("unexpected " + ie); orientation = "0"; } /* success, this is a newer device */ } catch (NoSuchMethodException nsme) { orientation = "0"; } catch (IllegalArgumentException e) { orientation = "0"; } catch (InstantiationException e) { orientation = "0"; } catch (IllegalAccessException e) { orientation = "0"; } catch (InvocationTargetException e) { orientation = "0"; } } return orientation; } //borrowed from http://android-developers.blogspot.com/2010/07/multithreading-for-performance.html class BitmapDownloaderTask extends AsyncTask<String, Void, Bitmap> { private String url; private final WeakReference<ImageView> imageViewReference; public BitmapDownloaderTask(ImageView imageView) { imageViewReference = new WeakReference<ImageView>(imageView); } @Override // Actual download method, run in the task thread protected Bitmap doInBackground(String... params) { // params comes from the execute() call: params[0] is the url. return downloadBitmap(params[0]); } @Override // Once the image is downloaded, associates it to the imageView protected void onPostExecute(Bitmap bitmap) { if (isCancelled()) { bitmap = null; } if (imageViewReference != null) { ImageView imageView = imageViewReference.get(); if (imageView != null && bitmap != null) { imageView.setImageBitmap(bitmap); } } } } static Bitmap downloadBitmap(String url) { final AndroidHttpClient client = AndroidHttpClient.newInstance("Android"); final HttpGet getRequest = new HttpGet(url); try { HttpResponse response = client.execute(getRequest); final int statusCode = response.getStatusLine().getStatusCode(); if (statusCode != HttpStatus.SC_OK) { Log.w("ImageDownloader", "Error " + statusCode + " while retrieving bitmap from " + url); return null; } final HttpEntity entity = response.getEntity(); if (entity != null) { InputStream inputStream = null; try { inputStream = entity.getContent(); Bitmap bitmap = BitmapFactory.decodeStream(inputStream); BitmapDrawable bd = new BitmapDrawable(bitmap); bitmap = ryan.com.commonsware.cwac.thumbnail.ThumbnailAdapter.getRoundedCornerBitmap(bd.getBitmap()); return bitmap; } finally { if (inputStream != null) { inputStream.close(); } entity.consumeContent(); } } } catch (Exception e) { // Could provide a more explicit error message for IOException or IllegalStateException getRequest.abort(); Log.w("ImageDownloader", "Error while retrieving bitmap from " + url); } finally { if (client != null) { client.close(); } } return null; } }