微信规定,分享小程序展示的图片应该在 128KB 以内,同时图片默认展示比例为 5:4。
所以需要对传入的图片进行裁剪和压缩。关于图片压缩有个很大的坑,改了一晚上才好,所以记录一下,先填坑以后再优化。
参考了其他大神的博客,整理出了下面具体的实现方法:
方法一:
/**
* 按5:4裁切图片
*/
private static Bitmap cropImage5To4(Bitmap srcBitmap) {
if (srcBitmap == null) {
return null;
}
int w = srcBitmap.getWidth(); // 得到图片的宽,高
int h = srcBitmap.getHeight();
float srcW = w > h * 1.25f ? h * 1.25f : w;
float srcH = w > h * 1.25f ? h : w / 1.25f;
float retX = w > h * 1.25f ? (w - h * 1.25f) / 2 : 0;//居中裁剪
float retY = w > h * 1.25f ? 0 : (h - w / 1.25f) / 2f;
//以下这句是关键
return Bitmap.createBitmap(srcBitmap, Math.round(retX), Math.round(retY), Math.round(srcW), Math.round(srcH), null, false);
}
/**
* 判断图片类型
*/
public static int getPicTypeByUrl(String url) {
int picType = -1;
if (url == null) {
return picType;
}
if (url.equals("")) {
return picType;
}
String[] picArray = url.split("/");
String picStr = "";
if (picArray.length > 0) {
picStr = picArray[picArray.length - 1];
} else {
picStr = picArray[0];
}
if (picStr.toLowerCase().contains(".png")) {
picType = 0;
} else if (picStr.toLowerCase().contains(".jpg") || picStr.toLowerCase().contains(".jpeg")) {
picType = 1;
}
return picType;
}
/**
* 按质量压缩图片
*/
private byte[] compressBitmap(Bitmap bitmap, long sizeLimit) {
ByteArrayOutputStream baos = new ByteArrayOutputStream();
int quality = 100;
bitmap.compress(Bitmap.CompressFormat.JPEG, quality, baos);
// 循环判断压缩后图片是否超过限制大小
while (baos.toByteArray().length / 1024 > sizeLimit) {
// 清空baos
baos.reset();
bitmap.compress(Bitmap.CompressFormat.JPEG, quality, baos);
quality -= 10;
}
return baos.toByteArray();
}
/**
* 分享到小程序
*/
public void shareWxMini(String path, String title, Bitmap bitmap, int picType) {
WXMiniProgramObject miniProgramObj = new WXMiniProgramObject();
miniProgramObj.webpageUrl = "http://www.qq.com"; // 兼容低版本的网页链接
miniProgramObj.miniprogramType = AppManager.isDebug() ? WXMiniProgramObject.MINIPROGRAM_TYPE_PREVIEW : WXMiniProgramObject.MINIPTOGRAM_TYPE_RELEASE;// 正式版:0,测试版:1,体验版:2
miniProgramObj.userName = Constants.MINI_ID; // 小程序原始id
miniProgramObj.path = path; //小程序页面路径;对于小游戏,可以只传入 query 部分,来实现传参效果,如:传入 "?foo=bar"
WXMediaMessage msg = new WXMediaMessage(miniProgramObj);
msg.title = title; // 小程序消息title
msg.description = ""; // 小程序消息desc
if (bitmap != null) {
ByteArrayOutputStream baos = new ByteArrayOutputStream();
bitmap.compress(picType == 0 ? Bitmap.CompressFormat.PNG : Bitmap.CompressFormat.JPEG, 50, baos);
msg.thumbData = compressBitmap(bitmap, 128);
}
SendMessageToWX.Req req = new SendMessageToWX.Req();
req.transaction = buildTransaction("miniProgram");
req.message = msg;
req.scene = SendMessageToWX.Req.WXSceneSession; // 目前只支持会话
api.sendReq(req);
}
方法二:重新用 Canvas 绘制一张图,将所要展示的图片居中展示
/**
* 居中裁剪图片
*/
public static Bitmap drawWXMiniBitmap(Bitmap bitmap, int width, int height) {
Bitmap mBitmap = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888);
// 用这个Bitmap生成一个Canvas,然后canvas就会把内容绘制到上面这个bitmap中
Canvas mCanvas = new Canvas(mBitmap);
// 绘制画笔
Paint mPicturePaint = new Paint();
// 绘制背景图片
mCanvas.drawBitmap(mBitmap, 0.0f, 0.0f, mPicturePaint);
// 绘制图片的宽、高
int width_head = bitmap.getWidth();
int height_head = bitmap.getHeight();
// 绘制图片--保证其在水平方向居中
mCanvas.drawBitmap(bitmap, (width - width_head) / 2, (height - height_head) / 2,
mPicturePaint);
// 保存绘图为本地图片
mCanvas.save();
mCanvas.restore();
return mBitmap;
}
/**
* 按指定宽高缩放图片
*/
public static Bitmap resizeBitmap(Bitmap bitmap, int w, int h) {
int width = bitmap.getWidth();
int height = bitmap.getHeight();
float scaleWidth = ((float) w) / width;
float scaleHeight = ((float) h) / height;
Matrix matrix = new Matrix();
matrix.postScale(scaleWidth, scaleHeight);
Bitmap resizedBitmap = Bitmap.createBitmap(bitmap, 0, 0, width,
height, matrix, true);
return resizedBitmap;
}
// 调用
Bitmap bitmap = BitmapUtil.drawWXMiniBitmap(bitmap, bitmap.getHeight() * 5 / 4, bitmap.getHeight());
if (BitmapUtil.isOverSize(bitmap, 128)) {// 判断是否超过128kb,方法略
bitmap = Utils.resizeBitmap(bitmap, 300, 240);
}
// 裁剪缩放完成后如果还大于128kb,再进行质量压缩,压缩方法用方法一
// ...
方法三:
这里没写具体的代码,只记录一下思路。
把图片放到宽高固定5:4的ImageView上(如果图片被拉伸就先裁剪再放上去),然后对ImageView截图,得到的就已经是压缩好的图片了。
关于压缩图片的坑
我最开始用的Luban压缩,毕竟是GitHub大神仿微信压缩的库,肯定没有问题,就是用起来麻烦一些,需要保存图片文件并转成Bitmap。得到的图片虽然已经被压缩到小于128kb,但还是分享不了。我以为是方法的问题,看日志发现是压缩好的Bitmap转成byte数组的锅,转换后大小变大了,超过128kb所以分享不了。
最后我用方法一,直接判断byte数组的大小进行压缩。成功分享。
如果有不对的地方欢迎大佬们留言指正。