package cn.hotapk.fastandrutils.utils; import android.annotation.TargetApi; import android.graphics.Bitmap; import android.graphics.BitmapFactory; import android.graphics.BitmapShader; import android.graphics.Canvas; import android.graphics.Color; import android.graphics.ColorMatrix; import android.graphics.ColorMatrixColorFilter; import android.graphics.ImageFormat; import android.graphics.LinearGradient; import android.graphics.Matrix; import android.graphics.Paint; import android.graphics.PixelFormat; import android.graphics.PorterDuff; import android.graphics.PorterDuffColorFilter; import android.graphics.PorterDuffXfermode; import android.graphics.Rect; import android.graphics.RectF; import android.graphics.Shader; import android.graphics.YuvImage; import android.graphics.drawable.BitmapDrawable; import android.graphics.drawable.Drawable; import android.media.ExifInterface; import android.os.Build; import android.renderscript.Allocation; import android.renderscript.Element; import android.renderscript.RenderScript; import android.renderscript.ScriptIntrinsicBlur; import android.support.annotation.ColorInt; import android.support.annotation.DrawableRes; import android.support.annotation.FloatRange; import android.support.annotation.IntRange; import android.support.v4.content.ContextCompat; import android.util.Base64; import android.view.View; import java.io.BufferedInputStream; import java.io.BufferedOutputStream; import java.io.ByteArrayOutputStream; import java.io.File; import java.io.FileDescriptor; import java.io.FileOutputStream; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; /** * @author laijian * @version 2017/9/18 * @Copyright (C)下午10:30 , www.hotapk.cn * 图片工具类 */ public final class FImageUtils { private FImageUtils() { } /** * bitmap转byteArr * * @param bitmap bitmap对象 * @param format 格式 * @return 字节数组 */ public static byte[] bitmap2Bytes(final Bitmap bitmap, final Bitmap.CompressFormat format) { if (bitmap == null) return null; ByteArrayOutputStream baos = new ByteArrayOutputStream(); bitmap.compress(format, 100, baos); return baos.toByteArray(); } /** * yuv转jpeg * * @param yuvBytes * @param width * @param height * @return */ public static byte[] yuv2Jpeg(byte[] yuvBytes, int width, int height) { YuvImage yuvImage = new YuvImage(yuvBytes, ImageFormat.NV21, width, height, null); ByteArrayOutputStream baos = new ByteArrayOutputStream(); yuvImage.compressToJpeg(new Rect(0, 0, width, height), 100, baos); return baos.toByteArray(); } /** * 将Bitmap转换成Base64字符串 * * @param bit 图片 * @return base64 编码的图片 */ public static String bitmap2StrByBase64(Bitmap bit) { if (bit == null) return null; byte[] bytes = bitmap2Bytes(bit, Bitmap.CompressFormat.JPEG); return Base64.encodeToString(bytes, Base64.DEFAULT); } /** * Base64字符串转bitmap * * @param base64 * @return */ public static Bitmap base64ToBitmap(String base64) { byte[] base64ToByte = FEncryptUtils.base64ToByte(base64); return bytes2Bitmap(base64ToByte); } /** * drawable转byteArr * * @param drawable drawable对象 * @param format 格式 * @return 字节数组 */ public static byte[] drawable2Bytes(final Drawable drawable, final Bitmap.CompressFormat format) { return drawable == null ? null : bitmap2Bytes(drawable2Bitmap(drawable), format); } /** * 读取图片属性:旋转的角度 * * @param path 图片绝对路径 * @return degree旋转的角度 */ public static int readPictureDegree(String path) { int degree = 0; try { ExifInterface exifInterface = new ExifInterface(path); int orientation = exifInterface.getAttributeInt(ExifInterface.TAG_ORIENTATION, ExifInterface.ORIENTATION_NORMAL); switch (orientation) { case ExifInterface.ORIENTATION_ROTATE_90: degree = 90; break; case ExifInterface.ORIENTATION_ROTATE_180: degree = 180; break; case ExifInterface.ORIENTATION_ROTATE_270: degree = 270; break; } } catch (IOException e) { e.printStackTrace(); } return degree; } /** * 旋转图片 * * @param angle * @param bitmap * @return */ public static Bitmap rotaingImageView(int angle, Bitmap bitmap) { // 旋转图片 动作 // 创建新的图片 Bitmap resizedBitmap = null; try { Matrix matrix = new Matrix(); matrix.postRotate(angle); resizedBitmap = Bitmap.createBitmap(bitmap, 0, 0, bitmap.getWidth(), bitmap.getHeight(), matrix, true); } catch (Error e) { // TODO Auto-generated catch block e.printStackTrace(); } return resizedBitmap; } /** * byteArr转bitmap * * @param bytes 字节数组 * @return bitmap */ public static Bitmap bytes2Bitmap(final byte[] bytes) { return (bytes == null || bytes.length == 0) ? null : BitmapFactory.decodeByteArray(bytes, 0, bytes.length); } /** * drawable转bitmap * * @param drawable drawable对象 * @return bitmap */ public static Bitmap drawable2Bitmap(final Drawable drawable) { if (drawable instanceof BitmapDrawable) { BitmapDrawable bitmapDrawable = (BitmapDrawable) drawable; if (bitmapDrawable.getBitmap() != null) { return bitmapDrawable.getBitmap(); } } Bitmap bitmap; if (drawable.getIntrinsicWidth() <= 0 || drawable.getIntrinsicHeight() <= 0) { bitmap = Bitmap.createBitmap(1, 1, drawable.getOpacity() != PixelFormat.OPAQUE ? Bitmap.Config.ARGB_8888 : Bitmap.Config.RGB_565); } else { bitmap = Bitmap.createBitmap(drawable.getIntrinsicWidth(), drawable.getIntrinsicHeight(), drawable.getOpacity() != PixelFormat.OPAQUE ? Bitmap.Config.ARGB_8888 : Bitmap.Config.RGB_565); } Canvas canvas = new Canvas(bitmap); drawable.setBounds(0, 0, canvas.getWidth(), canvas.getHeight()); drawable.draw(canvas); return bitmap; } /** * bitmap转drawable * * @param bitmap bitmap对象 * @return drawable */ public static Drawable bitmap2Drawable(final Bitmap bitmap) { return bitmap == null ? null : new BitmapDrawable(FUtils.getAppContext().getResources(), bitmap); } /** * byteArr转drawable * * @param bytes 字节数组 * @return drawable */ public static Drawable bytes2Drawable(final byte[] bytes) { return bitmap2Drawable(bytes2Bitmap(bytes)); } /** * view转bitmap * * @param view 视图 * @return bitmap */ public static Bitmap view2Bitmap(final View view) { if (view == null) return null; Bitmap ret = Bitmap.createBitmap(view.getWidth(), view.getHeight(), Bitmap.Config.ARGB_8888); Canvas canvas = new Canvas(ret); Drawable bgDrawable = view.getBackground(); if (bgDrawable != null) { bgDrawable.draw(canvas); } else { canvas.drawColor(Color.WHITE); } view.draw(canvas); return ret; } /** * 获取bitmap * * @param file 文件 * @return bitmap */ public static Bitmap getBitmap(final File file) { if (file == null) return null; InputStream is = null; InputStream fileinp = FFileUtils.file2Inp(file.getAbsolutePath()); if (fileinp != null) { is = new BufferedInputStream(fileinp); return BitmapFactory.decodeStream(is); } else { return null; } } /** * 获取bitmap * * @param filePath 文件路径 * @return bitmap */ public static Bitmap getBitmap(final String filePath) { if (isSpace(filePath)) return null; return BitmapFactory.decodeFile(filePath); } /** * 获取bitmap * * @param is 输入流 * @return bitmap */ public static Bitmap getBitmap(final InputStream is) { if (is == null) return null; return BitmapFactory.decodeStream(is); } /** * 获取bitmap * * @param data 数据 * @param offset 偏移量 * @return bitmap */ public static Bitmap getBitmap(final byte[] data, final int offset) { if (data.length == 0) return null; return BitmapFactory.decodeByteArray(data, offset, data.length); } /** * 获取bitmap * * @param resId 资源id * @return bitmap */ public static Bitmap getBitmap(@DrawableRes final int resId) { Drawable drawable = ContextCompat.getDrawable(FUtils.getAppContext(), resId); Canvas canvas = new Canvas(); Bitmap bitmap = Bitmap.createBitmap(drawable.getIntrinsicWidth(), drawable.getIntrinsicHeight(), Bitmap.Config.ARGB_8888); canvas.setBitmap(bitmap); drawable.setBounds(0, 0, drawable.getIntrinsicWidth(), drawable.getIntrinsicHeight()); drawable.draw(canvas); return bitmap; } /** * 获取bitmap * * @param fd 文件描述 * @return bitmap */ public static Bitmap getBitmap(final FileDescriptor fd) { if (fd == null) return null; return BitmapFactory.decodeFileDescriptor(fd); } /** * 缩放图片 * * @param src 源图片 * @param newWidth 新宽度 * @param newHeight 新高度 * @return 缩放后的图片 */ public static Bitmap scale(final Bitmap src, final int newWidth, final int newHeight) { return scale(src, newWidth, newHeight, false); } /** * 缩放图片 * * @param src 源图片 * @param newWidth 新宽度 * @param newHeight 新高度 * @param recycle 是否回收 * @return 缩放后的图片 */ public static Bitmap scale(final Bitmap src, final int newWidth, final int newHeight, final boolean recycle) { if (isEmptyBitmap(src)) return null; Bitmap ret = Bitmap.createScaledBitmap(src, newWidth, newHeight, true); if (recycle && !src.isRecycled()) src.recycle(); return ret; } /** * 缩放图片 * * @param src 源图片 * @param scaleWidth 缩放宽度倍数 * @param scaleHeight 缩放高度倍数 * @return 缩放后的图片 */ public static Bitmap scale(final Bitmap src, final float scaleWidth, final float scaleHeight) { return scale(src, scaleWidth, scaleHeight, false); } /** * 缩放图片 * * @param src 源图片 * @param scaleWidth 缩放宽度倍数 * @param scaleHeight 缩放高度倍数 * @param recycle 是否回收 * @return 缩放后的图片 */ public static Bitmap scale(final Bitmap src, final float scaleWidth, final float scaleHeight, final boolean recycle) { if (isEmptyBitmap(src)) return null; Matrix matrix = new Matrix(); matrix.setScale(scaleWidth, scaleHeight); Bitmap ret = Bitmap.createBitmap(src, 0, 0, src.getWidth(), src.getHeight(), matrix, true); if (recycle && !src.isRecycled()) src.recycle(); return ret; } /** * 裁剪图片 * * @param src 源图片 * @param x 开始坐标x * @param y 开始坐标y * @param width 裁剪宽度 * @param height 裁剪高度 * @return 裁剪后的图片 */ public static Bitmap clip(final Bitmap src, final int x, final int y, final int width, final int height) { return clip(src, x, y, width, height, false); } /** * 裁剪图片 * * @param src 源图片 * @param x 开始坐标x * @param y 开始坐标y * @param width 裁剪宽度 * @param height 裁剪高度 * @param recycle 是否回收 * @return 裁剪后的图片 */ public static Bitmap clip(final Bitmap src, final int x, final int y, final int width, final int height, final boolean recycle) { if (isEmptyBitmap(src)) return null; Bitmap ret = Bitmap.createBitmap(src, x, y, width, height); if (recycle && !src.isRecycled()) src.recycle(); return ret; } /** * 倾斜图片 * * @param src 源图片 * @param kx 倾斜因子x * @param ky 倾斜因子y * @return 倾斜后的图片 */ public static Bitmap skew(final Bitmap src, final float kx, final float ky) { return skew(src, kx, ky, 0, 0, false); } /** * 倾斜图片 * * @param src 源图片 * @param kx 倾斜因子x * @param ky 倾斜因子y * @param recycle 是否回收 * @return 倾斜后的图片 */ public static Bitmap skew(final Bitmap src, final float kx, final float ky, final boolean recycle) { return skew(src, kx, ky, 0, 0, recycle); } /** * 倾斜图片 * * @param src 源图片 * @param kx 倾斜因子x * @param ky 倾斜因子y * @param px 平移因子x * @param py 平移因子y * @return 倾斜后的图片 */ public static Bitmap skew(final Bitmap src, final float kx, final float ky, final float px, final float py) { return skew(src, kx, ky, px, py, false); } /** * 倾斜图片 * * @param src 源图片 * @param kx 倾斜因子x * @param ky 倾斜因子y * @param px 平移因子x * @param py 平移因子y * @param recycle 是否回收 * @return 倾斜后的图片 */ public static Bitmap skew(final Bitmap src, final float kx, final float ky, final float px, final float py, final boolean recycle) { if (isEmptyBitmap(src)) return null; Matrix matrix = new Matrix(); matrix.setSkew(kx, ky, px, py); Bitmap ret = Bitmap.createBitmap(src, 0, 0, src.getWidth(), src.getHeight(), matrix, true); if (recycle && !src.isRecycled()) src.recycle(); return ret; } /** * 旋转图片 * * @param src 源图片 * @param degrees 旋转角度 * @param px 旋转点横坐标 * @param py 旋转点纵坐标 * @return 旋转后的图片 */ public static Bitmap rotate(final Bitmap src, final int degrees, final float px, final float py) { return rotate(src, degrees, px, py, false); } /** * 旋转图片 * * @param src 源图片 * @param degrees 旋转角度 * @param px 旋转点横坐标 * @param py 旋转点纵坐标 * @param recycle 是否回收 * @return 旋转后的图片 */ public static Bitmap rotate(final Bitmap src, final int degrees, final float px, final float py, final boolean recycle) { if (isEmptyBitmap(src)) return null; if (degrees == 0) return src; Matrix matrix = new Matrix(); matrix.setRotate(degrees, px, py); Bitmap ret = Bitmap.createBitmap(src, 0, 0, src.getWidth(), src.getHeight(), matrix, true); if (recycle && !src.isRecycled()) src.recycle(); return ret; } /** * 获取图片旋转角度 * * @param filePath 文件路径 * @return 旋转角度 */ public static int getRotateDegree(final String filePath) { int degree = 0; try { ExifInterface exifInterface = new ExifInterface(filePath); int orientation = exifInterface.getAttributeInt( ExifInterface.TAG_ORIENTATION, ExifInterface.ORIENTATION_NORMAL); switch (orientation) { default: case ExifInterface.ORIENTATION_ROTATE_90: degree = 90; break; case ExifInterface.ORIENTATION_ROTATE_180: degree = 180; break; case ExifInterface.ORIENTATION_ROTATE_270: degree = 270; break; } } catch (IOException e) { e.printStackTrace(); } return degree; } /** * 转为圆形图片 * * @param src 源图片 * @return 圆形图片 */ public static Bitmap toRound(final Bitmap src) { return toRound(src, 0, 0, false); } /** * 转为圆形图片 * * @param src 源图片 * @param recycle 是否回收 * @return 圆形图片 */ public static Bitmap toRound(final Bitmap src, final boolean recycle) { return toRound(src, 0, 0, recycle); } /** * 转为圆形图片 * * @param src 源图片 * @param borderSize 边框尺寸 * @param borderColor 边框颜色 * @return 圆形图片 */ public static Bitmap toRound(final Bitmap src, @IntRange(from = 0) int borderSize, @ColorInt int borderColor) { return toRound(src, borderSize, borderColor, false); } /** * 转为圆形图片 * * @param src 源图片 * @param recycle 是否回收 * @param borderSize 边框尺寸 * @param borderColor 边框颜色 * @return 圆形图片 */ public static Bitmap toRound(final Bitmap src, @IntRange(from = 0) int borderSize, @ColorInt int borderColor, final boolean recycle) { if (isEmptyBitmap(src)) return null; int width = src.getWidth(); int height = src.getHeight(); int size = Math.min(width, height); Paint paint = new Paint(Paint.ANTI_ALIAS_FLAG); Bitmap ret = Bitmap.createBitmap(width, height, src.getConfig()); float center = size / 2f; RectF rectF = new RectF(0, 0, width, height); rectF.inset((width - size) / 2f, (height - size) / 2f); Matrix matrix = new Matrix(); matrix.setTranslate(rectF.left, rectF.top); matrix.preScale((float) size / width, (float) size / height); BitmapShader shader = new BitmapShader(src, Shader.TileMode.CLAMP, Shader.TileMode.CLAMP); shader.setLocalMatrix(matrix); paint.setShader(shader); Canvas canvas = new Canvas(ret); canvas.drawRoundRect(rectF, center, center, paint); if (borderSize > 0) { paint.setShader(null); paint.setColor(borderColor); paint.setStyle(Paint.Style.STROKE); paint.setStrokeWidth(borderSize); float radius = center - borderSize / 2f; canvas.drawCircle(width / 2f, height / 2f, radius, paint); } if (recycle && !src.isRecycled()) src.recycle(); return ret; } /** * 转为圆角图片 * * @param src 源图片 * @param radius 圆角的度数 * @return 圆角图片 */ public static Bitmap toRoundCorner(final Bitmap src, final float radius) { return toRoundCorner(src, radius, 0, 0, false); } /** * 转为圆角图片 * * @param src 源图片 * @param radius 圆角的度数 * @param recycle 是否回收 * @return 圆角图片 */ public static Bitmap toRoundCorner(final Bitmap src, final float radius, final boolean recycle) { return toRoundCorner(src, radius, 0, 0, recycle); } /** * 转为圆角图片 * * @param src 源图片 * @param radius 圆角的度数 * @param borderSize 边框尺寸 * @param borderColor 边框颜色 * @return 圆角图片 */ public static Bitmap toRoundCorner(final Bitmap src, final float radius, @IntRange(from = 0) int borderSize, @ColorInt int borderColor) { return toRoundCorner(src, radius, borderSize, borderColor, false); } /** * 转为圆角图片 * * @param src 源图片 * @param radius 圆角的度数 * @param borderSize 边框尺寸 * @param borderColor 边框颜色 * @param recycle 是否回收 * @return 圆角图片 */ public static Bitmap toRoundCorner(final Bitmap src, final float radius, @IntRange(from = 0) int borderSize, @ColorInt int borderColor, final boolean recycle) { if (isEmptyBitmap(src)) return null; int width = src.getWidth(); int height = src.getHeight(); Paint paint = new Paint(Paint.ANTI_ALIAS_FLAG); Bitmap ret = Bitmap.createBitmap(width, height, src.getConfig()); BitmapShader shader = new BitmapShader(src, Shader.TileMode.CLAMP, Shader.TileMode.CLAMP); paint.setShader(shader); Canvas canvas = new Canvas(ret); RectF rectF = new RectF(0, 0, width, height); float halfBorderSize = borderSize / 2f; rectF.inset(halfBorderSize, halfBorderSize); canvas.drawRoundRect(rectF, radius, radius, paint); if (borderSize > 0) { paint.setShader(null); paint.setColor(borderColor); paint.setStyle(Paint.Style.STROKE); paint.setStrokeWidth(borderSize); paint.setStrokeCap(Paint.Cap.ROUND); canvas.drawRoundRect(rectF, radius, radius, paint); } if (recycle && !src.isRecycled()) src.recycle(); return ret; } /** * 添加圆角边框 * * @param src 源图片 * @param borderSize 边框尺寸 * @param color 边框颜色 * @param cornerRadius 圆角半径 * @return 圆角边框图 */ public static Bitmap addCornerBorder(final Bitmap src, @IntRange(from = 1) final int borderSize, @ColorInt final int color, @FloatRange(from = 0) final float cornerRadius) { return addBorder(src, borderSize, color, false, cornerRadius, false); } /** * 添加圆角边框 * * @param src 源图片 * @param borderSize 边框尺寸 * @param color 边框颜色 * @param cornerRadius 圆角半径 * @param recycle 是否回收 * @return 圆角边框图 */ public static Bitmap addCornerBorder(final Bitmap src, @IntRange(from = 1) final int borderSize, @ColorInt final int color, @FloatRange(from = 0) final float cornerRadius, final boolean recycle) { return addBorder(src, borderSize, color, false, cornerRadius, recycle); } /** * 添加圆形边框 * * @param src 源图片 * @param borderSize 边框尺寸 * @param color 边框颜色 * @return 圆形边框图 */ public static Bitmap addCircleBorder(final Bitmap src, @IntRange(from = 1) final int borderSize, @ColorInt final int color) { return addBorder(src, borderSize, color, true, 0, false); } /** * 添加圆形边框 * * @param src 源图片 * @param borderSize 边框尺寸 * @param color 边框颜色 * @param recycle 是否回收 * @return 圆形边框图 */ public static Bitmap addCircleBorder(final Bitmap src, @IntRange(from = 1) final int borderSize, @ColorInt final int color, final boolean recycle) { return addBorder(src, borderSize, color, true, 0, recycle); } /** * 添加边框 * * @param src 源图片 * @param borderSize 边框尺寸 * @param color 边框颜色 * @param isCircle 是否画圆 * @param cornerRadius 圆角半径 * @param recycle 是否回收 * @return 边框图 */ private static Bitmap addBorder(final Bitmap src, @IntRange(from = 1) final int borderSize, @ColorInt final int color, final boolean isCircle, final float cornerRadius, final boolean recycle) { if (isEmptyBitmap(src)) return null; Bitmap ret = recycle ? src : src.copy(src.getConfig(), true); int width = ret.getWidth(); int height = ret.getHeight(); Canvas canvas = new Canvas(ret); Paint paint = new Paint(Paint.ANTI_ALIAS_FLAG); paint.setColor(color); paint.setStyle(Paint.Style.STROKE); paint.setStrokeWidth(borderSize); if (isCircle) { float radius = Math.min(width, height) / 2f - borderSize / 2f; canvas.drawCircle(width / 2f, height / 2f, radius, paint); } else { int halfBorderSize = borderSize >> 1; RectF rectF = new RectF(halfBorderSize, halfBorderSize, width - halfBorderSize, height - halfBorderSize); canvas.drawRoundRect(rectF, cornerRadius, cornerRadius, paint); } return ret; } /** * 添加倒影 * * @param src 源图片的 * @param reflectionHeight 倒影高度 * @return 带倒影图片 */ public static Bitmap addReflection(final Bitmap src, final int reflectionHeight) { return addReflection(src, reflectionHeight, false); } /** * 添加倒影 * * @param src 源图片的 * @param reflectionHeight 倒影高度 * @param recycle 是否回收 * @return 带倒影图片 */ public static Bitmap addReflection(final Bitmap src, final int reflectionHeight, final boolean recycle) { if (isEmptyBitmap(src)) return null; // 原图与倒影之间的间距 final int REFLECTION_GAP = 0; int srcWidth = src.getWidth(); int srcHeight = src.getHeight(); Matrix matrix = new Matrix(); matrix.preScale(1, -1); Bitmap reflectionBitmap = Bitmap.createBitmap(src, 0, srcHeight - reflectionHeight, srcWidth, reflectionHeight, matrix, false); Bitmap ret = Bitmap.createBitmap(srcWidth, srcHeight + reflectionHeight, src.getConfig()); Canvas canvas = new Canvas(ret); canvas.drawBitmap(src, 0, 0, null); canvas.drawBitmap(reflectionBitmap, 0, srcHeight + REFLECTION_GAP, null); Paint paint = new Paint(Paint.ANTI_ALIAS_FLAG); LinearGradient shader = new LinearGradient( 0, srcHeight, 0, ret.getHeight() + REFLECTION_GAP, 0x70FFFFFF, 0x00FFFFFF, Shader.TileMode.MIRROR); paint.setShader(shader); paint.setXfermode(new PorterDuffXfermode(android.graphics.PorterDuff.Mode.DST_IN)); canvas.drawRect(0, srcHeight + REFLECTION_GAP, srcWidth, ret.getHeight(), paint); if (!reflectionBitmap.isRecycled()) reflectionBitmap.recycle(); if (recycle && !src.isRecycled()) src.recycle(); return ret; } /** * 添加文字水印 * * @param src 源图片 * @param content 水印文本 * @param textSize 水印字体大小 * @param color 水印字体颜色 * @param x 起始坐标x * @param y 起始坐标y * @return 带有文字水印的图片 */ public static Bitmap addTextWatermark(final Bitmap src, final String content, final int textSize, @ColorInt final int color, final float x, final float y) { return addTextWatermark(src, content, textSize, color, x, y, false); } /** * 添加文字水印 * * @param src 源图片 * @param content 水印文本 * @param textSize 水印字体大小 * @param color 水印字体颜色 * @param x 起始坐标x * @param y 起始坐标y * @param recycle 是否回收 * @return 带有文字水印的图片 */ public static Bitmap addTextWatermark(final Bitmap src, final String content, final float textSize, @ColorInt final int color, final float x, final float y, final boolean recycle) { if (isEmptyBitmap(src) || content == null) return null; Bitmap ret = src.copy(src.getConfig(), true); Paint paint = new Paint(Paint.ANTI_ALIAS_FLAG); Canvas canvas = new Canvas(ret); paint.setColor(color); paint.setTextSize(textSize); Rect bounds = new Rect(); paint.getTextBounds(content, 0, content.length(), bounds); canvas.drawText(content, x, y + textSize, paint); if (recycle && !src.isRecycled()) src.recycle(); return ret; } /** * 添加图片水印 * * @param src 源图片 * @param watermark 图片水印 * @param x 起始坐标x * @param y 起始坐标y * @param alpha 透明度 * @return 带有图片水印的图片 */ public static Bitmap addImageWatermark(final Bitmap src, final Bitmap watermark, final int x, final int y, final int alpha) { return addImageWatermark(src, watermark, x, y, alpha, false); } /** * 添加图片水印 * * @param src 源图片 * @param watermark 图片水印 * @param x 起始坐标x * @param y 起始坐标y * @param alpha 透明度 * @param recycle 是否回收 * @return 带有图片水印的图片 */ public static Bitmap addImageWatermark(final Bitmap src, final Bitmap watermark, final int x, final int y, final int alpha, final boolean recycle) { if (isEmptyBitmap(src)) return null; Bitmap ret = src.copy(src.getConfig(), true); if (!isEmptyBitmap(watermark)) { Paint paint = new Paint(Paint.ANTI_ALIAS_FLAG); Canvas canvas = new Canvas(ret); paint.setAlpha(alpha); canvas.drawBitmap(watermark, x, y, paint); } if (recycle && !src.isRecycled()) src.recycle(); return ret; } /** * 转为alpha位图 * * @param src 源图片 * @return alpha位图 */ public static Bitmap toAlpha(final Bitmap src) { return toAlpha(src, false); } /** * 转为alpha位图 * * @param src 源图片 * @param recycle 是否回收 * @return alpha位图 */ public static Bitmap toAlpha(final Bitmap src, final Boolean recycle) { if (isEmptyBitmap(src)) return null; Bitmap ret = src.extractAlpha(); if (recycle && !src.isRecycled()) src.recycle(); return ret; } /** * 转为灰度图片 * * @param src 源图片 * @return 灰度图 */ public static Bitmap toGray(final Bitmap src) { return toGray(src, false); } /** * 转为灰度图片 * * @param src 源图片 * @param recycle 是否回收 * @return 灰度图 */ public static Bitmap toGray(final Bitmap src, final boolean recycle) { if (isEmptyBitmap(src)) return null; Bitmap ret = Bitmap.createBitmap(src.getWidth(), src.getHeight(), src.getConfig()); Canvas canvas = new Canvas(ret); Paint paint = new Paint(); ColorMatrix colorMatrix = new ColorMatrix(); colorMatrix.setSaturation(0); ColorMatrixColorFilter colorMatrixColorFilter = new ColorMatrixColorFilter(colorMatrix); paint.setColorFilter(colorMatrixColorFilter); canvas.drawBitmap(src, 0, 0, paint); if (recycle && !src.isRecycled()) src.recycle(); return ret; } /** * 快速模糊 *
先缩小原图,对小图进行模糊,再放大回原先尺寸
* * @param src 源图片 * @param scale 缩放比例(0...1) * @param radius 模糊半径 * @return 模糊后的图片 */ public static Bitmap fastBlur(final Bitmap src, @FloatRange(from = 0, to = 1, fromInclusive = false) final float scale, @FloatRange(from = 0, to = 25, fromInclusive = false) final float radius) { return fastBlur(src, scale, radius, false); } /** * 快速模糊图片 *先缩小原图,对小图进行模糊,再放大回原先尺寸
* * @param src 源图片 * @param scale 缩放比例(0...1) * @param radius 模糊半径(0...25) * @param recycle 是否回收 * @return 模糊后的图片 */ public static Bitmap fastBlur(final Bitmap src, @FloatRange(from = 0, to = 1, fromInclusive = false) final float scale, @FloatRange(from = 0, to = 25, fromInclusive = false) final float radius, final boolean recycle) { if (isEmptyBitmap(src)) return null; int width = src.getWidth(); int height = src.getHeight(); Matrix matrix = new Matrix(); matrix.setScale(scale, scale); Bitmap scaleBitmap = Bitmap.createBitmap(src, 0, 0, src.getWidth(), src.getHeight(), matrix, true); Paint paint = new Paint(Paint.FILTER_BITMAP_FLAG | Paint.ANTI_ALIAS_FLAG); Canvas canvas = new Canvas(); PorterDuffColorFilter filter = new PorterDuffColorFilter( Color.TRANSPARENT, PorterDuff.Mode.SRC_ATOP); paint.setColorFilter(filter); canvas.scale(scale, scale); canvas.drawBitmap(scaleBitmap, 0, 0, paint); if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR1) { scaleBitmap = renderScriptBlur(scaleBitmap, radius, recycle); } else { scaleBitmap = stackBlur(scaleBitmap, (int) radius, recycle); } if (scale == 1) return scaleBitmap; Bitmap ret = Bitmap.createScaledBitmap(scaleBitmap, width, height, true); if (scaleBitmap != null && !scaleBitmap.isRecycled()) scaleBitmap.recycle(); if (recycle && !src.isRecycled()) src.recycle(); return ret; } /** * renderScript模糊图片 *API大于17
* * @param src 源图片 * @param radius 模糊半径(0...25) * @return 模糊后的图片 */ @TargetApi(Build.VERSION_CODES.JELLY_BEAN_MR1) public static Bitmap renderScriptBlur(final Bitmap src, @FloatRange(from = 0, to = 25, fromInclusive = false) final float radius) { return renderScriptBlur(src, radius, false); } /** * renderScript模糊图片 *API大于17
* * @param src 源图片 * @param radius 模糊半径(0...25) * @param recycle 是否回收 * @return 模糊后的图片 */ @TargetApi(Build.VERSION_CODES.JELLY_BEAN_MR1) public static Bitmap renderScriptBlur(final Bitmap src, @FloatRange(from = 0, to = 25, fromInclusive = false) final float radius, final boolean recycle) { if (isEmptyBitmap(src)) return null; RenderScript rs = null; Bitmap ret = recycle ? src : src.copy(src.getConfig(), true); try { rs = RenderScript.create(FUtils.getAppContext()); rs.setMessageHandler(new RenderScript.RSMessageHandler()); Allocation input = Allocation.createFromBitmap(rs, ret, Allocation.MipmapControl.MIPMAP_NONE, Allocation .USAGE_SCRIPT); Allocation output = Allocation.createTyped(rs, input.getType()); ScriptIntrinsicBlur blurScript = ScriptIntrinsicBlur.create(rs, Element.U8_4(rs)); blurScript.setInput(input); blurScript.setRadius(radius); blurScript.forEach(output); output.copyTo(ret); } finally { if (rs != null) { rs.destroy(); } } return ret; } /** * stack模糊图片 * * @param src 源图片 * @param radius 模糊半径 * @return stack模糊后的图片 */ public static Bitmap stackBlur(final Bitmap src, final int radius) { return stackBlur(src, radius, false); } /** * stack模糊图片 * * @param src 源图片 * @param radius 模糊半径 * @param recycle 是否回收 * @return stack模糊后的图片 */ public static Bitmap stackBlur(final Bitmap src, final int radius, final boolean recycle) { Bitmap ret = recycle ? src : src.copy(src.getConfig(), true); if (radius < 1) { return null; } int w = ret.getWidth(); int h = ret.getHeight(); int[] pix = new int[w * h]; ret.getPixels(pix, 0, w, 0, 0, w, h); int wm = w - 1; int hm = h - 1; int wh = w * h; int div = radius + radius + 1; int r[] = new int[wh]; int g[] = new int[wh]; int b[] = new int[wh]; int rsum, gsum, bsum, x, y, i, p, yp, yi, yw; int vmin[] = new int[Math.max(w, h)]; int divsum = (div + 1) >> 1; divsum *= divsum; int dv[] = new int[256 * divsum]; for (i = 0; i < 256 * divsum; i++) { dv[i] = (i / divsum); } yw = yi = 0; int[][] stack = new int[div][3]; int stackpointer; int stackstart; int[] sir; int rbs; int r1 = radius + 1; int routsum, goutsum, boutsum; int rinsum, ginsum, binsum; for (y = 0; y < h; y++) { rinsum = ginsum = binsum = routsum = goutsum = boutsum = rsum = gsum = bsum = 0; for (i = -radius; i <= radius; i++) { p = pix[yi + Math.min(wm, Math.max(i, 0))]; sir = stack[i + radius]; sir[0] = (p & 0xff0000) >> 16; sir[1] = (p & 0x00ff00) >> 8; sir[2] = (p & 0x0000ff); rbs = r1 - Math.abs(i); rsum += sir[0] * rbs; gsum += sir[1] * rbs; bsum += sir[2] * rbs; if (i > 0) { rinsum += sir[0]; ginsum += sir[1]; binsum += sir[2]; } else { routsum += sir[0]; goutsum += sir[1]; boutsum += sir[2]; } } stackpointer = radius; for (x = 0; x < w; x++) { r[yi] = dv[rsum]; g[yi] = dv[gsum]; b[yi] = dv[bsum]; rsum -= routsum; gsum -= goutsum; bsum -= boutsum; stackstart = stackpointer - radius + div; sir = stack[stackstart % div]; routsum -= sir[0]; goutsum -= sir[1]; boutsum -= sir[2]; if (y == 0) { vmin[x] = Math.min(x + radius + 1, wm); } p = pix[yw + vmin[x]]; sir[0] = (p & 0xff0000) >> 16; sir[1] = (p & 0x00ff00) >> 8; sir[2] = (p & 0x0000ff); rinsum += sir[0]; ginsum += sir[1]; binsum += sir[2]; rsum += rinsum; gsum += ginsum; bsum += binsum; stackpointer = (stackpointer + 1) % div; sir = stack[(stackpointer) % div]; routsum += sir[0]; goutsum += sir[1]; boutsum += sir[2]; rinsum -= sir[0]; ginsum -= sir[1]; binsum -= sir[2]; yi++; } yw += w; } for (x = 0; x < w; x++) { rinsum = ginsum = binsum = routsum = goutsum = boutsum = rsum = gsum = bsum = 0; yp = -radius * w; for (i = -radius; i <= radius; i++) { yi = Math.max(0, yp) + x; sir = stack[i + radius]; sir[0] = r[yi]; sir[1] = g[yi]; sir[2] = b[yi]; rbs = r1 - Math.abs(i); rsum += r[yi] * rbs; gsum += g[yi] * rbs; bsum += b[yi] * rbs; if (i > 0) { rinsum += sir[0]; ginsum += sir[1]; binsum += sir[2]; } else { routsum += sir[0]; goutsum += sir[1]; boutsum += sir[2]; } if (i < hm) { yp += w; } } yi = x; stackpointer = radius; for (y = 0; y < h; y++) { // Preserve alpha channel: ( 0xff000000 & pix[yi] ) pix[yi] = (0xff000000 & pix[yi]) | (dv[rsum] << 16) | (dv[gsum] << 8) | dv[bsum]; rsum -= routsum; gsum -= goutsum; bsum -= boutsum; stackstart = stackpointer - radius + div; sir = stack[stackstart % div]; routsum -= sir[0]; goutsum -= sir[1]; boutsum -= sir[2]; if (x == 0) { vmin[y] = Math.min(y + r1, hm) * w; } p = x + vmin[y]; sir[0] = r[p]; sir[1] = g[p]; sir[2] = b[p]; rinsum += sir[0]; ginsum += sir[1]; binsum += sir[2]; rsum += rinsum; gsum += ginsum; bsum += binsum; stackpointer = (stackpointer + 1) % div; sir = stack[stackpointer]; routsum += sir[0]; goutsum += sir[1]; boutsum += sir[2]; rinsum -= sir[0]; ginsum -= sir[1]; binsum -= sir[2]; yi += w; } } ret.setPixels(pix, 0, w, 0, 0, w, h); return ret; } /** * 图片锐化(拉普拉斯变换) * * @param bmp * @return */ public static Bitmap sharpenImageAmeliorate(Bitmap bmp) { // 拉普拉斯矩阵 int[] laplacian = new int[]{-1, -1, -1, -1, 9, -1, -1, -1, -1}; int width = bmp.getWidth(); int height = bmp.getHeight(); Bitmap bitmap = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888); 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; } } bitmap.setPixels(pixels, 0, width, 0, 0, width, height); return bitmap; } /** * 图片二值化 * * @param bitmap * @return */ public static Bitmap binaryzation(Bitmap bitmap) { //得到图形的宽度和长度 int width = bitmap.getWidth(); int height = bitmap.getHeight(); //创建二值化图像 Bitmap binarymap = null; binarymap = bitmap.copy(Bitmap.Config.ARGB_8888, true); //依次循环,对图像的像素进行处理 for (int i = 0; i < width; i++) { for (int j = 0; j < height; j++) { int col = binarymap.getPixel(i, j); int alpha = col & 0xFF000000; //得到图像的像素RGB int red = (col & 0x00FF0000) >> 16; int green = (col & 0x0000FF00) >> 8; int blue = (col & 0x000000FF); // 用公式X = 0.3×R+0.59×G+0.11×B计算出X代替原来的RGB int gray = (int) ((float) red * 0.3 + (float) green * 0.59 + (float) blue * 0.11); //对图像进行二值化处理 if (gray <= 110) { gray = 0; } else { gray = 255; } // 新的ARGB int newColor = alpha | (gray << 16) | (gray << 8) | gray; //设置新图像的当前像素值 binarymap.setPixel(i, j, newColor); } } return binarymap; } /** * 保存图片 * * @param src 源图片 * @param filePath 要保存到的文件路径 * @param format 格式 * @return {@code true}: 成功