package com.netease.nim.uikit.common.util.media;
import android.content.Context;
import android.content.res.Resources;
import android.graphics.Bitmap;
import android.graphics.Bitmap.CompressFormat;
import android.graphics.Bitmap.Config;
import android.graphics.Matrix;
import android.graphics.drawable.BitmapDrawable;
import android.graphics.drawable.Drawable;
import android.media.ExifInterface;
import android.text.TextUtils;
import com.netease.nim.uikit.NimUIKit;
import com.netease.nim.uikit.R;
import com.netease.nim.uikit.common.util.file.AttachmentStore;
import com.netease.nim.uikit.common.util.file.FileUtil;
import com.netease.nim.uikit.common.util.log.LogUtil;
import com.netease.nim.uikit.common.util.storage.StorageType;
import com.netease.nim.uikit.common.util.storage.StorageUtil;
import com.netease.nim.uikit.common.util.string.StringUtil;
import com.netease.nim.uikit.session.viewholder.MsgViewHolderThumbBase;
import java.io.BufferedOutputStream;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
public class ImageUtil {
public static class ImageSize {
public int width = 0;
public int height = 0;
public ImageSize(int width, int height) {
this.width = width;
this.height = height;
}
}
public final static float MAX_IMAGE_RATIO = 5f;
public static Bitmap getDefaultBitmapWhenGetFail() {
try {
return getBitmapImmutableCopy(NimUIKit.getContext().getResources(), R.drawable.nim_image_download_failed);
} catch (Exception e) {
e.printStackTrace();
return null;
}
}
public static final Bitmap getBitmapImmutableCopy(Resources res, int id) {
return getBitmap(res.getDrawable(id)).copy(Config.RGB_565, false);
}
public static final Bitmap getBitmap(Drawable dr) {
if (dr == null) {
return null;
}
if (dr instanceof BitmapDrawable) {
return ((BitmapDrawable) dr).getBitmap();
}
return null;
}
public static Bitmap rotateBitmapInNeeded(String path, Bitmap srcBitmap) {
if (TextUtils.isEmpty(path) || srcBitmap == null) {
return null;
}
ExifInterface localExifInterface;
try {
localExifInterface = new ExifInterface(path);
int rotateInt = localExifInterface.getAttributeInt(
ExifInterface.TAG_ORIENTATION,
ExifInterface.ORIENTATION_NORMAL);
float rotate = getImageRotate(rotateInt);
if (rotate != 0) {
Matrix matrix = new Matrix();
matrix.postRotate(rotate);
Bitmap dstBitmap = Bitmap.createBitmap(srcBitmap, 0, 0,
srcBitmap.getWidth(), srcBitmap.getHeight(), matrix,
false);
if (dstBitmap == null) {
return srcBitmap;
} else {
if (srcBitmap != null && !srcBitmap.isRecycled()) {
srcBitmap.recycle();
}
return dstBitmap;
}
} else {
return srcBitmap;
}
} catch (IOException e) {
e.printStackTrace();
return srcBitmap;
}
}
/**
* 获得旋转角度
*
* @param rotate
* @return
*/
public static float getImageRotate(int rotate) {
float f;
if (rotate == 6) {
f = 90.0F;
} else if (rotate == 3) {
f = 180.0F;
} else if (rotate == 8) {
f = 270.0F;
} else {
f = 0.0F;
}
return f;
}
public static String makeThumbnail(Context context, File imageFile) {
String thumbFilePath = StorageUtil.getWritePath(imageFile.getName(),
StorageType.TYPE_THUMB_IMAGE);
File thumbFile = AttachmentStore.create(thumbFilePath);
if (thumbFile == null) {
return null;
}
boolean result = scaleThumbnail(
imageFile,
thumbFile,
MsgViewHolderThumbBase.getImageMaxEdge(),
MsgViewHolderThumbBase.getImageMinEdge(),
CompressFormat.JPEG,
60);
if (!result) {
AttachmentStore.delete(thumbFilePath);
return null;
}
return thumbFilePath;
}
public static Boolean scaleThumbnail(File srcFile, File dstFile, int dstMaxWH, int dstMinWH, CompressFormat compressFormat, int quality) {
Boolean bRet = false;
Bitmap srcBitmap = null;
Bitmap dstBitmap = null;
BufferedOutputStream bos = null;
try {
int[] bound = BitmapDecoder.decodeBound(srcFile);
ImageSize size = getThumbnailDisplaySize(bound[0], bound[1], dstMaxWH, dstMinWH);
srcBitmap = BitmapDecoder.decodeSampled(srcFile.getPath(), size.width, size.height);
// 旋转
ExifInterface localExifInterface = new ExifInterface(srcFile.getAbsolutePath());
int rotateInt = localExifInterface.getAttributeInt(
ExifInterface.TAG_ORIENTATION,
ExifInterface.ORIENTATION_NORMAL);
float rotate = getImageRotate(rotateInt);
Matrix matrix = new Matrix();
matrix.postRotate(rotate);
float inSampleSize = 1;
if (srcBitmap.getWidth() >= dstMinWH && srcBitmap.getHeight() <= dstMaxWH
&& srcBitmap.getWidth() >= dstMinWH && srcBitmap.getHeight() <= dstMaxWH) {
//如果第一轮拿到的srcBitmap尺寸都符合要求,不需要再做缩放
} else {
if (srcBitmap.getWidth() != size.width || srcBitmap.getHeight() != size.height) {
float widthScale = (float) size.width / (float) srcBitmap.getWidth();
float heightScale = (float) size.height / (float) srcBitmap.getHeight();
if (widthScale >= heightScale) {
size.width = srcBitmap.getWidth();
size.height /= widthScale;//必定小于srcBitmap.getHeight()
inSampleSize = widthScale;
} else {
size.width /= heightScale;//必定小于srcBitmap.getWidth()
size.height = srcBitmap.getHeight();
inSampleSize = heightScale;
}
}
}
matrix.postScale(inSampleSize, inSampleSize);
if (rotate == 0 && inSampleSize == 1) {
dstBitmap = srcBitmap;
} else {
dstBitmap = Bitmap.createBitmap(srcBitmap, 0, 0, size.width, size.height, matrix, true);
}
bos = new BufferedOutputStream(new FileOutputStream(dstFile));
dstBitmap.compress(compressFormat, quality, bos);
bos.flush();
bRet = true;
} catch (OutOfMemoryError e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} finally {
if (bos != null) {
try {
bos.close();
} catch (IOException e) {
e.printStackTrace();
}
}
if (srcBitmap != null && !srcBitmap.isRecycled()) {
srcBitmap.recycle();
srcBitmap = null;
}
if (dstBitmap != null && !dstBitmap.isRecycled()) {
dstBitmap.recycle();
dstBitmap = null;
}
}
return bRet;
}
public static ImageSize getThumbnailDisplaySize(float srcWidth, float srcHeight, float dstMaxWH, float dstMinWH) {
if (srcWidth <= 0 || srcHeight <= 0) { // bounds check
return new ImageSize((int) dstMinWH, (int) dstMinWH);
}
float shorter;
float longer;
boolean widthIsShorter;
//store
if (srcHeight < srcWidth) {
shorter = srcHeight;
longer = srcWidth;
widthIsShorter = false;
} else {
shorter = srcWidth;
longer = srcHeight;
widthIsShorter = true;
}
if (shorter < dstMinWH) {
float scale = dstMinWH / shorter;
shorter = dstMinWH;
if (longer * scale > dstMaxWH) {
longer = dstMaxWH;
} else {
longer *= scale;
}
} else if (longer > dstMaxWH) {
float scale = dstMaxWH / longer;
longer = dstMaxWH;
if (shorter * scale < dstMinWH) {
shorter = dstMinWH;
} else {
shorter *= scale;
}
}
//restore
if (widthIsShorter) {
srcWidth = shorter;
srcHeight = longer;
} else {
srcWidth = longer;
srcHeight = shorter;
}
return new ImageSize((int) srcWidth, (int) srcHeight);
}
public static File getScaledImageFileWithMD5(File imageFile, String mimeType) {
String filePath = imageFile.getPath();
if (!isInvalidPictureFile(mimeType)) {
LogUtil.i("ImageUtil", "is invalid picture file");
return null;
}
String tempFilePath = getTempFilePath(FileUtil.getExtensionName(filePath));
File tempImageFile = AttachmentStore.create(tempFilePath);
if (tempImageFile == null) {
return null;
}
CompressFormat compressFormat = CompressFormat.JPEG;
// 压缩数值由第三方开发者自行决定
int maxWidth = 720;
int quality = 60;
if (ImageUtil.scaleImage(imageFile, tempImageFile, maxWidth, compressFormat, quality)) {
return tempImageFile;
} else {
return null;
}
}
private static String getTempFilePath(String extension) {
return StorageUtil.getWritePath(
NimUIKit.getContext(),
"temp_image_" + StringUtil.get36UUID() + "." + extension,
StorageType.TYPE_TEMP);
}
public static Boolean scaleImage(File srcFile, File dstFile, int dstMaxWH, CompressFormat compressFormat, int quality) {
Boolean success = false;
try {
int inSampleSize = SampleSizeUtil.calculateSampleSize(srcFile.getAbsolutePath(), dstMaxWH * dstMaxWH);
Bitmap srcBitmap = BitmapDecoder.decodeSampled(srcFile.getPath(), inSampleSize);
if (srcBitmap == null) {
return success;
}
float rotate;
String mimeType = com.netease.nim.uikit.common.media.picker.util.BitmapUtil.getImageType(srcFile.getAbsolutePath());
if (!TextUtils.isEmpty(mimeType) && mimeType.equals("image/png")) {
// png格式不能使用ExifInterface
rotate = 0;
} else {
// 旋转
ExifInterface localExifInterface = new ExifInterface(srcFile.getAbsolutePath());
int rotateInt = localExifInterface.getAttributeInt(ExifInterface.TAG_ORIENTATION, ExifInterface.ORIENTATION_NORMAL);
rotate = getImageRotate(rotateInt);
}
Bitmap dstBitmap;
float scale = (float) Math.sqrt(((float) dstMaxWH * (float) dstMaxWH) / ((float) srcBitmap.getWidth() * (float) srcBitmap.getHeight()));
if (rotate == 0f && scale >= 1) {
dstBitmap = srcBitmap;
} else {
try {
Matrix matrix = new Matrix();
if (rotate != 0) {
matrix.postRotate(rotate);
}
if (scale < 1) {
matrix.postScale(scale, scale);
}
dstBitmap = Bitmap.createBitmap(srcBitmap, 0, 0, srcBitmap.getWidth(), srcBitmap.getHeight(), matrix, true);
} catch (OutOfMemoryError e) {
BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream(dstFile));
srcBitmap.compress(compressFormat, quality, bos);
bos.flush();
bos.close();
success = true;
if (!srcBitmap.isRecycled())
srcBitmap.recycle();
srcBitmap = null;
return success;
}
}
BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream(dstFile));
dstBitmap.compress(compressFormat, quality, bos);
bos.flush();
bos.close();
success = true;
if (!srcBitmap.isRecycled())
srcBitmap.recycle();
srcBitmap = null;
if (!dstBitmap.isRecycled())
dstBitmap.recycle();
dstBitmap = null;
} catch (Exception e) {
e.printStackTrace();
} catch (OutOfMemoryError e) {
e.printStackTrace();
}
return success;
}
public static ImageSize getThumbnailDisplaySize(int maxSide, int minSide, String imagePath) {
int[] bound = BitmapDecoder.decodeBound(imagePath);
ImageSize imageSize = getThumbnailDisplaySize(bound[0], bound[1], maxSide, minSide);
return imageSize;
}
public static int[] getBoundWithLength(int maxSide, Object imageObject, boolean resizeToDefault) {
int width = -1;
int height = -1;
int[] bound;
if (String.class.isInstance(imageObject)) {
bound = BitmapDecoder.decodeBound((String) imageObject);
width = bound[0];
height = bound[1];
} else if (Integer.class.isInstance(imageObject)) {
bound = BitmapDecoder.decodeBound(NimUIKit.getContext().getResources(), (Integer) imageObject);
width = bound[0];
height = bound[1];
} else if (InputStream.class.isInstance(imageObject)) {
bound = BitmapDecoder.decodeBound((InputStream) imageObject);
width = bound[0];
height = bound[1];
}
int defaultWidth = maxSide;
int defaultHeight = maxSide;
if (width <= 0 || height <= 0) {
width = defaultWidth;
height = defaultHeight;
} else if (resizeToDefault) {
if (width > height) {
height = (int) (defaultWidth * ((float) height / (float) width));
width = defaultWidth;
} else {
width = (int) (defaultHeight * ((float) width / (float) height));
height = defaultHeight;
}
}
return new int[]{width, height};
}
/**
* 下载失败与获取失败时都统一显示默认下载失败图片
*
* @return
*/
public static Bitmap getBitmapFromDrawableRes(int res) {
try {
return getBitmapImmutableCopy(NimUIKit.getContext().getResources(), res);
} catch (Exception e) {
e.printStackTrace();
return null;
}
}
public static boolean isInvalidPictureFile(String mimeType) {
String lowerCaseFilepath = mimeType.toLowerCase();
return (lowerCaseFilepath.contains("jpg") || lowerCaseFilepath.contains("jpeg")
|| lowerCaseFilepath.toLowerCase().contains("png") || lowerCaseFilepath.toLowerCase().contains("bmp") || lowerCaseFilepath
.toLowerCase().contains("gif"));
}
}