/** * * 创建人:SongZhiyong * 创建时间:2012-12-30 */ package com.jerome.utils.media; import java.io.ByteArrayOutputStream; import java.io.File; import java.io.FileOutputStream; import java.io.IOException; import android.graphics.Bitmap; import android.graphics.Bitmap.CompressFormat; import android.graphics.Bitmap.Config; import android.graphics.Canvas; import android.graphics.Color; import android.graphics.LinearGradient; import android.graphics.Matrix; import android.graphics.Paint; import android.graphics.PorterDuff; import android.graphics.PorterDuff.Mode; import android.graphics.PorterDuffXfermode; import android.graphics.Rect; import android.graphics.RectF; import android.graphics.Shader.TileMode; /** * 功能:Bitmap相关操作及特效 * * @author SongZhiyong * */ public class BitmapUtils { private static Bitmap destBmp = null; /** * 创建圆角图片 * * @param bmp * 源bitmap * @param radius * 圆角半径 * @return destBmp 已生成的圆角图片 * @throws Exception * 圆角直径大于最小边长 */ public static Bitmap createRoundCornerBmp(Bitmap bmp, int radius) throws Exception { if (2 * radius > Math.min(bmp.getWidth(), bmp.getHeight())) { throw new Exception("参数错误"); } destBmp = Bitmap.createBitmap(bmp.getWidth(), bmp.getHeight(), Config.ARGB_8888); Canvas canvas = new Canvas(destBmp); Paint paint = new Paint(); Rect rect = new Rect(0, 0, bmp.getWidth(), bmp.getHeight()); RectF rectF = new RectF(rect); // 去锯齿 paint.setAntiAlias(true); canvas.drawRoundRect(rectF, radius, radius, paint); // 设置相交模式 paint.setXfermode(new PorterDuffXfermode(Mode.SRC_IN)); canvas.drawBitmap(bmp, null, rect, paint); return destBmp; } /** * * getRoundedCornerBitmap: QQ代码中获取圆角bitmap * * @param @param paramBitmap * @param @param paramFloat * @param @param paramInt1 * @param @param paramInt2 * @param @return * @return Bitmap * @throws * @since 上午11:47:07 */ public static Bitmap getRoundedCornerBitmap(Bitmap srcBitmap, float radius, int width, int height) { Bitmap result; try { Bitmap localBitmap2 = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888); if (srcBitmap == null) { result = null; } else { Canvas canvas = new Canvas(localBitmap2); Paint localPaint = new Paint(); Rect localRect1 = new Rect(0, 0, srcBitmap.getWidth(), srcBitmap.getHeight()); Rect localRect2 = new Rect(0, 0, width, height); RectF localRectF = new RectF(localRect2); localPaint.setAntiAlias(true); canvas.drawARGB(0, 0, 0, 0); localPaint.setColor(-12434878); canvas.drawRoundRect(localRectF, radius, radius, localPaint); localPaint.setXfermode(new PorterDuffXfermode( PorterDuff.Mode.SRC_IN)); Matrix localMatrix = new Matrix(); localMatrix.setRectToRect(new RectF(localRect1), new RectF( localRect2), Matrix.ScaleToFit.FILL); canvas.drawBitmap(Bitmap.createBitmap(srcBitmap, 0, 0, srcBitmap.getWidth(), srcBitmap.getHeight(), localMatrix, true), localRect2, localRect2, localPaint); result = localBitmap2; } } catch (Throwable localThrowable) { localThrowable.printStackTrace(); result = null; } return result; } /** * 保存图片到指定的路径 * * @param bmp * 要保存的bitmap * @param path * 保存到的路径 * @param quality * 保存图片质量 * @param format * 压缩格式(CompressFormat.JPEG,CompressFormat.PNG) * @throws IOException * IO异常 */ public static void saveBitmap(CompressFormat format, Bitmap bmp, String path, int quality) throws IOException { File file = new File(path); if (!file.getParentFile().exists()) file.getParentFile().mkdirs(); if (!file.exists()) { file.createNewFile(); } FileOutputStream stream = new FileOutputStream(file); bmp.compress(format, quality, stream); } /** * 利用Matrix旋转图片 * * @param bmp * 需要旋转的图片 * @param degree * 旋转角度 * @return destBmp 旋转后的图片 */ public static Bitmap rotate(Bitmap bmp, int degree) { Matrix matrix = new Matrix(); matrix.postRotate(degree); destBmp = Bitmap.createBitmap(bmp, 0, 0, bmp.getWidth(), bmp.getHeight(), matrix, true); bmp.recycle(); return destBmp; } /** * 根据传入的Bitmap对象构建带有倒影的Bitmap * * @param bmp * 图片位图 * @return Bitmap 返回带有倒影的位图Bitmap * */ public static Bitmap createWithReflectedBmp(Bitmap bmp) { if (bmp == null) { return bmp; } // 图片与倒影之间的距离间隔 int reflectionGap = 4; int width = bmp.getWidth(); int height = bmp.getHeight(); // 变换所需的Matrix,完成 图片旋转,缩放等控制 Matrix matrix = new Matrix(); matrix.preScale(1, -1); // 获取倒影Bitmap Bitmap reflectionBitmap = Bitmap.createBitmap(bmp, 0, height / 2, width, height / 2, matrix, false); // 获取带倒影的Bitmap.即整体的效果图位图对象 Bitmap withReflectionBitmap = Bitmap.createBitmap(width, height + height / 2, Config.ARGB_8888); /** Bitmap的显示还需要画布Canvas来完成 */ // 由该位图对象创建初始画布(规定了画布的宽高) Canvas canvas = new Canvas(withReflectionBitmap); canvas.drawBitmap(bmp, 0, 0, null); // 绘制出原图与倒影之间的间隔,用矩形来描绘 Paint paint1 = new Paint(); canvas.drawRect(0, height, width, height + reflectionGap, paint1); // 绘制出倒影的Bitmap canvas.drawBitmap(reflectionBitmap, 0, height + reflectionGap, paint1); // 绘制线性渐变对象 Paint paint2 = new Paint(); LinearGradient shader = new LinearGradient(0, bmp.getHeight(), 0, withReflectionBitmap.getHeight() + reflectionGap, 0x70ffffff, 0x00ffffff, TileMode.CLAMP); // 把渐变效果应用在画笔上 paint2.setShader(shader); // 设置倒影的阴影度,使其与原来的图像颜色区别开来,此处显示灰度,会被染上下面的底部的原图片的倒影颜色,实现倒影的修饰 paint2.setXfermode(new PorterDuffXfermode(Mode.DST_IN)); // 用设置好的paint2绘制此倒影 canvas.drawRect(0, height, width, withReflectionBitmap.getHeight() + reflectionGap, paint2); return withReflectionBitmap; } /** * 怀旧效果(相对之前做了优化快一倍) * * @param bmp * 源bitmap * @return destBmp 怀旧效果的图片 * */ public static Bitmap createOlderBmp(Bitmap bmp) { int width = bmp.getWidth(); int height = bmp.getHeight(); destBmp = Bitmap.createBitmap(width, height, Bitmap.Config.RGB_565); int pixColor = 0; int pixR = 0; int pixG = 0; int pixB = 0; int newR = 0; int newG = 0; int newB = 0; int[] pixels = new int[width * height]; bmp.getPixels(pixels, 0, width, 0, 0, width, height); for (int i = 0; i < height; i++) { for (int k = 0; k < width; k++) { pixColor = pixels[width * i + k]; pixR = Color.red(pixColor); pixG = Color.green(pixColor); pixB = Color.blue(pixColor); newR = (int) (0.393 * pixR + 0.769 * pixG + 0.189 * pixB); newG = (int) (0.349 * pixR + 0.686 * pixG + 0.168 * pixB); newB = (int) (0.272 * pixR + 0.534 * pixG + 0.131 * pixB); int newColor = Color.argb(255, newR > 255 ? 255 : newR, newG > 255 ? 255 : newG, newB > 255 ? 255 : newB); pixels[width * i + k] = newColor; } } destBmp.setPixels(pixels, 0, width, 0, 0, width, height); return destBmp; } /** * 图片锐化(拉普拉斯变换) * * @param bmp * 源bitmap * @return 锐化后图片 */ public static Bitmap createSharpenBmp(Bitmap bmp) { // 拉普拉斯矩阵 int[] laplacian = new int[] { -1, -1, -1, -1, 9, -1, -1, -1, -1 }; int width = bmp.getWidth(); int height = bmp.getHeight(); destBmp = Bitmap.createBitmap(width, height, Bitmap.Config.RGB_565); int pixR = 0; int pixG = 0; int pixB = 0; int pixColor = 0; int newR = 0; int newG = 0; int newB = 0; int idx = 0; float alpha = 0.3F; int[] pixels = new int[width * height]; bmp.getPixels(pixels, 0, width, 0, 0, width, height); for (int i = 1, length = height - 1; i < length; i++) { for (int k = 1, len = width - 1; k < len; k++) { idx = 0; for (int m = -1; m <= 1; m++) { for (int n = -1; n <= 1; n++) { pixColor = pixels[(i + n) * width + k + m]; pixR = Color.red(pixColor); pixG = Color.green(pixColor); pixB = Color.blue(pixColor); newR = newR + (int) (pixR * laplacian[idx] * alpha); newG = newG + (int) (pixG * laplacian[idx] * alpha); newB = newB + (int) (pixB * laplacian[idx] * alpha); idx++; } } newR = Math.min(255, Math.max(0, newR)); newG = Math.min(255, Math.max(0, newG)); newB = Math.min(255, Math.max(0, newB)); pixels[i * width + k] = Color.argb(255, newR, newG, newB); newR = 0; newG = 0; newB = 0; } } destBmp.setPixels(pixels, 0, width, 0, 0, width, height); return destBmp; } /** * 柔化效果(高斯模糊)(优化后比上面快三倍) * * @param bmp * 源bitmap * @return destBmp 模糊后的图片 */ public static Bitmap createBlurBmp(Bitmap bmp) { // 高斯矩阵 int[] gauss = new int[] { 1, 2, 1, 2, 4, 2, 1, 2, 1 }; int width = bmp.getWidth(); int height = bmp.getHeight(); destBmp = Bitmap.createBitmap(width, height, Bitmap.Config.RGB_565); int pixR = 0; int pixG = 0; int pixB = 0; int pixColor = 0; int newR = 0; int newG = 0; int newB = 0; int delta = 16; // 值越小图片会越亮,越大则越暗 int idx = 0; int[] pixels = new int[width * height]; bmp.getPixels(pixels, 0, width, 0, 0, width, height); for (int i = 1, length = height - 1; i < length; i++) { for (int k = 1, len = width - 1; k < len; k++) { idx = 0; for (int m = -1; m <= 1; m++) { for (int n = -1; n <= 1; n++) { pixColor = pixels[(i + m) * width + k + n]; pixR = Color.red(pixColor); pixG = Color.green(pixColor); pixB = Color.blue(pixColor); newR = newR + (int) (pixR * gauss[idx]); newG = newG + (int) (pixG * gauss[idx]); newB = newB + (int) (pixB * gauss[idx]); idx++; } } newR /= delta; newG /= delta; newB /= delta; newR = Math.min(255, Math.max(0, newR)); newG = Math.min(255, Math.max(0, newG)); newB = Math.min(255, Math.max(0, newB)); pixels[i * width + k] = Color.argb(255, newR, newG, newB); newR = 0; newG = 0; newB = 0; } } destBmp.setPixels(pixels, 0, width, 0, 0, width, height); return destBmp; } /** * 底片效果 * * @param bmp * 源bitmap * @return 底片效果图片 */ public static Bitmap createFilmBmp(Bitmap bmp) { // RGBA的最大值 final int MAX_VALUE = 255; int width = bmp.getWidth(); int height = bmp.getHeight(); destBmp = Bitmap.createBitmap(width, height, Bitmap.Config.RGB_565); int pixR = 0; int pixG = 0; int pixB = 0; int pixColor = 0; int newR = 0; int newG = 0; int newB = 0; int[] pixels = new int[width * height]; bmp.getPixels(pixels, 0, width, 0, 0, width, height); int pos = 0; for (int i = 1, length = height - 1; i < length; i++) { for (int k = 1, len = width - 1; k < len; k++) { pos = i * width + k; pixColor = pixels[pos]; pixR = Color.red(pixColor); pixG = Color.green(pixColor); pixB = Color.blue(pixColor); newR = MAX_VALUE - pixR; newG = MAX_VALUE - pixG; newB = MAX_VALUE - pixB; newR = Math.min(MAX_VALUE, Math.max(0, newR)); newG = Math.min(MAX_VALUE, Math.max(0, newG)); newB = Math.min(MAX_VALUE, Math.max(0, newB)); pixels[pos] = Color.argb(MAX_VALUE, newR, newG, newB); } } destBmp.setPixels(pixels, 0, width, 0, 0, width, height); return destBmp; } /** * Bitmap转换到Byte[] * * @param bitmap * 源bitmap * @return byte 字节数组 */ public static byte[] bitmap2Bytes(Bitmap bitmap) { ByteArrayOutputStream bas = new ByteArrayOutputStream(); bitmap.compress(Bitmap.CompressFormat.JPEG, 100, bas); return bas.toByteArray(); } /** * 截取Bitmap为CenterCrop样式 * * @param @param source * @param @param newHeight * @param @param newWidth * @param @return 设定文件 * @return Bitmap DOM对象 * @throws * @since CodingExample Ver 1.1 */ public static Bitmap scaleCenterCrop(Bitmap source, int newHeight, int newWidth) { int sourceWidth = source.getWidth(); int sourceHeight = source.getHeight(); // Compute the scaling factors to fit the new height and width, // respectively. // To cover the final image, the final scaling will be the bigger // of these two. float xScale = (float) newWidth / sourceWidth; float yScale = (float) newHeight / sourceHeight; float scale = Math.max(xScale, yScale); // Now get the size of the source bitmap when scaled float scaledWidth = scale * sourceWidth; float scaledHeight = scale * sourceHeight; // Let's find out the upper left coordinates if the scaled bitmap // should be centered in the new size give by the parameters float left = (newWidth - scaledWidth) / 2; float top = (newHeight - scaledHeight) / 2; // The target rectangle for the new, scaled version of the source bitmap // will now // be RectF targetRect = new RectF(left, top, left + scaledWidth, top + scaledHeight); // Finally, we create a new bitmap of the specified size and draw our // new, // scaled bitmap onto it. Bitmap dest = Bitmap.createBitmap(newWidth, newHeight, source.getConfig()); Canvas canvas = new Canvas(dest); canvas.drawBitmap(source, null, targetRect, null); return dest; } }