/* * Copyright (C) 2011 Baidu Inc. All rights reserved. */ package com.example.datalibrary.utils; import android.content.Context; import android.graphics.Bitmap; import android.graphics.BitmapFactory; import android.graphics.Canvas; import android.graphics.Color; import android.graphics.Matrix; import android.graphics.Paint; import android.media.ExifInterface; import android.net.Uri; import android.os.Environment; import android.util.Base64; import android.util.Log; import com.baidu.idl.main.facesdk.model.BDFaceImageInstance; import com.baidu.idl.main.facesdk.model.BDFaceSDKCommon; import java.io.BufferedInputStream; import java.io.ByteArrayOutputStream; import java.io.File; import java.io.FileInputStream; import java.io.FileNotFoundException; import java.io.FileOutputStream; import java.io.IOException; import java.nio.ByteBuffer; /** * 这个类提供一些操作Bitmap的方法 */ public final class BitmapUtils { /** * 图像的旋转方向是0 */ public static final int ROTATE0 = 0; /** * 图像的旋转方向是90 */ public static final int ROTATE90 = 90; /** * 图像的旋转方向是180 */ public static final int ROTATE180 = 180; /** * 图像的旋转方向是270 */ public static final int ROTATE270 = 270; /** * 图像的旋转方向是360 */ public static final int ROTATE360 = 360; /** * 图片太大内存溢出后压缩的比例 */ public static final int PIC_COMPRESS_SIZE = 4; /** * 图像压缩边界 */ public static final int IMAGEBOUND = 128; /** * 图片显示最大边的像素 */ public static final int MAXLENTH = 1024; /** * Log TAG */ private static final String TAG = "ImageUtils"; /** * Log switch */ private static final boolean DEBUG = false; /** * 保存图片的质量:100 */ private static final int QUALITY = 100; /** * 默认的最大尺寸 */ private static final int DEFAULT_MAX_SIZE_CELL_NETWORK = 600; /** * 题编辑wifi环境下压缩的最大尺寸 */ private static final int QUESTION_MAX_SIZE_CELL_NETWORK = 1024; /** * 图片压缩的质量 */ private static final int QUESTION_IMAGE_JPG_QUALITY = 75; /** * 默认的图片压缩的质量 */ private static final int DEFAULT_IMAGE_JPG_QUALITY = 50; /** * 网络请求超时时间 */ private static final int CONNECTTIMEOUT = 3000; /** * Private constructor to prohibit nonsense instance creation. */ private BitmapUtils() { } /** * 得到要显示的图片数据 */ public static Bitmap createBitmap(byte[] data, float orientation) { Bitmap bitmap = null; Bitmap transformed = null; BitmapFactory.Options opts = new BitmapFactory.Options(); try { int width = 2000; int hight = 2000; int min = Math.min(width, hight); opts.inJustDecodeBounds = true; BitmapFactory.decodeByteArray(data, 0, data.length, opts); opts.inSampleSize = BitmapUtils.computeSampleSize(opts, min, BitmapUtils.MAXLENTH * BitmapUtils.MAXLENTH); opts.inJustDecodeBounds = false; bitmap = BitmapFactory.decodeByteArray(data, 0, data.length, opts); transformed = BitmapUtils.rotateBitmap(orientation, bitmap); } catch (OutOfMemoryError e) { e.printStackTrace(); if (bitmap != null && !bitmap.isRecycled()) { bitmap.recycle(); bitmap = null; } if (transformed != null && !transformed.isRecycled()) { transformed.recycle(); transformed = null; } opts.inJustDecodeBounds = true; BitmapFactory.decodeByteArray(data, 0, data.length, opts); opts.inSampleSize = BitmapUtils.computeSampleSize(opts, -1, opts.outWidth * opts.outHeight / BitmapUtils.PIC_COMPRESS_SIZE); opts.inJustDecodeBounds = false; bitmap = BitmapFactory.decodeByteArray(data, 0, data.length, opts); transformed = BitmapUtils.rotateBitmap(orientation, bitmap); } if (transformed != bitmap && bitmap != null) { bitmap.recycle(); bitmap = null; } return transformed; } /** * 根据从数据中读到的方向旋转图片 * * @param orientation 图片方向 * @param bitmap 要旋转的bitmap * @return 旋转后的图片 */ public static Bitmap rotateBitmap(float orientation, Bitmap bitmap) { Bitmap transformed; Matrix m = new Matrix(); if (orientation == 0) { transformed = bitmap; } else { m.setRotate(orientation); transformed = Bitmap.createBitmap(bitmap, 0, 0, bitmap.getWidth(), bitmap.getHeight(), m, true); } return transformed; } /** * 获取无损压缩图片合适的压缩比例 * * @param options 图片的一些设置项 * @param minSideLength 最小边长 * @param maxNumOfPixels 最大的像素数目 * @return 返回合适的压缩值 */ public static int computeSampleSize(BitmapFactory.Options options, int minSideLength, int maxNumOfPixels) { int initialSize = BitmapUtils.computeInitialSampleSize(options, minSideLength, maxNumOfPixels); int roundedSize; if (initialSize <= 8) { // SUPPRESS CHECKSTYLE roundedSize = 1; while (roundedSize < initialSize) { roundedSize <<= 1; } } else { roundedSize = (initialSize + 7) / 8 * 8; // SUPPRESS CHECKSTYLE } return roundedSize; } /** * 获取无损压缩图片的压缩比 * * @param options 图片的一些设置项 * @param minSideLength 最小边长 * @param maxNumOfPixels 最大的像素数目 * @return 返回合适的压缩值 */ public static int computeInitialSampleSize(BitmapFactory.Options options, int minSideLength, int maxNumOfPixels) { double w = options.outWidth; double h = options.outHeight; int lowerBound = (maxNumOfPixels == -1) ? 1 : (int) Math.ceil(Math.sqrt(w * h / maxNumOfPixels)); int upperBound = (minSideLength == -1) ? BitmapUtils.IMAGEBOUND : (int) Math.min( Math.floor(w / minSideLength), Math.floor(h / minSideLength)); if (upperBound < lowerBound) { return lowerBound; } if ((maxNumOfPixels == -1) && (minSideLength == -1)) { return 1; } else if (minSideLength == -1) { return lowerBound; } else { return upperBound; } } /** * 解析图片的旋转方向 * * @param path 图片的路径 * @return 旋转角度 */ public static int decodeImageDegree(String path) { int degree = ROTATE0; try { ExifInterface exifInterface = new ExifInterface(path); int orientation = exifInterface.getAttributeInt(ExifInterface.TAG_ORIENTATION, ExifInterface.ORIENTATION_NORMAL); switch (orientation) { case ExifInterface.ORIENTATION_ROTATE_90: degree = ROTATE90; break; case ExifInterface.ORIENTATION_ROTATE_180: degree = ROTATE180; break; case ExifInterface.ORIENTATION_ROTATE_270: degree = ROTATE270; break; default: degree = ROTATE0; break; } } catch (Exception e) { e.printStackTrace(); degree = ROTATE0; } return degree; } /** * 等比压缩图片 * * @param bitmap 原图 * @param scale 压缩因子 * @return 压缩后的图片 */ public static Bitmap scale(Bitmap bitmap, float scale) { Matrix matrix = new Matrix(); matrix.postScale(scale, scale); return Bitmap.createBitmap(bitmap, 0, 0, bitmap.getWidth(), bitmap.getHeight(), matrix, true); } /** * 尺寸缩放 * * @param bitmap bitmap * @param w width * @param h height * @return scaleBitmap */ public static Bitmap scale(Bitmap bitmap, int w, int h) { if (bitmap == null) { return null; } int width = bitmap.getWidth(); int height = bitmap.getHeight(); Matrix matrix = new Matrix(); float scaleWidth = ((float) w / width); float scaleHeight = ((float) h / height); matrix.postScale(scaleWidth, scaleHeight); return Bitmap.createBitmap(bitmap, 0, 0, width, height, matrix, true); } /** * 等比压缩图片 * * @param resBitmap 原图 * @param desWidth 压缩后图片的宽度 * @param desHeight 压缩后图片的高度 * @return 压缩后的图片 */ public static Bitmap calculateInSampleSize(Bitmap resBitmap, int desWidth, int desHeight) { if (resBitmap == null) { return null; } int resWidth = resBitmap.getWidth(); int resHeight = resBitmap.getHeight(); if (resHeight > desHeight || resWidth > desWidth) { // 计算出实际宽高和目标宽高的比率 final float heightRatio = (float) desHeight / (float) resHeight; final float widthRatio = (float) desWidth / (float) resWidth; float scale = heightRatio < widthRatio ? heightRatio : widthRatio; return scale(resBitmap, scale); } return resBitmap; } public static Uri saveTakePictureImage(Context context, byte[] data) { File file = context.getExternalFilesDir("file1"); file = new File(file.getAbsolutePath() + File.separator + System.currentTimeMillis() + ".jpg"); FileOutputStream fout = null; try { fout = new FileOutputStream(file); fout.write(data); fout.flush(); } catch (Exception e) { e.printStackTrace(); // 异常时删除保存失败的文件 try { if (file != null && file.exists() && file.isFile()) { file.delete(); } } catch (Exception ex) { ex.printStackTrace(); } return null; } finally { if (fout != null) { try { fout.close(); } catch (IOException e) { e.printStackTrace(); } } } Log.e(TAG, file.getAbsolutePath()); return Uri.fromFile(file); } public static Bitmap yuv2Bitmap(byte[] data, int width, int height) { int frameSize = width * height; int[] rgba = new int[frameSize]; for (int i = 0; i < height; i++) { for (int j = 0; j < width; j++) { int y = (0xff & ((int) data[i * width + j])); int u = (0xff & ((int) data[frameSize + (i >> 1) * width + (j & ~1) + 0])); int v = (0xff & ((int) data[frameSize + (i >> 1) * width + (j & ~1) + 1])); y = y < 16 ? 16 : y; int r = Math.round(1.164f * (y - 16) + 1.596f * (v - 128)); int g = Math.round(1.164f * (y - 16) - 0.813f * (v - 128) - 0.391f * (u - 128)); int b = Math.round(1.164f * (y - 16) + 2.018f * (u - 128)); r = r < 0 ? 0 : (r > 255 ? 255 : r); g = g < 0 ? 0 : (g > 255 ? 255 : g); b = b < 0 ? 0 : (b > 255 ? 255 : b); rgba[i * width + j] = 0xff000000 + (b << 16) + (g << 8) + r; } } Bitmap bmp = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888); bmp.setPixels(rgba, 0, width, 0, 0, width, height); return bmp; } public static Bitmap depthBitmap(byte[] depthBytes, int width, int height) { Bitmap bitmap = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888); int[] argbData = new int[width * height]; for (int i = 0; i < width * height; i++) { argbData[i] = (((int) depthBytes[i * 2] + depthBytes[i * 2 + 1] * 256) / 10 & 0x000000ff) | ((((int) depthBytes[i * 2] + depthBytes[i * 2 + 1] * 256) / 10) & 0x000000ff) << 8 | ((((int) depthBytes[i * 2] + depthBytes[i * 2 + 1] * 256) / 10) & 0x000000ff) << 16 | 0xff000000; } bitmap.setPixels(argbData, 0, width, 0, 0, width, height); return bitmap; } public static Bitmap depth2Bitmap(byte[] depthBytes, int width, int height) { Bitmap bitmap = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888); int[] argbData = new int[width * height * 2]; for (int i = 0; i < width * height; i++) { argbData[i] = (((int) depthBytes[i * 2] + depthBytes[i * 2 + 1] * 256) / 10 & 0x000000ff) | ((((int) depthBytes[i * 2] + depthBytes[i * 2 + 1] * 256) / 10) & 0x000000ff) << 8 | ((((int) depthBytes[i * 2] + depthBytes[i * 2 + 1] * 256) / 10) & 0x000000ff) << 16 | 0xff000000; } bitmap.setPixels(argbData, 0, width, 0, 0, width, height); return bitmap; } public static Bitmap rgb2Bitmap(byte[] bytes, int width, int height) { // use Bitmap.Config.ARGB_8888 instead of type is OK Bitmap stitchBmp = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888); byte[] rgba = new byte[width * height * 4]; for (int i = 0; i < width * height; i++) { byte b1 = bytes[i * 3 + 0]; byte b2 = bytes[i * 3 + 1]; byte b3 = bytes[i * 3 + 2]; // set value rgba[i * 4 + 0] = b1; rgba[i * 4 + 1] = b2; rgba[i * 4 + 2] = b3; rgba[i * 4 + 3] = (byte) 255; } stitchBmp.copyPixelsFromBuffer(ByteBuffer.wrap(rgba)); return stitchBmp; } public static Bitmap bgr2Bitmap(byte[] bytes, int width, int height) { // use Bitmap.Config.ARGB_8888 instead of type is OK Bitmap stitchBmp = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888); byte[] rgba = new byte[width * height * 4]; for (int i = 0; i < width * height; i++) { byte b1 = bytes[i * 3 + 0]; byte b2 = bytes[i * 3 + 1]; byte b3 = bytes[i * 3 + 2]; // set value rgba[i * 4 + 0] = b3; rgba[i * 4 + 1] = b2; rgba[i * 4 + 2] = b1; rgba[i * 4 + 3] = (byte) 255; } stitchBmp.copyPixelsFromBuffer(ByteBuffer.wrap(rgba)); return stitchBmp; } public static byte[] argb2R(byte[] bytes, int width, int height) { byte[] ir = new byte[width * height]; for (int i = 0; i < width * height; i++) { ir[i] = bytes[i * 4]; } return ir; } public static Bitmap getInstaceBmp(BDFaceImageInstance newInstance) { Bitmap transBmp = null; if (newInstance.imageType == BDFaceSDKCommon.BDFaceImageType.BDFACE_IMAGE_TYPE_RGBA) { transBmp = Bitmap.createBitmap(newInstance.width, newInstance.height, Bitmap.Config.ARGB_8888); transBmp.copyPixelsFromBuffer(ByteBuffer.wrap(newInstance.data)); } else if (newInstance.imageType == BDFaceSDKCommon.BDFaceImageType.BDFACE_IMAGE_TYPE_BGR) { transBmp = BitmapUtils.bgr2Bitmap(newInstance.data, newInstance.width, newInstance.height); } else if (newInstance.imageType == BDFaceSDKCommon.BDFaceImageType.BDFACE_IMAGE_TYPE_YUV_NV21) { transBmp = BitmapUtils.yuv2Bitmap(newInstance.data, newInstance.width, newInstance.height); } else if (newInstance.imageType == BDFaceSDKCommon.BDFaceImageType.BDFACE_IMAGE_TYPE_GRAY) { transBmp = depthBitmap(newInstance.data, newInstance.width, newInstance.height); } else if (newInstance.imageType == BDFaceSDKCommon.BDFaceImageType.BDFACE_IMAGE_TYPE_DEPTH) { transBmp = depth2Bitmap(newInstance.data, newInstance.width, newInstance.height); } return transBmp; } /** * 获取图片数据 * * @param path * @return */ public static Bitmap getBitmap(String path) { FileInputStream fis; Bitmap bm = null; try { fis = new FileInputStream(path); BitmapFactory.Options options = new BitmapFactory.Options(); // 图片的长宽都是原来的1/8 options.inSampleSize = 8; BufferedInputStream bis = new BufferedInputStream(fis); bm = BitmapFactory.decodeStream(bis, null, options); fis.close(); } catch (FileNotFoundException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); } return bm; } public static Bitmap base64ToBitmap(String base64String) { base64String = Uri.decode(base64String); byte[] decode = Base64.decode(base64String, Base64.DEFAULT); Bitmap bitmap = BitmapFactory.decodeByteArray(decode, 0, decode.length); return bitmap; } public static byte[] bitmapToBytes(Bitmap bm) { ByteArrayOutputStream baos = new ByteArrayOutputStream(); bm.compress(Bitmap.CompressFormat.PNG, 100, baos); return baos.toByteArray(); } public static void saveRgbBitmap(Bitmap bitmap, String dirName, String fileName) { String path = Environment.getExternalStorageDirectory().getAbsolutePath(); File dir = new File(path + "/" + dirName); dir.mkdirs(); long time = System.currentTimeMillis(); File jpgFile = new File(dir + File.separator + fileName + ".png"); try { if (!jpgFile.exists()) { jpgFile.createNewFile(); } FileOutputStream fileOutputStream = new FileOutputStream(jpgFile); bitmap.compress(Bitmap.CompressFormat.PNG, 100, fileOutputStream); fileOutputStream.flush(); fileOutputStream.close(); // Log.e("Save-Image-tag", "rgb图片保存成功"); } catch (IOException e) { e.printStackTrace(); } } public static Bitmap adjustPhotoRotation(Bitmap bm, final int orientationDegree) { Matrix m = new Matrix(); m.setRotate(orientationDegree, (float) bm.getWidth() / 2, (float) bm.getHeight() / 2); try { Bitmap bm1 = Bitmap.createBitmap(bm, 0, 0, bm.getWidth(), bm.getHeight(), m, true); return bm1; } catch (OutOfMemoryError ex) { return null; } } public static Bitmap broadImage(Bitmap bm) { if (bm == null) { return null; } int width = bm.getWidth(); int height = bm.getHeight(); int outwardWidth = (int) (width * 0.35); int outwardHeight = (int) (height * 0.35); // 创建目标大小Bitmap Bitmap scaledImage = Bitmap.createBitmap(width + outwardWidth, height + outwardHeight, Bitmap.Config.ARGB_8888); Canvas canvas = new Canvas(scaledImage); // 绘制背景颜色 Paint paint = new Paint(); paint.setColor(Color.parseColor("#ffffff")); paint.setStyle(Paint.Style.FILL); canvas.drawRect(0, 0, canvas.getWidth(), canvas.getHeight(), paint); canvas.drawBitmap( bm, outwardWidth / 2 , outwardHeight / 2, null ); // if (!bm.isRecycled()){ // bm.recycle(); // } return scaledImage; } }