效果:
描述:后边的背景是固定的,但是二维码和用户有关,所以要后生成 并且和后边背景合并为一个bitmap 用于分享
原来我是用最常用的方法来通过异步来合成图片的
代码如下
protected Integer[] imgUrls = {R.drawable.share_bg1,
R.drawable.share_bg2,
R.drawable.share_bg3,
R.drawable.share_bg4,
R.drawable.share_bg5};
protected Runnable drawingSharePic = new Runnable() {
@RequiresApi(api = Build.VERSION_CODES.KITKAT)
@Override
public void run() {
try {
isDrawing = true;
for (int i = 0; i < imgUrls.length; i++) {
LogUtil.e("");
Bitmap bitmapBg = BitmapFactory.decodeResource(getResources(), imgUrls[i]);//这里
Bitmap bitmapShare = SharePictureCreator.drawPicture(activity, getShareUrl(), bitmapBg);
if (mListShare == null) {
return;
}
mListShare.add(bitmapShare);
bitmapBg.recycle();
bitmapBg = null;
}
if (mListShare.size() > 1) {
Bitmap bitmap0 = mListShare.get(0);
Bitmap bitmapEnd = mListShare.get(mListShare.size() - 1);
mListShare.add(0, bitmapEnd);
mListShare.add(bitmap0);
}
isPicSuccess = true;
runOnUiThread(new Runnable() {
@Override
public void run() {
dismissProgressDialog();
LogUtil.e("mListImgShare的长度====>>" + mListShare.size());
if (mShareAdapter == null) {
mShareAdapter = new ShareChoosePagerAdapter();
viewPager_share.setAdapter(mShareAdapter);
viewPager_share.setCurrentItem(2);
return;
}
if (mShareAdapter != null) {
mShareAdapter.notifyDataSetChanged();
}
viewPager_share.setCurrentItem(2);
}
});
} catch (ExecutionException e) {
dismissProgressDialog();
isPicSuccess = false;
e.printStackTrace();
} catch (InterruptedException e) {
dismissProgressDialog();
isPicSuccess = false;
e.printStackTrace();
} finally {
isDrawing = false;
}
}
};
new Thread(drawingSharePic).start();
我昨天看了一个人分享rxjava的用法,想用rxjava试试 就改变了写法 后来运行,证明效果一样 贴出来大家分享一下
这个人的文章地址-->>http://gank.io/post/560e15be2dca930e00da1083 写的很详细
Observable.from(imgUrls)//
.subscribeOn(Schedulers.io())
.observeOn(Schedulers.newThread())//开启新线程 下边的map是这个子线程要完成的东西
.map(new Func1<Integer, Bitmap>() {
@Override
public Bitmap call(Integer integer) {
isDrawing = true;
try {
Bitmap bitmapBg = BitmapFactory.decodeResource(getResources(), integer);
Bitmap bitmapShare = SharePictureCreator.drawPicture(activity, getShareUrl(), bitmapBg, mListTxt);
return bitmapShare;
} catch (ExecutionException e) {
e.printStackTrace();
return null;
} catch (InterruptedException e) {
e.printStackTrace();
return null;
}finally {
isDrawing=false;
}
}
}).observeOn(Schedulers.io())//开启一个io线程 在上边的子线程完成之后,
.map(new Func1<Bitmap, List<Bitmap>>() {//这个里是io线程里需要做的事情
@Override
public List<Bitmap> call(Bitmap bitmap) {
isPicSuccess = true;
mListShare.add(bitmap);
return mListShare;
}
}).subscribe(new Action1<List<Bitmap>>() {//这个是安卓给安卓控件加数据了
@Override
public void call(List<Bitmap> bitmaps) {
dismissProgressDialog();
LogUtil.e("mListImgShare的长度====>>" + mListShare.size());
if (mListShare.size() > 1) {
Bitmap bitmap0 = mListShare.get(0);
Bitmap bitmapEnd = mListShare.get(mListShare.size() - 1);
mListShare.add(0, bitmapEnd);
mListShare.add(bitmap0);
}
if (mShareAdapter == null) {
mShareAdapter = new ShareChoosePagerAdapter();
viewPager_share.setAdapter(mShareAdapter);
viewPager_share.setCurrentItem(2);
return;
}
if (mShareAdapter != null) {
mShareAdapter.notifyDataSetChanged();
}
viewPager_share.setCurrentItem(2);
}
});
下边是将背景和二维码合成的工具
//这个是我用来合并背景和二维码的类 需要依赖zxing
public class SharePictureCreator {
public static String TAG = "SharePictureCreator=======>>";
static int relativeWidth = 640;
static int relativeHeight = 1130;
//以上的数都是ui给的像素都是按照640*1130来给的 为了保证画的位置不变 ,需要进行适配
@RequiresApi(api = Build.VERSION_CODES.KITKAT)
public static Bitmap drawPicture(final Activity activity,
String url_login,
Bitmap bitmap_background
) throws ExecutionException, InterruptedException {
Paint paint = new Paint();
paint.setColor(Color.argb(255, 0, 0, 0));
paint.setStrokeWidth(20);
paint.setAntiAlias(true);
//背景bitmap
int widthBg = (int) (bitmap_background.getWidth());
int heightBg = (int) (bitmap_background.getHeight());
//要分享的bitmap
Bitmap bitmapShare = Bitmap.createBitmap(widthBg, heightBg, bitmap_background.getConfig());
// Bitmap bitmapShare=BitmapUtils.getZoomImage(bitmapShareBig,widthBg/2,heightBg/2);
Canvas canvas = new Canvas(bitmapShare);
canvas.drawBitmap(bitmap_background, 0, 0, paint);
//写文字 这个功能我不做了 如果要的话 我传了一个list<string>;
// int txtLeft = 48 * widthBg / relativeWidth;
//int txtTop = 766 * heightBg / relativeHeight;
//int space = 25 * widthBg / relativeWidth;
//paint.setTextSize(20 * widthBg / relativeWidth);// 字体大小
//paint.setStrokeWidth(30);
//if (list_txt != null) {
//for (int i = 0; i < list_txt.size(); i++) {
// canvas.drawText(list_txt.get(i), txtLeft, txtTop + i * space, paint);
// }
// }
//二维码生成
try {
int leftQCode = 456 * widthBg / relativeWidth;//二维码距离左边的距离
int topQCode = 907 * heightBg / relativeHeight;//二维码距离top的距离
int leftQCodeBg = 454 * widthBg / relativeWidth;//二维码后边有个绿色的框 我就画的实心的正方形 让二维码覆盖上了这个是他的left距离
int topQCodeBG = 905 * heightBg / relativeHeight;//绿色背景的top距离
int rightQCodeBg = (454 +160)* widthBg / relativeWidth;//绿色背景的left距离
int bottomQCodeBG = (905+160) * heightBg / relativeHeight;//绿色背景的bottom距离
paint.setARGB(255, 34, 139, 34);
paint.setColor(activity.getResources().getColor(R.color.green_base));
canvas.drawRect(leftQCodeBg, topQCodeBG, rightQCodeBg, bottomQCodeBG, paint);
// Bitmap bitmap_code = CodeCreator.createQRCode(activity, url_login, 120 * widthBg / relativeWidth, 120 * widthBg / relativeWidth);
//二维码中间那个logo
Bitmap bitmapLogo = BitmapFactory.decodeResource(activity.getResources(), R.mipmap.ic_launcher);
Bitmap bitmap_code = LogoCofig.createCode(url_login, bitmapLogo);
// 这个就是变化一下bitmap的大小
Bitmap bitmapCodeUse = BitmapUtils.getZoomImage(bitmap_code, 156 * widthBg / relativeWidth, 156 * widthBg / relativeWidth);
canvas.drawBitmap(bitmapCodeUse, leftQCode, topQCode, paint);
Bitmap zoomImage = BitmapUtils.getZoomImage(bitmapShare, bitmapShare.getWidth() / 2, bitmapShare.getHeight() / 2);
return zoomImage;
} catch (WriterException e) {
return null;
}
}
}
生成二维码的工具
public class LogoCofig {
public class LogoConfig {
/**
* @return 返回带有白色背景框logo
*/
public Bitmap modifyLogo(Bitmap bgBitmap, Bitmap logoBitmap) {
int bgWidth = bgBitmap.getWidth();
int bgHeigh = bgBitmap.getHeight();
//通过ThumbnailUtils压缩原图片,并指定宽高为背景图的3/4
logoBitmap = ThumbnailUtils.extractThumbnail(logoBitmap,bgWidth*3/4, bgHeigh*3/4, ThumbnailUtils.OPTIONS_RECYCLE_INPUT);
Bitmap cvBitmap = Bitmap.createBitmap(bgWidth, bgHeigh, Bitmap.Config.ARGB_8888);
Canvas canvas = new Canvas(cvBitmap);
// 开始合成图片
canvas.drawBitmap(bgBitmap, 0, 0, null);
canvas.drawBitmap(logoBitmap,(bgWidth - logoBitmap.getWidth()) /2,(bgHeigh - logoBitmap.getHeight()) / 2, null);
canvas.save(Canvas.ALL_SAVE_FLAG);// 保存
canvas.restore();
if(cvBitmap.isRecycled()){
cvBitmap.recycle();
}
return cvBitmap;
}
}
/**
* 黑点颜色
*/
private static final int BLACK = 0xFF000000;
/**
* 白色
*/
private static final int WHITE = 0xFFFFFFFF;
/**
* 正方形二维码宽度
*/
private static final int CODE_WIDTH = 440;
/**
* LOGO宽度值,最大不能大于二维码20%宽度值,大于可能会导致二维码信息失效
*/
private static final int LOGO_WIDTH_MAX = CODE_WIDTH / 5;
/**
*LOGO宽度值,最小不能小于二维码10%宽度值,小于影响Logo与二维码的整体搭配
*/
private static final int LOGO_WIDTH_MIN = CODE_WIDTH / 10;
/**
* 生成带LOGO的二维码
*/
public static Bitmap createCode(String content, Bitmap logoBitmap)
throws WriterException {
int logoWidth = logoBitmap.getWidth();
int logoHeight = logoBitmap.getHeight();
int logoHaleWidth = logoWidth >= CODE_WIDTH ? LOGO_WIDTH_MIN
: LOGO_WIDTH_MAX;
int logoHaleHeight = logoHeight >= CODE_WIDTH ? LOGO_WIDTH_MIN
: LOGO_WIDTH_MAX;
// 将logo图片按martix设置的信息缩放
Matrix m = new Matrix();
/*
* 给的源码是,由于CSDN上传的资源不能改动,这里注意改一下
* float sx = (float) 2*logoHaleWidth / logoWidth;
* float sy = (float) 2*logoHaleHeight / logoHeight;
*/
float sx = (float) logoHaleWidth / logoWidth;
float sy = (float) logoHaleHeight / logoHeight;
m.setScale(sx, sy);// 设置缩放信息
Bitmap newLogoBitmap = Bitmap.createBitmap(logoBitmap, 0, 0, logoWidth,
logoHeight, m, false);
int newLogoWidth = newLogoBitmap.getWidth();
int newLogoHeight = newLogoBitmap.getHeight();
Hashtable<EncodeHintType, Object> hints = new Hashtable<EncodeHintType, Object>();
hints.put(EncodeHintType.CHARACTER_SET, "UTF-8");
hints.put(EncodeHintType.ERROR_CORRECTION, ErrorCorrectionLevel.H);//设置容错级别,H为最高
hints.put(EncodeHintType.MAX_SIZE, LOGO_WIDTH_MAX);// 设置图片的最大值
hints.put(EncodeHintType.MIN_SIZE, LOGO_WIDTH_MIN);// 设置图片的最小值
hints.put(EncodeHintType.MARGIN, 2);//设置白色边距值
// 生成二维矩阵,编码时指定大小,不要生成了图片以后再进行缩放,这样会模糊导致识别失败
BitMatrix matrix = new MultiFormatWriter().encode(content,
BarcodeFormat.QR_CODE, CODE_WIDTH, CODE_WIDTH, hints);
int width = matrix.getWidth();
int height = matrix.getHeight();
int halfW = width / 2;
int halfH = height / 2;
// 二维矩阵转为一维像素数组,也就是一直横着排了
int[] pixels = new int[width * height];
for (int y = 0; y < height; y++) {
for (int x = 0; x < width; x++) {
/*
* 取值范围,可以画图理解下
* halfW + newLogoWidth / 2 - (halfW - newLogoWidth / 2) = newLogoWidth
* halfH + newLogoHeight / 2 - (halfH - newLogoHeight) = newLogoHeight
*/
if (x > halfW - newLogoWidth / 2&& x < halfW + newLogoWidth / 2
&& y > halfH - newLogoHeight / 2 && y < halfH + newLogoHeight / 2) {// 该位置用于存放图片信息
/*
* 记录图片每个像素信息
* halfW - newLogoWidth / 2 < x < halfW + newLogoWidth / 2
* --> 0 < x - halfW + newLogoWidth / 2 < newLogoWidth
* halfH - newLogoHeight / 2 < y < halfH + newLogoHeight / 2
* -->0 < y - halfH + newLogoHeight / 2 < newLogoHeight
* 刚好取值newLogoBitmap。getPixel(0-newLogoWidth,0-newLogoHeight);
*/
pixels[y * width + x] = newLogoBitmap.getPixel(
x - halfW + newLogoWidth / 2, y - halfH + newLogoHeight / 2);
} else {
pixels[y * width + x] = matrix.get(x, y) ? BLACK: WHITE;// 设置信息
}
}
}
Bitmap bitmap = Bitmap.createBitmap(width, height,
Bitmap.Config.ARGB_8888);
// 通过像素数组生成bitmap,具体参考api
bitmap.setPixels(pixels, 0, width, 0, 0, width, height);
return bitmap;
}
}
bitmap工具类 ----------------->>这个是在网上找的
package com.puti.getknowledge.utils;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Matrix;
import android.util.Log;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.net.HttpURLConnection;
import java.net.URL;
/**
* Created by Administrator on 2017/12/26.
*/
public class BitmapUtils {
private static final String TAG ="BitmapUtils=====>>" ;
/**
* 图片的缩放方法
*
* @param bitmap :源图片资源
* @param maxSize :图片允许最大空间 单位:KB
* @return
*/
public static Bitmap getZoomImage(Bitmap bitmap, double maxSize) {
if (null == bitmap) {
return null;
}
if (bitmap.isRecycled()) {
return null;
}
// 单位:从 Byte 换算成 KB
double currentSize = bitmapToByteArray(bitmap, false).length / 1024;
// 判断bitmap占用空间是否大于允许最大空间,如果大于则压缩,小于则不压缩
while (currentSize > maxSize) {
// 计算bitmap的大小是maxSize的多少倍
double multiple = currentSize / maxSize;
// 开始压缩:将宽带和高度压缩掉对应的平方根倍
// 1.保持新的宽度和高度,与bitmap原来的宽高比率一致
// 2.压缩后达到了最大大小对应的新bitmap,显示效果最好
bitmap = getZoomImage(bitmap, bitmap.getWidth() / Math.sqrt(multiple), bitmap.getHeight() / Math.sqrt(multiple));
currentSize = bitmapToByteArray(bitmap, false).length / 1024;
}
return bitmap;
}
/**
* 图片的缩放方法
*
* @param orgBitmap :源图片资源
* @param newWidth :缩放后宽度
* @param newHeight :缩放后高度
* @return
*/
public static Bitmap getZoomImage(Bitmap orgBitmap, double newWidth, double newHeight) {
if (null == orgBitmap) {
return null;
}
if (orgBitmap.isRecycled()) {
return null;
}
if (newWidth <= 0 || newHeight <= 0) {
return null;
}
// 获取图片的宽和高
float width = orgBitmap.getWidth();
float height = orgBitmap.getHeight();
// 创建操作图片的matrix对象
Matrix matrix = new Matrix();
// 计算宽高缩放率
float scaleWidth = ((float) newWidth) / width;
float scaleHeight = ((float) newHeight) / height;
// 缩放图片动作
matrix.postScale(scaleWidth, scaleHeight);
Bitmap bitmap = Bitmap.createBitmap(orgBitmap, 0, 0, (int) width, (int) height, matrix, true);
return bitmap;
}
/**
* bitmap转换成byte数组
*
* @param bitmap
* @param needRecycle
* @return
*/
public static byte[] bitmapToByteArray(Bitmap bitmap, boolean needRecycle) {
if (null == bitmap) {
return null;
}
if (bitmap.isRecycled()) {
return null;
}
ByteArrayOutputStream output = new ByteArrayOutputStream();
bitmap.compress(Bitmap.CompressFormat.PNG, 100, output);
if (needRecycle) {
bitmap.recycle();
}
byte[] result = output.toByteArray();
try {
output.close();
} catch (Exception e) {
Log.e(TAG, e.toString());
}
return result;
}
public static Bitmap getBitmapByUrl(String imageUri) {
LogUtil.e("imageUri===>>"+imageUri);
// 显示网络上的图片
Bitmap bitmap = null;
try {
URL myFileUrl = new URL(imageUri);
HttpURLConnection conn = (HttpURLConnection) myFileUrl
.openConnection();
conn.setDoInput(true);
conn.connect();
InputStream is = conn.getInputStream();
bitmap = BitmapFactory.decodeStream(is);
is.close();
LogUtil.e("url转bitmap完成=========>>"+imageUri);
} catch (OutOfMemoryError e) {
e.printStackTrace();
LogUtil.e("url转bitmap错误OutOfMemoryError=========>>"+e.toString());
bitmap = null;
} catch (IOException e) {
e.printStackTrace();
LogUtil.e("url转bitmap错误IOException=========>>"+e.toString());
bitmap = null;
}
return bitmap;
}
}