ImageUtils
JavaSE
package com.easystructure.utils.system; import java.awt.Color; import java.awt.Font; import java.awt.FontMetrics; import java.awt.Graphics; import java.awt.Graphics2D; import java.awt.Image; import java.awt.image.BufferedImage; import java.io.File; import java.io.FileInputStream; import java.io.FileNotFoundException; import java.io.FileOutputStream; import java.io.IOException; import java.io.InputStream; import javax.imageio.ImageIO; import com.sun.image.codec.jpeg.JPEGCodec; import com.sun.image.codec.jpeg.JPEGEncodeParam; import com.sun.image.codec.jpeg.JPEGImageEncoder; @SuppressWarnings("all") public class ImageUtils { /** * 把图片印刷到图片上 * * @param pressImg * -- 水印文件 * @param targetImg * -- 目标文件 * @param intAlign * --位置类型 */ public final static void pressImage(String pressImg, String targetImg, int intAlign) { try { // 目标文件 File _file = new File(targetImg); Image src = ImageIO.read(_file); int wideth = src.getWidth(null); int height = src.getHeight(null); BufferedImage image = new BufferedImage(wideth, height, BufferedImage.TYPE_INT_RGB); Graphics2D g = image.createGraphics(); g.drawImage(src, 0, 0, wideth, height, null); // 水印文件 File _filebiao = new File(pressImg); Image src_biao = ImageIO.read(_filebiao); int wideth_biao = src_biao.getWidth(null); int height_biao = src_biao.getHeight(null); if (intAlign == 1) { g.drawImage(src_biao, 5, 10, wideth_biao, height_biao, null); } else if (intAlign == 2) { g.drawImage(src_biao, (wideth - wideth_biao) / 2 - 5, 10, wideth_biao, height_biao, null); } else if (intAlign == 3) { g.drawImage(src_biao, wideth - wideth_biao - 5, 10, wideth_biao, height_biao, null); } else if (intAlign == 4) { g.drawImage(src_biao, 5, (height - height_biao) / 2 - 10, wideth_biao, height_biao, null); } else if (intAlign == 5) { g.drawImage(src_biao, (wideth - wideth_biao) / 2 - 5, (height - height_biao) / 2 - 10, wideth_biao, height_biao, null); } else if (intAlign == 6) { g.drawImage(src_biao, wideth - wideth_biao - 5, (height - height_biao) / 2 - 10, wideth_biao, height_biao, null); } else if (intAlign == 7) { g.drawImage(src_biao, 5, height - height_biao - 10, wideth_biao, height_biao, null); } else if (intAlign == 8) { g.drawImage(src_biao, (wideth - wideth_biao) / 2 - 5, height - height_biao - 10, wideth_biao, height_biao, null); } else if (intAlign == 9) { g.drawImage(src_biao, wideth - wideth_biao - 5, height - height_biao - 10, wideth_biao, height_biao, null); } // 水印文件结束 g.dispose(); FileOutputStream out = new FileOutputStream(targetImg); JPEGImageEncoder encoder = JPEGCodec.createJPEGEncoder(out); encoder.encode(image); out.close(); } catch (Exception e) { e.printStackTrace(); } } /** * * @param strImageText * @param fm * @return * @author googol Feb 9, 2006 */ public static int getStringWidth(String strImageText, FontMetrics fm) { int intReturn = 0; int intCount = strImageText.length(); char chrImageText[] = strImageText.toCharArray(); for (int i = 0; i < intCount; i++) { int charWidth = fm.charWidth(chrImageText[i]); intReturn += charWidth; } return intReturn += 10; } /** */ /** * 打印文字水印图片 * * @param pressText * --文字 * @param targetImg * -- 目标图片 * @param fontName * -- 字体名 * @param fontStyle * -- 字体样式 * @param color * -- 字体颜色 * @param fontSize * -- 字体大小 * @param intAlign * --位置类型 */ public static void pressText(String pressText, String targetImg, String fontName, int fontStyle, Color color, int fontSize, int intAlign) { try { File _file = new File(targetImg); Image src = ImageIO.read(_file); int wideth = src.getWidth(null); int height = src.getHeight(null); BufferedImage image = new BufferedImage(wideth, height, BufferedImage.TYPE_INT_RGB); Graphics2D g = image.createGraphics(); g.drawImage(src, 0, 0, wideth, height, null); g.setColor(color); g.setFont(new Font(fontName, fontStyle, fontSize)); int intWidth = getStringWidth(pressText, g.getFontMetrics()); if (wideth > intWidth) { if (intAlign == 1) { g.drawString(pressText, 5, 20); } else if (intAlign == 2) { g.drawString(pressText, (wideth - intWidth) / 2 - 5, 20); } else if (intAlign == 3) { g.drawString(pressText, wideth - intWidth - 5, 20); } else if (intAlign == 4) { g.drawString(pressText, 5, height / 2 - 10); } else if (intAlign == 5) { g.drawString(pressText, (wideth - intWidth) / 2 - 5, height / 2 - 10); } else if (intAlign == 6) { g.drawString(pressText, wideth - intWidth - 5, height / 2 - 10); } else if (intAlign == 7) { g.drawString(pressText, 5, height - 10); } else if (intAlign == 8) { g.drawString(pressText, (wideth - intWidth) / 2 - 5, height - 10); } else if (intAlign == 9) { g.drawString(pressText, wideth - intWidth - 5, height - 10); } } else { g.drawString(pressText, 0, height - 10); } g.dispose(); FileOutputStream out = new FileOutputStream(targetImg); JPEGImageEncoder encoder = JPEGCodec.createJPEGEncoder(out); encoder.encode(image); out.close(); } catch (Exception e) { System.out.println(e); } } /** * 只限制宽度生成缩略图,按比例缩放,如果原图宽度比需要生成的图的宽度还小,则简单拷贝一张图 * * @author Dennis * * 2009-11-17 下午04:41:55 */ public static void makeMiniature(String strPicturePath, String strOutPath, int intMinWidth) { File _file = new File(strPicturePath); Image src; try { src = ImageIO.read(_file); int width = src.getWidth(null); int height = src.getHeight(null); if (width <= intMinWidth) { // 直接copy makeMiniature(strPicturePath, strOutPath, width, height); } else { // 得到缩放比例 float scale = (float) intMinWidth / width; makeMiniature(strPicturePath, strOutPath, intMinWidth, (int) (height * scale - 1)); } } catch (IOException e) { System.out.println(e); } } /** * 产生一个缩略 * * @param strPicturePath * 原图片位置 * @param strOutPath * 生成图片的位置 2009-11-17 下午04:43:50 */ public static void makeMiniature(String strPicturePath, String strOutPath, int intMinWidth, int intMinHeight) { try { String imageFile = strPicturePath; File file = new File(imageFile); BufferedImage im = null; InputStream imageIn = new FileInputStream(file); im = ImageIO.read(imageIn); int minh = intMinHeight, minw = intMinWidth; BufferedImage imout = new BufferedImage(minw, minh, 1); Graphics g = imout.getGraphics(); g.drawImage(im, 0, 0, minw, minh, null); imageIn.close(); File out = new File(strOutPath); if (strOutPath.endsWith(".JPG") || strOutPath.endsWith(".jpg")) { ImageIO.write(imout, "jpg", out); } else if (strOutPath.endsWith(".GIF") || strOutPath.endsWith(".gif")) { ImageIO.write(imout, "gif", out); } } catch (Exception ex) { ex.printStackTrace(); } } /** * 压缩图片文件<br> * 先保存原文件,再压缩、上传 * * @param oldFile * 要进行压缩的文件全路径 * @param width * 宽度 * @param height * 高度 * @param quality * 质量 * @param smallIcon * 小图片的后缀 * @return 返回压缩后的文件的全路径 */ public static String zipImageFile(String oldFile, int width, int height, float quality, String smallIcon) { if (oldFile == null) return null; String newImage = null; try { /** 对服务器上的临时文件进行处理 */ Image srcFile = ImageIO.read(new File(oldFile)); double rate1 = ((double) srcFile.getWidth(null)) / (double) width + 0.1; double rate2 = ((double) srcFile.getHeight(null)) / (double) width + 0.1; double rate = rate1 > rate2 ? rate1 : rate2; width = (int) (((double) srcFile.getWidth(null)) / rate); width = (int) (((double) srcFile.getHeight(null)) / rate); /** 宽,高设定 */ BufferedImage tag = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB); tag.getGraphics().drawImage(srcFile, 0, 0, width, height, null); String filePrex = oldFile.substring(0, oldFile.indexOf('.')); /** 压缩后的文件名 */ newImage = filePrex + smallIcon + oldFile.substring(filePrex.length()); /** 压缩之后临时存放位置 */ FileOutputStream out = new FileOutputStream(newImage); JPEGImageEncoder encoder = JPEGCodec.createJPEGEncoder(out); JPEGEncodeParam jep = JPEGCodec.getDefaultJPEGEncodeParam(tag); /** 压缩质量 */ jep.setQuality(quality, true); encoder.encode(tag, jep); out.close(); } catch (FileNotFoundException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); } return newImage; } /** * 经过缩略图算法的压缩。存放生成图片的路径同源图片。 * * @param oldFile * @param width * @param height * @param smallIcon */ public static void zipImageFileSameOldPath(String oldFile, int intMinWidth, int intMinHeight, String smallIcon) { String strPicturePath = oldFile; String strOutPath = CommonUtils.addStrToFileName(strPicturePath, smallIcon); zipImageFileDifferPath(strPicturePath, strOutPath, intMinWidth, intMinHeight); } /** * 经过缩略图算法的压缩。存放生成图片的路径为指定路径。 * * @param oldFile * @param width * @param height * @param smallIcon */ public static void zipImageFileDifferPath(String oldFilePath, String newFilePath, int intMinWidth, int intMinHeight) { BufferedImage im = null; BufferedImage imout = null; int minh = intMinHeight; int minw = intMinWidth; try { File file = new File(oldFilePath); InputStream imageIn = new FileInputStream(file); im = ImageIO.read(imageIn); imout = new ImageScale().imageZoomOut(im, minw, minh); imageIn.close(); File out = new File(newFilePath); if (newFilePath.endsWith(".JPG") || newFilePath.endsWith(".jpg")) { ImageIO.write(imout, "jpg", out); } else if (newFilePath.endsWith(".GIF") || newFilePath.endsWith(".gif")) { ImageIO.write(imout, "gif", out); } } catch (Exception ex) { ex.printStackTrace(); } } public static void main(String[] args) { // pressImage("F:/bisonte.png", "F:/123.jpg", 9); pressText("Dennis", "F:/123.jpg", "宋体", Font.PLAIN, Color.RED, 15, 6); // createMark("F:/123.jpg", "mmmmnn", Color.RED, 15); } }
http://blog.csdn.net/googolplex/article/details/6724887
Android
bitmap2Bytes, bytes2Bitmap : bitmap与byteArr互转
drawable2Bitmap, bitmap2Drawable : drawable与bitmap互转
drawable2Bytes, bytes2Drawable : drawable与byteArr互转
getBitmap : 获取bitmap
scale : 缩放图片
clip : 裁剪图片
skew : 倾斜图片
rotate : 旋转图片
getRotateDegree : 获取图片旋转角度
toRound : 转为圆形图片
toRoundCorner : 转为圆角图片
fastBlur : 快速模糊
renderScriptBlur : renderScript模糊图片
stackBlur : stack模糊图片
addFrame : 添加颜色边框
addReflection : 添加倒影
addTextWatermark : 添加文字水印
addImageWatermark : 添加图片水印
toAlpha : 转为alpha位图
toGray : 转为灰度图片
save : 保存图片
isImage : 根据文件名判断文件是否为图片
getImageType : 获取图片类型
compressByScale : 按缩放压缩
compressByQuality : 按质量压缩
compressBySampleSize : 按采样大小压缩
import android.annotation.TargetApi; import android.content.Context; import android.content.res.Resources; import android.graphics.Bitmap; import android.graphics.Bitmap.CompressFormat; import android.graphics.BitmapFactory; import android.graphics.Canvas; import android.graphics.Color; import android.graphics.ColorMatrix; import android.graphics.ColorMatrixColorFilter; 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.drawable.BitmapDrawable; import android.graphics.drawable.Drawable; import android.graphics.drawable.NinePatchDrawable; 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.FloatRange; import android.support.annotation.IntRange; 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.FileInputStream; import java.io.FileNotFoundException; import java.io.FileOutputStream; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; /** * <pre> * author: Blankj * blog : http://blankj.com * time : 2016/8/12 * desc : 图片相关工具类 * </pre> */ public class ImageUtils { private ImageUtils() { throw new UnsupportedOperationException("u can't instantiate me..."); } /** * bitmap转byteArr * * @param bitmap bitmap对象 * @param format 格式 * @return 字节数组 */ public static byte[] bitmap2Bytes(Bitmap bitmap, CompressFormat format) { if (bitmap == null) return null; ByteArrayOutputStream baos = new ByteArrayOutputStream(); bitmap.compress(format, 100, baos); return baos.toByteArray(); } /** * byteArr转bitmap * * @param bytes 字节数组 * @return bitmap */ public static Bitmap bytes2Bitmap(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(Drawable drawable) { if (drawable instanceof BitmapDrawable) { return ((BitmapDrawable) drawable).getBitmap(); } else if (drawable instanceof NinePatchDrawable) { Bitmap 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, drawable.getIntrinsicWidth(), drawable.getIntrinsicHeight()); drawable.draw(canvas); return bitmap; } else { return null; } } /** * bitmap转drawable * * @param res resources对象 * @param bitmap bitmap对象 * @return drawable */ public static Drawable bitmap2Drawable(Resources res, Bitmap bitmap) { return bitmap == null ? null : new BitmapDrawable(res, bitmap); } /** * drawable转byteArr * * @param drawable drawable对象 * @param format 格式 * @return 字节数组 */ public static byte[] drawable2Bytes(Drawable drawable, CompressFormat format) { return drawable == null ? null : bitmap2Bytes(drawable2Bitmap(drawable), format); } /** * byteArr转drawable * * @param res resources对象 * @param bytes 字节数组 * @return drawable */ public static Drawable bytes2Drawable(Resources res, byte[] bytes) { return res == null ? null : bitmap2Drawable(res, bytes2Bitmap(bytes)); } /** * view转Bitmap * * @param view 视图 * @return bitmap */ public static Bitmap view2Bitmap(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; } /** * 计算采样大小 * * @param options 选项 * @param maxWidth 最大宽度 * @param maxHeight 最大高度 * @return 采样大小 */ private static int calculateInSampleSize(BitmapFactory.Options options, int maxWidth, int maxHeight) { if (maxWidth == 0 || maxHeight == 0) return 1; int height = options.outHeight; int width = options.outWidth; int inSampleSize = 1; while ((height >>= 1) >= maxHeight && (width >>= 1) >= maxWidth) { inSampleSize <<= 1; } return inSampleSize; } /** * 获取bitmap * * @param file 文件 * @return bitmap */ public static Bitmap getBitmap(File file) { if (file == null) return null; InputStream is = null; try { is = new BufferedInputStream(new FileInputStream(file)); return BitmapFactory.decodeStream(is); } catch (FileNotFoundException e) { e.printStackTrace(); return null; } finally { CloseUtils.closeIO(is); } } /** * 获取bitmap * * @param file 文件 * @param maxWidth 最大宽度 * @param maxHeight 最大高度 * @return bitmap */ public static Bitmap getBitmap(File file, int maxWidth, int maxHeight) { if (file == null) return null; InputStream is = null; try { BitmapFactory.Options options = new BitmapFactory.Options(); options.inJustDecodeBounds = true; is = new BufferedInputStream(new FileInputStream(file)); BitmapFactory.decodeStream(is, null, options); options.inSampleSize = calculateInSampleSize(options, maxWidth, maxHeight); options.inJustDecodeBounds = false; return BitmapFactory.decodeStream(is, null, options); } catch (FileNotFoundException e) { e.printStackTrace(); return null; } finally { CloseUtils.closeIO(is); } } /** * 获取bitmap * * @param filePath 文件路径 * @return bitmap */ public static Bitmap getBitmap(String filePath) { if (StringUtils.isSpace(filePath)) return null; return BitmapFactory.decodeFile(filePath); } /** * 获取bitmap * * @param filePath 文件路径 * @param maxWidth 最大宽度 * @param maxHeight 最大高度 * @return bitmap */ public static Bitmap getBitmap(String filePath, int maxWidth, int maxHeight) { if (StringUtils.isSpace(filePath)) return null; BitmapFactory.Options options = new BitmapFactory.Options(); options.inJustDecodeBounds = true; BitmapFactory.decodeFile(filePath, options); options.inSampleSize = calculateInSampleSize(options, maxWidth, maxHeight); options.inJustDecodeBounds = false; return BitmapFactory.decodeFile(filePath, options); } /** * 获取bitmap * * @param is 输入流 * @return bitmap */ public static Bitmap getBitmap(InputStream is) { if (is == null) return null; return BitmapFactory.decodeStream(is); } /** * 获取bitmap * * @param is 输入流 * @param maxWidth 最大宽度 * @param maxHeight 最大高度 * @return bitmap */ public static Bitmap getBitmap(InputStream is, int maxWidth, int maxHeight) { if (is == null) return null; BitmapFactory.Options options = new BitmapFactory.Options(); options.inJustDecodeBounds = true; BitmapFactory.decodeStream(is, null, options); options.inSampleSize = calculateInSampleSize(options, maxWidth, maxHeight); options.inJustDecodeBounds = false; return BitmapFactory.decodeStream(is, null, options); } /** * 获取bitmap * * @param data 数据 * @param offset 偏移量 * @return bitmap */ public static Bitmap getBitmap(byte[] data, int offset) { if (data.length == 0) return null; return BitmapFactory.decodeByteArray(data, offset, data.length); } /** * 获取bitmap * * @param data 数据 * @param offset 偏移量 * @param maxWidth 最大宽度 * @param maxHeight 最大高度 * @return bitmap */ public static Bitmap getBitmap(byte[] data, int offset, int maxWidth, int maxHeight) { if (data.length == 0) return null; BitmapFactory.Options options = new BitmapFactory.Options(); options.inJustDecodeBounds = true; BitmapFactory.decodeByteArray(data, offset, data.length, options); options.inSampleSize = calculateInSampleSize(options, maxWidth, maxHeight); options.inJustDecodeBounds = false; return BitmapFactory.decodeByteArray(data, offset, data.length, options); } /** * 获取bitmap * * @param res 资源对象 * @param id 资源id * @return bitmap */ public static Bitmap getBitmap(Resources res, int id) { if (res == null) return null; return BitmapFactory.decodeResource(res, id); } /** * 获取bitmap * * @param res 资源对象 * @param id 资源id * @param maxWidth 最大宽度 * @param maxHeight 最大高度 * @return bitmap */ public static Bitmap getBitmap(Resources res, int id, int maxWidth, int maxHeight) { if (res == null) return null; BitmapFactory.Options options = new BitmapFactory.Options(); options.inJustDecodeBounds = true; BitmapFactory.decodeResource(res, id, options); options.inSampleSize = calculateInSampleSize(options, maxWidth, maxHeight); options.inJustDecodeBounds = false; return BitmapFactory.decodeResource(res, id, options); } /** * 获取bitmap * * @param fd 文件描述 * @return bitmap */ public static Bitmap getBitmap(FileDescriptor fd) { if (fd == null) return null; return BitmapFactory.decodeFileDescriptor(fd); } /** * 获取bitmap * * @param fd 文件描述 * @param maxWidth 最大宽度 * @param maxHeight 最大高度 * @return bitmap */ public static Bitmap getBitmap(FileDescriptor fd, int maxWidth, int maxHeight) { if (fd == null) return null; BitmapFactory.Options options = new BitmapFactory.Options(); options.inJustDecodeBounds = true; BitmapFactory.decodeFileDescriptor(fd, null, options); options.inSampleSize = calculateInSampleSize(options, maxWidth, maxHeight); options.inJustDecodeBounds = false; return BitmapFactory.decodeFileDescriptor(fd, null, options); } /** * 缩放图片 * * @param src 源图片 * @param newWidth 新宽度 * @param newHeight 新高度 * @return 缩放后的图片 */ public static Bitmap scale(Bitmap src, int newWidth, int newHeight) { return scale(src, newWidth, newHeight, false); } /** * 缩放图片 * * @param src 源图片 * @param newWidth 新宽度 * @param newHeight 新高度 * @param recycle 是否回收 * @return 缩放后的图片 */ public static Bitmap scale(Bitmap src, int newWidth, int newHeight, 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(Bitmap src, float scaleWidth, float scaleHeight) { return scale(src, scaleWidth, scaleHeight, false); } /** * 缩放图片 * * @param src 源图片 * @param scaleWidth 缩放宽度倍数 * @param scaleHeight 缩放高度倍数 * @param recycle 是否回收 * @return 缩放后的图片 */ public static Bitmap scale(Bitmap src, float scaleWidth, float scaleHeight, 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(Bitmap src, int x, int y, int width, 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(Bitmap src, int x, int y, int width, int height, 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(Bitmap src, float kx, 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(Bitmap src, float kx, float ky, 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(Bitmap src, float kx, float ky, float px, 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(Bitmap src, float kx, float ky, float px, float py, 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(Bitmap src, int degrees, float px, float py) { return rotate(src, degrees, px, py, false); } /** * 旋转图片 * * @param src 源图片 * @param degrees 旋转角度 * @param px 旋转点横坐标 * @param py 旋转点纵坐标 * @param recycle 是否回收 * @return 旋转后的图片 */ public static Bitmap rotate(Bitmap src, int degrees, float px, float py, 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(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(Bitmap src) { return toRound(src, false); } /** * 转为圆形图片 * * @param src 源图片 * @param recycle 是否回收 * @return 圆形图片 */ public static Bitmap toRound(Bitmap src, boolean recycle) { if (isEmptyBitmap(src)) return null; int width = src.getWidth(); int height = src.getHeight(); int radius = Math.min(width, height) >> 1; Bitmap ret = Bitmap.createBitmap(width, height, src.getConfig()); Paint paint = new Paint(); Canvas canvas = new Canvas(ret); Rect rect = new Rect(0, 0, width, height); paint.setAntiAlias(true); canvas.drawARGB(0, 0, 0, 0); canvas.drawCircle(width >> 1, height >> 1, radius, paint); paint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.SRC_IN)); canvas.drawBitmap(src, rect, rect, paint); if (recycle && !src.isRecycled()) src.recycle(); return ret; } /** * 转为圆角图片 * * @param src 源图片 * @param radius 圆角的度数 * @return 圆角图片 */ public static Bitmap toRoundCorner(Bitmap src, float radius) { return toRoundCorner(src, radius, false); } /** * 转为圆角图片 * * @param src 源图片 * @param radius 圆角的度数 * @param recycle 是否回收 * @return 圆角图片 */ public static Bitmap toRoundCorner(Bitmap src, float radius, boolean recycle) { if (null == src) return null; int width = src.getWidth(); int height = src.getHeight(); Bitmap ret = Bitmap.createBitmap(width, height, src.getConfig()); Paint paint = new Paint(); Canvas canvas = new Canvas(ret); Rect rect = new Rect(0, 0, width, height); paint.setAntiAlias(true); canvas.drawRoundRect(new RectF(rect), radius, radius, paint); paint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.SRC_IN)); canvas.drawBitmap(src, rect, rect, paint); if (recycle && !src.isRecycled()) src.recycle(); return ret; } /** * 快速模糊 * <p>先缩小原图,对小图进行模糊,再放大回原先尺寸</p> * * @param src 源图片 * @param scale 缩放比例(0...1) * @param radius 模糊半径 * @return 模糊后的图片 */ public static Bitmap fastBlur(Bitmap src, @FloatRange(from = 0, to = 1, fromInclusive = false) float scale, @FloatRange(from = 0, to = 25, fromInclusive = false) float radius) { return fastBlur(src, scale, radius, false); } /** * 快速模糊图片 * <p>先缩小原图,对小图进行模糊,再放大回原先尺寸</p> * * @param src 源图片 * @param scale 缩放比例(0...1) * @param radius 模糊半径(0...25) * @param recycle 是否回收 * @return 模糊后的图片 */ public static Bitmap fastBlur(Bitmap src, @FloatRange(from = 0, to = 1, fromInclusive = false) float scale, @FloatRange(from = 0, to = 25, fromInclusive = false) float radius, boolean recycle) { if (isEmptyBitmap(src)) return null; int width = src.getWidth(); int height = src.getHeight(); int scaleWidth = (int) (width * scale + 0.5f); int scaleHeight = (int) (height * scale + 0.5f); if (scaleWidth == 0 || scaleHeight == 0) return null; Bitmap scaleBitmap = Bitmap.createScaledBitmap(src, scaleWidth, scaleHeight, 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(Utils.getContext(), scaleBitmap, radius); } 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模糊图片 * <p>API大于17</p> * * @param context 上下文 * @param src 源图片 * @param radius 模糊半径(0...25) * @return 模糊后的图片 */ @TargetApi(Build.VERSION_CODES.JELLY_BEAN_MR1) public static Bitmap renderScriptBlur(Context context, Bitmap src, @FloatRange(from = 0, to = 25, fromInclusive = false) float radius) { if (isEmptyBitmap(src)) return null; RenderScript rs = null; try { rs = RenderScript.create(context); rs.setMessageHandler(new RenderScript.RSMessageHandler()); Allocation input = Allocation.createFromBitmap(rs, src, 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(src); } finally { if (rs != null) { rs.destroy(); } } return src; } /** * stack模糊图片 * * @param src 源图片 * @param radius 模糊半径 * @param recycle 是否回收 * @return stack模糊后的图片 */ public static Bitmap stackBlur(Bitmap src, int radius, boolean recycle) { Bitmap ret; if (recycle) { ret = src; } else { ret = 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 src 源图片 * @param borderWidth 边框宽度 * @param color 边框的颜色值 * @return 带颜色边框图 */ public static Bitmap addFrame(Bitmap src, int borderWidth, int color) { return addFrame(src, borderWidth, color, false); } /** * 添加颜色边框 * * @param src 源图片 * @param borderWidth 边框宽度 * @param color 边框的颜色值 * @param recycle 是否回收 * @return 带颜色边框图 */ public static Bitmap addFrame(Bitmap src, int borderWidth, int color, boolean recycle) { if (isEmptyBitmap(src)) return null; int doubleBorder = borderWidth << 1; int newWidth = src.getWidth() + doubleBorder; int newHeight = src.getHeight() + doubleBorder; Bitmap ret = Bitmap.createBitmap(newWidth, newHeight, src.getConfig()); Canvas canvas = new Canvas(ret); Rect rect = new Rect(0, 0, newWidth, newHeight); Paint paint = new Paint(); paint.setColor(color); paint.setStyle(Paint.Style.STROKE); // setStrokeWidth是居中画的,所以要两倍的宽度才能画,否则有一半的宽度是空的 paint.setStrokeWidth(doubleBorder); canvas.drawRect(rect, paint); canvas.drawBitmap(src, borderWidth, borderWidth, null); if (recycle && !src.isRecycled()) src.recycle(); return ret; } /** * 添加倒影 * * @param src 源图片的 * @param reflectionHeight 倒影高度 * @return 带倒影图片 */ public static Bitmap addReflection(Bitmap src, int reflectionHeight) { return addReflection(src, reflectionHeight, false); } /** * 添加倒影 * * @param src 源图片的 * @param reflectionHeight 倒影高度 * @param recycle 是否回收 * @return 带倒影图片 */ public static Bitmap addReflection(Bitmap src, int reflectionHeight, 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.setAntiAlias(true); 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(Bitmap src, String content, int textSize, int color, float x, 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(Bitmap src, String content, float textSize, int color, float x, float y, 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(Bitmap src, Bitmap watermark, int x, int y, 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(Bitmap src, Bitmap watermark, int x, int y, int alpha, 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(Bitmap src) { return toAlpha(src, false); } /** * 转为alpha位图 * * @param src 源图片 * @param recycle 是否回收 * @return alpha位图 */ public static Bitmap toAlpha(Bitmap src, 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(Bitmap src) { return toGray(src, false); } /** * 转为灰度图片 * * @param src 源图片 * @param recycle 是否回收 * @return 灰度图 */ public static Bitmap toGray(Bitmap src, boolean recycle) { if (isEmptyBitmap(src)) return null; Bitmap grayBitmap = Bitmap.createBitmap(src.getWidth(), src.getHeight(), Bitmap.Config.ARGB_8888); Canvas canvas = new Canvas(grayBitmap); 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 grayBitmap; } /** * 保存图片 * * @param src 源图片 * @param filePath 要保存到的文件路径 * @param format 格式 * @return {@code true}: 成功<br>{@code false}: 失败 */ public static boolean save(Bitmap src, String filePath, CompressFormat format) { return save(src, FileUtils.getFileByPath(filePath), format, false); } /** * 保存图片 * * @param src 源图片 * @param file 要保存到的文件 * @param format 格式 * @return {@code true}: 成功<br>{@code false}: 失败 */ public static boolean save(Bitmap src, File file, CompressFormat format) { return save(src, file, format, false); } /** * 保存图片 * * @param src 源图片 * @param filePath 要保存到的文件路径 * @param format 格式 * @param recycle 是否回收 * @return {@code true}: 成功<br>{@code false}: 失败 */ public static boolean save(Bitmap src, String filePath, CompressFormat format, boolean recycle) { return save(src, FileUtils.getFileByPath(filePath), format, recycle); } /** * 保存图片 * * @param src 源图片 * @param file 要保存到的文件 * @param format 格式 * @param recycle 是否回收 * @return {@code true}: 成功<br>{@code false}: 失败 */ public static boolean save(Bitmap src, File file, CompressFormat format, boolean recycle) { if (isEmptyBitmap(src) || !FileUtils.createOrExistsFile(file)) return false; System.out.println(src.getWidth() + ", " + src.getHeight()); OutputStream os = null; boolean ret = false; try { os = new BufferedOutputStream(new FileOutputStream(file)); ret = src.compress(format, 100, os); if (recycle && !src.isRecycled()) src.recycle(); } catch (IOException e) { e.printStackTrace(); } finally { CloseUtils.closeIO(os); } return ret; } /** * 根据文件名判断文件是否为图片 * * @param file 文件 * @return {@code true}: 是<br>{@code false}: 否 */ public static boolean isImage(File file) { return file != null && isImage(file.getPath()); } /** * 根据文件名判断文件是否为图片 * * @param filePath 文件路径 * @return {@code true}: 是<br>{@code false}: 否 */ public static boolean isImage(String filePath) { String path = filePath.toUpperCase(); return path.endsWith(".PNG") || path.endsWith(".JPG") || path.endsWith(".JPEG") || path.endsWith(".BMP") || path.endsWith(".GIF"); } /** * 获取图片类型 * * @param filePath 文件路径 * @return 图片类型 */ public static String getImageType(String filePath) { return getImageType(FileUtils.getFileByPath(filePath)); } /** * 获取图片类型 * * @param file 文件 * @return 图片类型 */ public static String getImageType(File file) { if (file == null) return null; InputStream is = null; try { is = new FileInputStream(file); return getImageType(is); } catch (IOException e) { e.printStackTrace(); return null; } finally { CloseUtils.closeIO(is); } } /** * 流获取图片类型 * * @param is 图片输入流 * @return 图片类型 */ public static String getImageType(InputStream is) { if (is == null) return null; try { byte[] bytes = new byte[8]; return is.read(bytes, 0, 8) != -1 ? getImageType(bytes) : null; } catch (IOException e) { e.printStackTrace(); return null; } } /** * 获取图片类型 * * @param bytes bitmap的前8字节 * @return 图片类型 */ public static String getImageType(byte[] bytes) { if (isJPEG(bytes)) return "JPEG"; if (isGIF(bytes)) return "GIF"; if (isPNG(bytes)) return "PNG"; if (isBMP(bytes)) return "BMP"; return null; } private static boolean isJPEG(byte[] b) { return b.length >= 2 && (b[0] == (byte) 0xFF) && (b[1] == (byte) 0xD8); } private static boolean isGIF(byte[] b) { return b.length >= 6 && b[0] == 'G' && b[1] == 'I' && b[2] == 'F' && b[3] == '8' && (b[4] == '7' || b[4] == '9') && b[5] == 'a'; } private static boolean isPNG(byte[] b) { return b.length >= 8 && (b[0] == (byte) 137 && b[1] == (byte) 80 && b[2] == (byte) 78 && b[3] == (byte) 71 && b[4] == (byte) 13 && b[5] == (byte) 10 && b[6] == (byte) 26 && b[7] == (byte) 10); } private static boolean isBMP(byte[] b) { return b.length >= 2 && (b[0] == 0x42) && (b[1] == 0x4d); } /** * 判断bitmap对象是否为空 * * @param src 源图片 * @return {@code true}: 是<br>{@code false}: 否 */ private static boolean isEmptyBitmap(Bitmap src) { return src == null || src.getWidth() == 0 || src.getHeight() == 0; } /******************************~~~~~~~~~ 下方和压缩有关 ~~~~~~~~~******************************/ /** * 按缩放压缩 * * @param src 源图片 * @param newWidth 新宽度 * @param newHeight 新高度 * @return 缩放压缩后的图片 */ public static Bitmap compressByScale(Bitmap src, int newWidth, int newHeight) { return scale(src, newWidth, newHeight, false); } /** * 按缩放压缩 * * @param src 源图片 * @param newWidth 新宽度 * @param newHeight 新高度 * @param recycle 是否回收 * @return 缩放压缩后的图片 */ public static Bitmap compressByScale(Bitmap src, int newWidth, int newHeight, boolean recycle) { return scale(src, newWidth, newHeight, recycle); } /** * 按缩放压缩 * * @param src 源图片 * @param scaleWidth 缩放宽度倍数 * @param scaleHeight 缩放高度倍数 * @return 缩放压缩后的图片 */ public static Bitmap compressByScale(Bitmap src, float scaleWidth, float scaleHeight) { return scale(src, scaleWidth, scaleHeight, false); } /** * 按缩放压缩 * * @param src 源图片 * @param scaleWidth 缩放宽度倍数 * @param scaleHeight 缩放高度倍数 * @param recycle 是否回收 * @return 缩放压缩后的图片 */ public static Bitmap compressByScale(Bitmap src, float scaleWidth, float scaleHeight, boolean recycle) { return scale(src, scaleWidth, scaleHeight, recycle); } /** * 按质量压缩 * * @param src 源图片 * @param quality 质量 * @return 质量压缩后的图片 */ public static Bitmap compressByQuality(Bitmap src, @IntRange(from = 0, to = 100) int quality) { return compressByQuality(src, quality, false); } /** * 按质量压缩 * * @param src 源图片 * @param quality 质量 * @param recycle 是否回收 * @return 质量压缩后的图片 */ public static Bitmap compressByQuality(Bitmap src, @IntRange(from = 0, to = 100) int quality, boolean recycle) { if (isEmptyBitmap(src)) return null; ByteArrayOutputStream baos = new ByteArrayOutputStream(); src.compress(Bitmap.CompressFormat.JPEG, quality, baos); byte[] bytes = baos.toByteArray(); if (recycle && !src.isRecycled()) src.recycle(); return BitmapFactory.decodeByteArray(bytes, 0, bytes.length); } /** * 按质量压缩 * * @param src 源图片 * @param maxByteSize 允许最大值字节数 * @return 质量压缩压缩过的图片 */ public static Bitmap compressByQuality(Bitmap src, long maxByteSize) { return compressByQuality(src, maxByteSize, false); } /** * 按质量压缩 * * @param src 源图片 * @param maxByteSize 允许最大值字节数 * @param recycle 是否回收 * @return 质量压缩压缩过的图片 */ public static Bitmap compressByQuality(Bitmap src, long maxByteSize, boolean recycle) { if (isEmptyBitmap(src) || maxByteSize <= 0) return null; ByteArrayOutputStream baos = new ByteArrayOutputStream(); int quality = 100; src.compress(CompressFormat.JPEG, quality, baos); while (baos.toByteArray().length > maxByteSize && quality > 0) { baos.reset(); src.compress(CompressFormat.JPEG, quality -= 5, baos); } if (quality < 0) return null; byte[] bytes = baos.toByteArray(); if (recycle && !src.isRecycled()) src.recycle(); return BitmapFactory.decodeByteArray(bytes, 0, bytes.length); } /** * 按采样大小压缩 * * @param src 源图片 * @param sampleSize 采样率大小 * @return 按采样率压缩后的图片 */ public static Bitmap compressBySampleSize(Bitmap src, int sampleSize) { return compressBySampleSize(src, sampleSize, false); } /** * 按采样大小压缩 * * @param src 源图片 * @param sampleSize 采样率大小 * @param recycle 是否回收 * @return 按采样率压缩后的图片 */ public static Bitmap compressBySampleSize(Bitmap src, int sampleSize, boolean recycle) { if (isEmptyBitmap(src)) return null; BitmapFactory.Options options = new BitmapFactory.Options(); options.inSampleSize = sampleSize; ByteArrayOutputStream baos = new ByteArrayOutputStream(); src.compress(Bitmap.CompressFormat.JPEG, 100, baos); byte[] bytes = baos.toByteArray(); if (recycle && !src.isRecycled()) src.recycle(); return BitmapFactory.decodeByteArray(bytes, 0, bytes.length, options); } }
http://www.jianshu.com/p/72494773aace
QRcode
package com.summer.common.utils.img; import java.awt.AlphaComposite; import java.awt.BasicStroke; import java.awt.Color; import java.awt.Graphics2D; import java.awt.RenderingHints; import java.awt.Transparency; import java.awt.geom.Ellipse2D; import java.awt.geom.RoundRectangle2D; import java.awt.image.BufferedImage; import java.io.ByteArrayInputStream; import java.io.ByteArrayOutputStream; import java.io.File; import java.io.IOException; import java.nio.file.Paths; import java.util.HashMap; import java.util.Hashtable; import java.util.Map; import javax.imageio.ImageIO; import com.google.zxing.BarcodeFormat; import com.google.zxing.BinaryBitmap; import com.google.zxing.EncodeHintType; import com.google.zxing.MultiFormatWriter; import com.google.zxing.WriterException; import com.google.zxing.client.j2se.MatrixToImageConfig; import com.google.zxing.client.j2se.MatrixToImageWriter; import com.google.zxing.common.BitMatrix; import com.google.zxing.qrcode.decoder.ErrorCorrectionLevel; public class QRUtils { public static void main(String[] args) throws IOException, WriterException { String format = "jpg"; int QRCODE_SIZE = 1000; MatrixToImageWriter.toBufferedImage(encodePDF17("haha", QRCODE_SIZE)); // writeQR("haha", 102, "C:\\haha.jpg", format); // BufferedImage ImageOne = getQRImage("houpin.1688.com", QRCODE_SIZE); MatrixToImageWriter.writeToPath(encodePDF17("haha", QRCODE_SIZE), format, Paths.get("C:\\haha.jpg")); //对第二张图片做相同的处理 // File fileTwo = new File("c:\\1.jpg"); // BufferedImage ImageTwo = ImageIO.read(fileTwo); // BufferedImage ImageNew = createQRImageWithCirclePortrait(ImageOne, ImageTwo); // ImageIO.write(ImageNew, format, new File("c://123-A.jpg")); // ImageIO.write( createQRImageWithSquarePortrait(ImageOne, ImageTwo), format, new File("c://123-B.jpg")); // ImageIO.write( createQRCodeBitmapWithRoundRectanglePortrait(ImageOne, ImageTwo), format, new File("c://123-C.jpg")); } // 计算边框比例 private static final int BORDER_LEMON = 30; /** * 如果小于1像素,返回1px * @param size * @return */ private static int calBorderPix(int size) { int border = size /BORDER_LEMON; return border > 1 ? border : 1; } /** * 把source拷贝到RGB BufferedImage * @param source * @return */ private static BufferedImage copyToRGBImage(BufferedImage source) { int width = source.getWidth(), height = source.getWidth(); BufferedImage imageNew = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB); // 从QR中读取RGB int[] qrImageArray = new int[width * height]; qrImageArray = source.getRGB(0,0,width,height,qrImageArray,0,width); // QR写入 imageNew.setRGB(0, 0, width, height, qrImageArray, 0, width); return imageNew; } /** * 为QR码添加头像,方形,带白相框 * @param qr * @param portrait 头像 * @return */ public static BufferedImage createQRImageWithSquarePortrait(BufferedImage qr, BufferedImage portrait) { BufferedImage imageNew = copyToRGBImage(qr); // portrait int portraitWidth = portrait.getWidth(), portraitHeight = portrait.getHeight(); // 框偏移 int wBorder = calBorderPix(portraitWidth), hBorder = calBorderPix(portraitHeight); // 位置计算 int left = (imageNew.getWidth()-portraitWidth) / 2, top = (imageNew.getHeight()-portraitHeight) / 2; // 先绘制白色背景 // = for (int x=0; x<portraitWidth; x++) { for (int y=0; y<hBorder; y++) { imageNew.setRGB(left+x, top+y, Color.white.getRGB()); imageNew.setRGB(left+x, top+y+portraitHeight - hBorder, Color.white.getRGB()); } } //|| for (int x=0; x<wBorder; x++) { for (int y=0; y<portraitHeight - hBorder; y++) { imageNew.setRGB(left+x, top+y+hBorder, Color.white.getRGB()); imageNew.setRGB(left+x+portraitWidth-wBorder, top+y+hBorder, Color.white.getRGB()); } } // 贴上头像 addPortraitImg(imageNew, portrait, left + wBorder, top + hBorder, wBorder,hBorder,portraitWidth-2*wBorder,portraitHeight-2*hBorder); return imageNew; } private static void addPortraitImg(BufferedImage setImg,BufferedImage getImg, int sX, int sY, int gX, int gY, int gW, int gH ) { int[] portraitArray = new int[gW * gH]; portraitArray = getImg.getRGB(gX, gY, gW, gH,portraitArray,0, gW); setImg.setRGB(sX, sY, gW, gH, portraitArray, 0, gW); } /** * 产生一个平滑,抗锯齿的Graphics2D * @param img * @return */ private static Graphics2D createGraphics(BufferedImage img) { Graphics2D g2d = img.createGraphics(); g2d.setStroke(new BasicStroke(1)); // 使用 setRenderingHint 设置抗锯齿 g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING,RenderingHints.VALUE_ANTIALIAS_ON); return g2d; } /** * 为QR码添加头像,圆形,带白相框 * @param qr * @param portrait * @return * @throws IOException */ public static BufferedImage createQRImageWithCirclePortrait(BufferedImage qr, BufferedImage portrait) throws IOException { BufferedImage imageNew = copyToRGBImage(qr); // portrait int portraitWidth = portrait.getWidth(), portraitHeight = portrait.getHeight(); // 框偏移 int wBorder = portraitWidth/ 30, hBorder = portraitHeight/ 30; // 位置计算 int left = (imageNew.getWidth() - portraitWidth) / 2, top = (imageNew.getHeight() - portraitHeight) / 2; { // 先绘制白色背景 BufferedImage circleBorder = new BufferedImage(portraitWidth + 2*wBorder, portraitWidth + 2*hBorder, BufferedImage.TYPE_INT_RGB); addPortraitImg(circleBorder, qr, 0, 0, left-wBorder,top-hBorder, portraitWidth+2*wBorder,portraitHeight+2*hBorder); Graphics2D g2d = createGraphics(circleBorder); g2d.setColor(Color.white); g2d.fill( new Ellipse2D.Double(0,0,portraitWidth+ 2*wBorder,portraitHeight+ 2*hBorder)); g2d.dispose(); addPortraitImg(imageNew, circleBorder, left-wBorder,top-hBorder, 0,0,portraitWidth+ 2*wBorder,portraitHeight+ 2*hBorder); } { // 在画 BufferedImage circleImage = new BufferedImage(portraitWidth, portraitWidth, BufferedImage.TYPE_INT_RGB); addPortraitImg(circleImage, imageNew, 0, 0, left,top,portraitWidth,portraitHeight); Graphics2D g2d = createGraphics(circleImage); g2d.setClip(new Ellipse2D.Double(0,0,portraitWidth,portraitHeight)); g2d.drawImage(portrait, 0, 0, null); g2d.dispose(); addPortraitImg(imageNew, circleImage, left, top, 0,0,portraitWidth,portraitHeight); } return imageNew; } /** * 为QR码添加头像,圆角,带白相框 * @param qr * @param portrait * @return * @throws IOException */ public static BufferedImage createQRCodeBitmapWithRoundRectanglePortrait(BufferedImage qr, BufferedImage portrait) throws IOException { BufferedImage imageNew = copyToRGBImage(qr); // portrait int portraitWidth = portrait.getWidth(), portraitHeight = portrait.getHeight(); // 框偏移 int wBorder = portraitWidth/ 30, hBorder = portraitHeight/ 30; // 位置计算 int left = (imageNew.getWidth() - portraitWidth) / 2, top = (imageNew.getHeight() - portraitHeight) / 2; { // 先绘制白色背景 BufferedImage circleBorder = new BufferedImage(portraitWidth + 2*wBorder, portraitWidth + 2*hBorder, BufferedImage.TYPE_INT_RGB); addPortraitImg(circleBorder, qr, 0, 0, left-wBorder,top-hBorder, portraitWidth+2*wBorder,portraitHeight+2*hBorder); Graphics2D g2d = createGraphics(circleBorder); g2d.setColor(Color.white); g2d.fill( new RoundRectangle2D.Double(0,0,portraitWidth+ 2*wBorder,portraitHeight+ 2*hBorder, wBorder *8 , hBorder *8)); g2d.dispose(); addPortraitImg(imageNew, circleBorder, left-wBorder,top-hBorder, 0,0,portraitWidth+ 2*wBorder,portraitHeight+ 2*hBorder); } BufferedImage circleImage = new BufferedImage(portraitWidth, portraitWidth, BufferedImage.TYPE_INT_RGB); addPortraitImg(circleImage, imageNew, 0, 0, left,top,portraitWidth,portraitHeight); Graphics2D g2d = createGraphics(circleImage); g2d.setClip(new RoundRectangle2D.Double(0,0,portraitWidth,portraitHeight, wBorder *8 , hBorder *8)); g2d.drawImage(portrait, 0, 0, null); g2d.dispose(); addPortraitImg(imageNew, circleImage, left, top, 0,0,portraitWidth,portraitHeight); return imageNew; } /** * 返回透明的 <code>BufferedImage</code>. * * @param image image to be made transparent * @param transperancy value of the transparency * @return transparent <code>BufferedImage</code> */ public static BufferedImage getTransparentImage(BufferedImage image, float transperancy) { // Create the image using the BufferedImage transparentImage = new BufferedImage(image.getWidth(), image.getHeight(), Transparency.TRANSLUCENT); // Get the images graphics. Graphics2D g = transparentImage.createGraphics(); // Set the graphics composite to Alpha. g.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_OVER, transperancy)); // Draw the passed image into the new transparent image. g.drawImage(image, null, 0, 0); // Free all system resources. g.dispose(); // Return the image return transparentImage; } /** * 写入路径的QR * @param content * @param sideLength * @param outfile * @param format * @throws IOException * @throws WriterException */ public static void writeQR(String content, int sideLength, String outfile, String format) throws IOException, WriterException { BitMatrix matrix = encodeQR(content, sideLength); MatrixToImageWriter.writeToPath(matrix, format, Paths.get(outfile)); } public static BufferedImage getQRImage(String content, int sideLength) throws WriterException { BitMatrix matrix = encodeQR(content, sideLength); return MatrixToImageWriter.toBufferedImage(matrix); } public static BufferedImage getQRImage(String content, int sideLength, MatrixToImageConfig config) throws WriterException { BitMatrix matrix = encodeQR(content, sideLength); return MatrixToImageWriter.toBufferedImage(matrix, config); } /** * 将BufferedImage转为bytes * @param image * @param format * @return * @throws IOException */ public static byte[] convertBufferedImageToBytes(BufferedImage image, String format) throws IOException { ByteArrayOutputStream out = new ByteArrayOutputStream(); ImageIO.write(image, format, out); return out.toByteArray(); } /** * 将bytes转为BufferedImage * @param bytes * @return * @throws IOException */ public static BufferedImage convertBytesToBufferedImage(byte[] bytes) throws IOException { ByteArrayInputStream in = new ByteArrayInputStream(bytes); //作为输入流; return ImageIO.read(in); //将in作为输入流,读取图片存入image中,而这里in可以为ByteArrayInputStream(); } /** * QR编码 * @param content * @param sideLength * @return * @throws WriterException */ public static BitMatrix encodeQR(String content, int sideLength) throws WriterException { // 用于设置QR二维码参数 Hashtable<EncodeHintType, Object> qrParam = new Hashtable<EncodeHintType, Object>(); // 设置QR二维码的纠错级别——这里选择最高H级别 qrParam.put(EncodeHintType.ERROR_CORRECTION, ErrorCorrectionLevel.H); // 设置编码方式 qrParam.put(EncodeHintType.CHARACTER_SET, "UTF-8"); MultiFormatWriter barcodeWriter = new MultiFormatWriter(); // 编码内容,编码类型,生成图片宽度,生成图片高度,设置参数 BitMatrix matrix = barcodeWriter.encode(content, BarcodeFormat.QR_CODE, sideLength, sideLength, qrParam); return matrix; } /** * * @param content * @param sideLength * @return * @throws WriterException */ public static BitMatrix encodePDF17(String content, int sideLength) throws WriterException { // 用于设置QR二维码参数 Hashtable<EncodeHintType, Object> qrParam = new Hashtable<EncodeHintType, Object>(); // 设置QR二维码的纠错级别——这里选择最高H级别 qrParam.put(EncodeHintType.ERROR_CORRECTION, ErrorCorrectionLevel.H); // 设置编码方式 qrParam.put(EncodeHintType.CHARACTER_SET, "UTF-8"); MultiFormatWriter barcodeWriter = new MultiFormatWriter(); // 编码内容,编码类型,生成图片宽度,生成图片高度,设置参数 //BarcodeFormat.DATA_MATRIX BitMatrix matrix = barcodeWriter.encode(content, BarcodeFormat.PDF_417, sideLength, sideLength, qrParam); return matrix; } }