package org.zarroboogs.utils; import org.zarroboogs.util.net.HttpUtility; import org.zarroboogs.util.net.WeiboException; import org.zarroboogs.utils.file.FileDownloaderHttpHelper; import org.zarroboogs.utils.file.FileLocationMethod; import org.zarroboogs.utils.file.FileManager; import org.zarroboogs.weibo.BeeboApplication; import org.zarroboogs.weibo.setting.SettingUtils; import org.zarroboogs.weibo.support.utils.Utility; import android.content.Context; import android.graphics.Bitmap; import android.graphics.BitmapFactory; import android.graphics.BitmapRegionDecoder; import android.graphics.Matrix; import android.graphics.Rect; import android.media.ExifInterface; import android.text.TextUtils; import android.util.DisplayMetrics; import java.io.File; import java.io.FileOutputStream; import java.io.IOException; import static android.media.ExifInterface.ORIENTATION_NORMAL; import static android.media.ExifInterface.ORIENTATION_ROTATE_180; import static android.media.ExifInterface.ORIENTATION_ROTATE_270; import static android.media.ExifInterface.ORIENTATION_ROTATE_90; import static android.media.ExifInterface.TAG_ORIENTATION; public class ImageUtility { public static final int WITH_UNDEFINED = -1; public static final int HEIGHT_UNDEFINED = -1; /** * 1. convert gif to normal bitmap 2. cut bitmap */ private static Bitmap getMiddlePictureInTimeLineGif(String filePath, int reqWidth, int reqHeight) { try { BitmapFactory.Options options = new BitmapFactory.Options(); options.inJustDecodeBounds = true; BitmapFactory.decodeFile(filePath, options); options.inSampleSize = calculateInSampleSize(options, reqWidth, reqHeight); options.inJustDecodeBounds = false; options.inPurgeable = true; options.inInputShareable = true; Bitmap bitmap = BitmapFactory.decodeFile(filePath, options); if (bitmap == null) { return null; } int height = options.outHeight; int width = options.outWidth; int cutHeight = 0; int cutWidth = 0; if (height >= reqHeight && width >= reqWidth) { cutHeight = reqHeight; cutWidth = reqWidth; } else if (height < reqHeight && width >= reqWidth) { cutHeight = height; cutWidth = (reqWidth * cutHeight) / reqHeight; } else if (height >= reqHeight && width < reqWidth) { cutWidth = width; cutHeight = (reqHeight * cutWidth) / reqWidth; } else if (height < reqHeight && width < reqWidth) { float betweenWidth = ((float) reqWidth - (float) width) / (float) width; float betweenHeight = ((float) reqHeight - (float) height) / (float) height; if (betweenWidth > betweenHeight) { cutWidth = width; cutHeight = (reqHeight * cutWidth) / reqWidth; } else { cutHeight = height; cutWidth = (reqWidth * cutHeight) / reqHeight; } } if (cutWidth <= 0 || cutHeight <= 0) { return null; } Bitmap region = Bitmap.createBitmap(bitmap, 0, 0, cutWidth, cutHeight); if (region != bitmap) { bitmap.recycle(); bitmap = region; } if (bitmap.getHeight() < reqHeight && bitmap.getWidth() < reqWidth) { Bitmap scale = Bitmap.createScaledBitmap(bitmap, reqWidth, reqHeight, true); if (scale != bitmap) { bitmap.recycle(); bitmap = scale; } } Bitmap cornerBitmap = ImageEditUtility.getRoundedCornerBitmap(bitmap); if (cornerBitmap != bitmap) { bitmap.recycle(); bitmap = cornerBitmap; } return bitmap; } catch (OutOfMemoryError ignored) { return null; } } private static boolean isGif(String path) { return path.endsWith(".gif"); } public static Bitmap getMiddlePictureInTimeLine(String url, int reqWidth, int reqHeight, FileDownloaderHttpHelper.DownloadListener downloadListener) throws WeiboException { try { String filePath = FileManager.getFilePathFromUrl(url, FileLocationMethod.picture_bmiddle); File file = new File(filePath); if (!file.exists() && !SettingUtils.isEnablePic()) { return null; } if (!file.exists()) { getBitmapFromNetWork(url, filePath, downloadListener); } if (isGif(filePath)) { return getMiddlePictureInTimeLineGif(filePath, reqWidth, reqHeight); } BitmapFactory.Options options = new BitmapFactory.Options(); options.inJustDecodeBounds = true; BitmapFactory.decodeFile(filePath, options); int height = options.outHeight; int width = options.outWidth; int cutHeight = 0; int cutWidth = 0; if (height >= reqHeight && width >= reqWidth) { cutHeight = reqHeight; cutWidth = reqWidth; } else if (height < reqHeight && width >= reqWidth) { cutHeight = height; cutWidth = (reqWidth * cutHeight) / reqHeight; } else if (height >= reqHeight && width < reqWidth) { cutWidth = width; cutHeight = (reqHeight * cutWidth) / reqWidth; } else if (height < reqHeight && width < reqWidth) { float betweenWidth = ((float) reqWidth - (float) width) / (float) width; float betweenHeight = ((float) reqHeight - (float) height) / (float) height; if (betweenWidth > betweenHeight) { cutWidth = width; cutHeight = (reqHeight * cutWidth) / reqWidth; } else { cutHeight = height; cutWidth = (reqWidth * cutHeight) / reqHeight; } } if (cutWidth > 0 && cutHeight > 0) { int startX = 0; if (cutWidth < width) { startX = (width - cutWidth) / 2; } try { BitmapRegionDecoder decoder = BitmapRegionDecoder.newInstance(filePath, false); if (decoder != null) { Bitmap bitmap = decoder.decodeRegion(new Rect(startX, 0, startX + cutWidth, cutHeight), null); if (bitmap.getHeight() < reqHeight && bitmap.getWidth() < reqWidth) { Bitmap scale = Bitmap.createScaledBitmap(bitmap, reqWidth, reqHeight, true); if (scale != bitmap) { bitmap.recycle(); bitmap = scale; } } if (bitmap != null) { Bitmap roundedCornerBitmap = ImageEditUtility.getRoundedCornerBitmap(bitmap); if (roundedCornerBitmap != bitmap) { bitmap.recycle(); bitmap = roundedCornerBitmap; } return bitmap; } } } catch (IOException ignored) { } } return null; } catch (OutOfMemoryError ignored) { ignored.printStackTrace(); return null; } } public static Bitmap getRoundedCornerPic(String url, int reqWidth, int reqHeight, FileLocationMethod method) throws WeiboException { return getRoundedCornerPic(url, reqWidth, reqHeight, method, null); } public static Bitmap getRoundedCornerPic(String url, int reqWidth, int reqHeight, FileLocationMethod method, FileDownloaderHttpHelper.DownloadListener downloadListener) throws WeiboException { try { if (!FileManager.isExternalStorageMounted()) { return null; } String filePath = FileManager.getFilePathFromUrl(url, method); if (!filePath.endsWith(".jpg") && !filePath.endsWith(".gif")) { filePath = filePath + ".jpg"; } boolean fileExist = new File(filePath).exists(); if (!fileExist && !SettingUtils.isEnablePic()) { return null; } if (!fileExist) { boolean result = getBitmapFromNetWork(url, filePath, downloadListener); if (!result) { return null; } } BitmapFactory.Options options = new BitmapFactory.Options(); options.inJustDecodeBounds = true; BitmapFactory.decodeFile(filePath, options); options.inSampleSize = calculateInSampleSize(options, reqWidth, reqHeight); options.inJustDecodeBounds = false; options.inPurgeable = true; options.inInputShareable = true; Bitmap bitmap = BitmapFactory.decodeFile(filePath, options); if (bitmap == null) { // this picture is broken,so delete it new File(filePath).delete(); return null; } int[] size = calcResize(bitmap.getWidth(), bitmap.getHeight(), reqWidth, reqHeight); if (size[0] > 0 && size[1] > 0) { Bitmap scaledBitmap = Bitmap.createScaledBitmap(bitmap, size[0], size[1], true); if (scaledBitmap != bitmap) { bitmap.recycle(); bitmap = scaledBitmap; } } Bitmap roundedBitmap = ImageEditUtility.getRoundedCornerBitmap(bitmap); if (roundedBitmap != bitmap) { bitmap.recycle(); bitmap = roundedBitmap; } return bitmap; } catch (OutOfMemoryError ignored) { ignored.printStackTrace(); return null; } } public static Bitmap getRoundedCornerPic(String filePath, int reqWidth, int reqHeight) { return getRoundedCornerPic(filePath, reqWidth, reqHeight, 0); } public static Bitmap getRoundedCornerPic(String filePath, int reqWidth, int reqHeight, int cornerRadius) { try { if (!FileManager.isExternalStorageMounted()) { return null; } if (!filePath.endsWith(".jpg") && !filePath.endsWith(".gif") && !filePath.endsWith(".png")) { filePath = filePath + ".jpg"; } boolean fileExist = new File(filePath).exists(); if (!fileExist && !SettingUtils.isEnablePic()) { return null; } BitmapFactory.Options options = new BitmapFactory.Options(); options.inJustDecodeBounds = true; BitmapFactory.decodeFile(filePath, options); options.inSampleSize = calculateInSampleSize(options, reqWidth, reqHeight); options.inJustDecodeBounds = false; options.inPurgeable = true; options.inInputShareable = true; Bitmap bitmap = BitmapFactory.decodeFile(filePath, options); if (bitmap == null) { // this picture is broken,so delete it new File(filePath).delete(); return null; } if (cornerRadius > 0) { int[] size = calcResize(bitmap.getWidth(), bitmap.getHeight(), reqWidth, reqHeight); if (size[0] > 0 && size[1] > 0) { Bitmap scaledBitmap = Bitmap.createScaledBitmap(bitmap, size[0], size[1], true); if (scaledBitmap != bitmap) { bitmap.recycle(); bitmap = scaledBitmap; } } Bitmap roundedBitmap = ImageEditUtility.getRoundedCornerBitmap(bitmap, cornerRadius); if (roundedBitmap != bitmap) { bitmap.recycle(); bitmap = roundedBitmap; } } return bitmap; } catch (OutOfMemoryError ignored) { ignored.printStackTrace(); return null; } } public static Bitmap readNormalPic(String filePath, int reqWidth, int reqHeight) { try { if (!FileManager.isExternalStorageMounted()) { return null; } if (TextUtils.isEmpty(filePath)) { return null; } if (!filePath.endsWith(".jpg") && !filePath.endsWith(".gif") && !filePath.endsWith(".png")) { filePath = filePath + ".jpg"; } boolean fileExist = new File(filePath).exists(); if (!fileExist && !SettingUtils.isEnablePic()) { return null; } BitmapFactory.Options options = new BitmapFactory.Options(); options.inJustDecodeBounds = true; BitmapFactory.decodeFile(filePath, options); if (reqHeight > 0 && reqWidth > 0) { options.inSampleSize = calculateInSampleSize(options, reqWidth, reqHeight); } options.inJustDecodeBounds = false; options.inPurgeable = true; options.inInputShareable = true; Bitmap bitmap = BitmapFactory.decodeFile(filePath, options); if (bitmap == null) { // this picture is broken,so delete it new File(filePath).delete(); return null; } if (reqHeight > 0 && reqWidth > 0) { int[] size = calcResize(bitmap.getWidth(), bitmap.getHeight(), reqWidth, reqHeight); if (size[0] > 0 && size[1] > 0) { Bitmap scaledBitmap = Bitmap.createScaledBitmap(bitmap, size[0], size[1], true); if (scaledBitmap != bitmap) { bitmap.recycle(); bitmap = scaledBitmap; } } } return bitmap; } catch (OutOfMemoryError ignored) { ignored.printStackTrace(); return null; } } public static Bitmap getMiddlePictureInBrowserMSGActivity(String url, FileLocationMethod method, FileDownloaderHttpHelper.DownloadListener downloadListener) { try { String filePath = FileManager.getFilePathFromUrl(url, method); File file = new File(filePath); if (!file.exists() && !SettingUtils.isEnablePic()) { return null; } if (!isThisBitmapCanRead(filePath)) { getBitmapFromNetWork(url, filePath, downloadListener); } file = new File(filePath); if (file.exists()) { DisplayMetrics displayMetrics = BeeboApplication.getInstance().getDisplayMetrics(); return decodeBitmapFromSDCard(filePath, displayMetrics.widthPixels, 900); } return null; } catch (OutOfMemoryError ignored) { return null; } } public static String getLargePictureWithoutRoundedCorner(String url, FileDownloaderHttpHelper.DownloadListener downloadListener, FileLocationMethod fileLocationMethod) { String absoluteFilePath = FileManager.getFilePathFromUrl(url, fileLocationMethod); File file = new File(absoluteFilePath); if (file.exists()) { return absoluteFilePath; } else { getBitmapFromNetWork(url, absoluteFilePath, downloadListener); if (isThisBitmapCanRead(absoluteFilePath)) { return absoluteFilePath; } else { return "about:blank"; } } } public static boolean isThisBitmapCanRead(String path) { if (TextUtils.isEmpty(path)) { return false; } File file = new File(path); if (!file.exists()) { return false; } final BitmapFactory.Options options = new BitmapFactory.Options(); options.inJustDecodeBounds = true; BitmapFactory.decodeFile(path, options); int width = options.outWidth; int height = options.outHeight; return !(width == -1 || height == -1); } public static boolean isThisBitmapTooLargeToRead(String path) { File file = new File(path); if (!file.exists()) { return false; } final BitmapFactory.Options options = new BitmapFactory.Options(); options.inJustDecodeBounds = true; BitmapFactory.decodeFile(path, options); int width = options.outWidth; int height = options.outHeight; if (width == -1 || height == -1) { return false; } return width > Utility.getBitmapMaxWidthAndMaxHeight() || height > Utility.getBitmapMaxWidthAndMaxHeight(); } public static int[] getBitmapSize(String path) { int[] result = { -1, -1 }; File file = new File(path); if (!file.exists()) { return result; } final BitmapFactory.Options options = new BitmapFactory.Options(); options.inJustDecodeBounds = true; BitmapFactory.decodeFile(path, options); int width = options.outWidth; int height = options.outHeight; if (width > 0 && height > 0) { result[0] = width; result[1] = height; } return result; } public static Bitmap decodeBitmapFromSDCard(String path, int reqWidth, int reqHeight) { final BitmapFactory.Options options = new BitmapFactory.Options(); options.inJustDecodeBounds = true; BitmapFactory.decodeFile(path, options); options.inSampleSize = calculateInSampleSize(options, reqWidth, reqHeight); options.inJustDecodeBounds = false; return BitmapFactory.decodeFile(path, options); } public static Bitmap getNotificationSendFailedPic(String path) { final BitmapFactory.Options options = new BitmapFactory.Options(); options.inJustDecodeBounds = true; BitmapFactory.decodeFile(path, options); options.inSampleSize = calculateInSampleSize(options, Utility.getScreenWidth(), Utility.getScreenHeight()); options.inJustDecodeBounds = false; return BitmapFactory.decodeFile(path, options); } public static Bitmap getWriteWeiboRoundedCornerPic(String url, int reqWidth, int reqHeight, FileLocationMethod method) { try { if (!FileManager.isExternalStorageMounted()) { return null; } String filePath = FileManager.getFilePathFromUrl(url, method); if (!ImageUtility.isThisBitmapCanRead(filePath)) { return null; } if (!filePath.endsWith(".jpg") && !filePath.endsWith(".gif")) { filePath = filePath + ".jpg"; } boolean fileExist = new File(filePath).exists(); if (!fileExist) { return null; } BitmapFactory.Options options = new BitmapFactory.Options(); options.inJustDecodeBounds = true; BitmapFactory.decodeFile(filePath, options); options.inSampleSize = calculateInSampleSize(options, reqWidth, reqHeight); options.inJustDecodeBounds = false; options.inPurgeable = true; options.inInputShareable = true; Bitmap bitmap = BitmapFactory.decodeFile(filePath, options); if (bitmap == null) { // this picture is broken,so delete it new File(filePath).delete(); return null; } int[] size = calcResize(bitmap.getWidth(), bitmap.getHeight(), reqWidth, reqHeight); if (size[0] > 0 && size[1] > 0) { Bitmap scaledBitmap = Bitmap.createScaledBitmap(bitmap, size[0], size[1], true); if (scaledBitmap != bitmap) { bitmap.recycle(); bitmap = scaledBitmap; } } Bitmap roundedBitmap = ImageEditUtility.getRoundedCornerBitmap(bitmap); if (roundedBitmap != bitmap) { bitmap.recycle(); bitmap = roundedBitmap; } return bitmap; } catch (OutOfMemoryError ignored) { ignored.printStackTrace(); return null; } } public static Bitmap getWriteWeiboPictureThumblr(String filePath) { try { // actionbar button image width and height is 32 dip int reqWidth = Utility.dip2px(32); int reqHeight = Utility.dip2px(32); if (!FileManager.isExternalStorageMounted()) { return null; } boolean fileExist = new File(filePath).exists(); if (!fileExist) { return null; } BitmapFactory.Options options = new BitmapFactory.Options(); options.inJustDecodeBounds = true; BitmapFactory.decodeFile(filePath, options); options.inSampleSize = calculateInSampleSize(options, reqWidth, reqHeight); options.inJustDecodeBounds = false; options.inPurgeable = true; options.inInputShareable = true; Bitmap bitmap = BitmapFactory.decodeFile(filePath, options); if (bitmap == null) { // this picture is broken,so delete it new File(filePath).delete(); return null; } int[] size = calcResize(bitmap.getWidth(), bitmap.getHeight(), reqWidth, reqHeight); if (size[0] > 0 && size[1] > 0) { Bitmap scaledBitmap = Bitmap.createScaledBitmap(bitmap, size[0], size[1], true); if (scaledBitmap != bitmap) { bitmap.recycle(); bitmap = scaledBitmap; } } Bitmap roundedBitmap = ImageEditUtility.getRoundedCornerBitmap(bitmap); if (roundedBitmap != bitmap) { bitmap.recycle(); bitmap = roundedBitmap; } int exifRotation = ImageUtility.getFileExifRotation(filePath); if (exifRotation != 0) { Matrix mtx = new Matrix(); mtx.postRotate(exifRotation); Bitmap adjustedBitmap = Bitmap.createBitmap(roundedBitmap, 0, 0, bitmap.getWidth(), bitmap.getHeight(), mtx, true); if (adjustedBitmap != bitmap) { bitmap.recycle(); bitmap = adjustedBitmap; } } return bitmap; } catch (OutOfMemoryError ignored) { ignored.printStackTrace(); return null; } } public static boolean getBitmapFromNetWork(String url, String path, FileDownloaderHttpHelper.DownloadListener downloadListener) { for (int i = 0; i < 3; i++) { if (HttpUtility.getInstance().executeDownloadTask(url, path, downloadListener)) { return true; } new File(path).delete(); } return false; } private static int calculateInSampleSize(BitmapFactory.Options options, int reqWidth, int reqHeight) { final int height = options.outHeight; final int width = options.outWidth; int inSampleSize = 1; if (height > reqHeight || width > reqWidth) { if (height > reqHeight && reqHeight != 0) { inSampleSize = (int) Math.floor((double) height / (double) reqHeight); } int tmp = 0; if (width > reqWidth && reqWidth != 0) { tmp = (int) Math.floor((double) width / (double) reqWidth); } inSampleSize = Math.max(inSampleSize, tmp); } int roundedSize; if (inSampleSize <= 8) { roundedSize = 1; while (roundedSize < inSampleSize) { roundedSize <<= 1; } } else { roundedSize = (inSampleSize + 7) / 8 * 8; } return roundedSize; } private static int[] calcResize(int actualWidth, int actualHeight, int reqWidth, int reqHeight) { int height = actualHeight; int width = actualWidth; float betweenWidth = ((float) reqWidth) / (float) actualWidth; float betweenHeight = ((float) reqHeight) / (float) actualHeight; float min = Math.min(betweenHeight, betweenWidth); height = (int) (min * actualHeight); width = (int) (min * actualWidth); return new int[]{ width, height }; } public static String compressPic(Context context, String picPath) { BitmapFactory.Options options = new BitmapFactory.Options(); options.inJustDecodeBounds = false; options.inSampleSize = 1; switch (SettingUtils.getUploadQuality()) { case 1: return picPath; case 2: options.inSampleSize = 2; break; case 3: options.inSampleSize = 4; break; case 4: options.inSampleSize = 2; if (Utility.isWifi(context)) { return picPath; } break; } Bitmap bitmap = BitmapFactory.decodeFile(picPath, options); int exifRotation = ImageUtility.getFileExifRotation(picPath); if (exifRotation != 0) { // TODO write EXIF instead of rotating bitmap. Matrix mtx = new Matrix(); mtx.postRotate(exifRotation); Bitmap adjustedBitmap = Bitmap.createBitmap(bitmap, 0, 0, bitmap.getWidth(), bitmap.getHeight(), mtx, true); if (adjustedBitmap != bitmap) { bitmap.recycle(); bitmap = adjustedBitmap; } } FileOutputStream stream = null; String tmp = FileManager.getUploadPicTempFile(); try { new File(tmp).getParentFile().mkdirs(); new File(tmp).createNewFile(); stream = new FileOutputStream(new File(tmp)); } catch (IOException ignored) { } bitmap.compress(Bitmap.CompressFormat.JPEG, 100, stream); if (stream != null) { try { stream.close(); bitmap.recycle(); } catch (IOException ignored) { } } return tmp; } public static boolean isThisPictureGif(String url) { return !TextUtils.isEmpty(url) && url.endsWith(".gif"); } public static int getFileExifRotation(String filePath) { try { ExifInterface exifInterface = new ExifInterface(filePath); int orientation = exifInterface.getAttributeInt(TAG_ORIENTATION, ORIENTATION_NORMAL); switch (orientation) { case ORIENTATION_ROTATE_90: return 90; case ORIENTATION_ROTATE_180: return 180; case ORIENTATION_ROTATE_270: return 270; default: return 0; } } catch (IOException e) { return 0; } } }