package com.netease.nim.uikit.common.util.media; import java.io.File; import java.io.FileInputStream; import java.io.FileNotFoundException; import java.io.IOException; import java.io.InputStream; import android.annotation.TargetApi; import android.content.res.Resources; import android.graphics.Bitmap; import android.graphics.BitmapFactory; import android.media.ThumbnailUtils; import android.os.Build; import android.provider.MediaStore; import com.netease.nim.uikit.common.util.file.AttachmentStore; import com.netease.nim.uikit.common.util.sys.ScreenUtil; public class BitmapDecoder { public static Bitmap decode(InputStream is) { BitmapFactory.Options options = new BitmapFactory.Options(); // RGB_565 options.inPreferredConfig = Bitmap.Config.RGB_565; /** * 在4.4上,如果之前is标记被移动过,会导致解码失败 */ try { if (is.markSupported()) { is.reset(); } } catch (IOException e) { e.printStackTrace(); } try { return BitmapFactory.decodeStream(is, null, options); } catch (OutOfMemoryError e) { e.printStackTrace(); } return null; } public static Bitmap decodeSampledForDisplay(String pathName) { return decodeSampledForDisplay(pathName, true); } public static Bitmap decodeSampledForDisplay(String pathName, boolean withTextureLimit) { float ratio = ImageUtil.MAX_IMAGE_RATIO; int[][] reqBounds = new int[][]{ new int[]{ScreenUtil.screenWidth * 2, ScreenUtil.screenHeight}, new int[]{ScreenUtil.screenWidth, ScreenUtil.screenHeight * 2}, new int[]{(int) (ScreenUtil.screenWidth * 1.414), (int) (ScreenUtil.screenHeight * 1.414)}, }; // decode bound int[] bound = decodeBound(pathName); // pick request bound int[] reqBound = pickReqBoundWithRatio(bound, reqBounds, ratio); int width = bound[0]; int height = bound[1]; int reqWidth = reqBound[0]; int reqHeight = reqBound[1]; // calculate sample size int sampleSize = SampleSizeUtil.calculateSampleSize(width, height, reqWidth, reqHeight); if (withTextureLimit) { // adjust sample size sampleSize = SampleSizeUtil.adjustSampleSizeWithTexture(sampleSize, width, height); } int RETRY_LIMIT = 5; Bitmap bitmap = decodeSampled(pathName, sampleSize); while (bitmap == null && RETRY_LIMIT > 0) { sampleSize++; RETRY_LIMIT--; bitmap = decodeSampled(pathName, sampleSize); } return bitmap; } public static int[] decodeBound(String pathName) { BitmapFactory.Options options = new BitmapFactory.Options(); options.inJustDecodeBounds = true; BitmapFactory.decodeFile(pathName, options); return new int[]{options.outWidth, options.outHeight}; } public static int[] decodeBound(Resources res, int resId) { BitmapFactory.Options options = new BitmapFactory.Options(); options.inJustDecodeBounds = true; BitmapFactory.decodeResource(res, resId, options); return new int[]{options.outWidth, options.outHeight}; } private static int[] pickReqBoundWithRatio(int[] bound, int[][] reqBounds, float ratio) { float hRatio = bound[1] == 0 ? 0 : (float) bound[0] / (float) bound[1]; float vRatio = bound[0] == 0 ? 0 : (float) bound[1] / (float) bound[0]; if (hRatio >= ratio) { return reqBounds[0]; } else if (vRatio >= ratio) { return reqBounds[1]; } else { return reqBounds[2]; } } public static Bitmap decodeSampled(String pathName, int sampleSize) { BitmapFactory.Options options = new BitmapFactory.Options(); // RGB_565 options.inPreferredConfig = Bitmap.Config.RGB_565; // sample size options.inSampleSize = sampleSize; Bitmap bitmap = null; try { bitmap = BitmapFactory.decodeFile(pathName, options); } catch (OutOfMemoryError e) { e.printStackTrace(); return null; } return checkInBitmap(bitmap, options, pathName); } @TargetApi(Build.VERSION_CODES.HONEYCOMB) private static Bitmap checkInBitmap(Bitmap bitmap, BitmapFactory.Options options, String path) { boolean honeycomb = Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB; if (honeycomb && bitmap != options.inBitmap && options.inBitmap != null) { options.inBitmap.recycle(); options.inBitmap = null; } if (bitmap == null) { try { bitmap = BitmapFactory.decodeFile(path, options); } catch (OutOfMemoryError e) { e.printStackTrace(); } } return bitmap; } public static int[] decodeBound(File file) { InputStream is = null; try { is = new FileInputStream(file); int[] bound = decodeBound(is); return bound; } catch (FileNotFoundException e) { e.printStackTrace(); } finally { if (is != null) { try { is.close(); } catch (IOException e) { e.printStackTrace(); } } } return new int[]{0, 0}; } public static int[] decodeBound(InputStream is) { BitmapFactory.Options options = new BitmapFactory.Options(); options.inJustDecodeBounds = true; BitmapFactory.decodeStream(is, null, options); return new int[]{options.outWidth, options.outHeight}; } public static Bitmap decodeSampled(InputStream is, int reqWidth, int reqHeight) { BitmapFactory.Options options = new BitmapFactory.Options(); // RGB_565 options.inPreferredConfig = Bitmap.Config.RGB_565; // sample size options.inSampleSize = getSampleSize(is, reqWidth, reqHeight); try { return BitmapFactory.decodeStream(is, null, options); } catch (OutOfMemoryError e) { e.printStackTrace(); } return null; } public static Bitmap decodeSampled(String pathName, int reqWidth, int reqHeight) { return decodeSampled(pathName, getSampleSize(pathName, reqWidth, reqHeight)); } public static int getSampleSize(InputStream is, int reqWidth, int reqHeight) { // decode bound int[] bound = decodeBound(is); // calculate sample size int sampleSize = SampleSizeUtil.calculateSampleSize(bound[0], bound[1], reqWidth, reqHeight); return sampleSize; } public static int getSampleSize(String pathName, int reqWidth, int reqHeight) { // decode bound int[] bound = decodeBound(pathName); // calculate sample size int sampleSize = SampleSizeUtil.calculateSampleSize(bound[0], bound[1], reqWidth, reqHeight); return sampleSize; } /** * ******************************* decode resource ****************************************** */ public static Bitmap decodeSampled(Resources resources, int resId, int reqWidth, int reqHeight) { return decodeSampled(resources, resId, getSampleSize(resources, resId, reqWidth, reqHeight)); } public static int getSampleSize(Resources resources, int resId, int reqWidth, int reqHeight) { // decode bound int[] bound = decodeBound(resources, resId); // calculate sample size int sampleSize = SampleSizeUtil.calculateSampleSize(bound[0], bound[1], reqWidth, reqHeight); return sampleSize; } public static Bitmap decodeSampled(Resources res, int resId, int sampleSize) { BitmapFactory.Options options = new BitmapFactory.Options(); // RGB_565 options.inPreferredConfig = Bitmap.Config.RGB_565; // sample size options.inSampleSize = sampleSize; try { return BitmapFactory.decodeResource(res, resId, options); } catch (OutOfMemoryError e) { e.printStackTrace(); } return null; } public static boolean extractThumbnail(String videoPath, String thumbPath) { if (!AttachmentStore.isFileExist(thumbPath)) { Bitmap thumbnail = ThumbnailUtils.createVideoThumbnail(videoPath, MediaStore.Images.Thumbnails.MINI_KIND); if (thumbnail != null) { AttachmentStore.saveBitmap(thumbnail, thumbPath, true); return true; } } return false; } }