描述
- 应用场景:需要根据后台配置的模板信息,客户端合成海报类信息图片
- 将图片合成流程抽离出Module库,供不同项目使用
源代码
- 地址
https://gitee.com/zhoulikai/ImageMerge
-
项目结构
image
分析说明
- 将海报上文字、图片、二维码抽象一个个类型的元素,元素只关心两件事:生成元素所需要原料(如文字需要画笔、图片需要bitmap),其次元素向画布上绘制
示例代码:
package com.kaily.imagelib;
import android.graphics.Canvas;
/**
* 合成图片所需要的元素
*
* @date 2018/10/19 下午1:54
* @author: kaily_zhou
*/
public interface IMergeImageElement {
/**
* 生成元素对象
*
* @return
*/
boolean generateElement();
/**
* 将元素画到画布上
*
* @param canvas
* @return
*/
boolean mergeImage(Canvas canvas);
/**
* 是否是必须元素
*
* @return
*/
boolean isRequireElement();
}
文字元素
package com.kaily.imagelib.element;
import android.graphics.Canvas;
import android.graphics.Paint;
import android.text.Layout;
import android.text.StaticLayout;
import android.text.TextPaint;
import android.util.Log;
import com.kaily.imagelib.IMergeImageElement;
/**
* 文本元素
*
* @author kaily_zhou
* @date 2018/10/19 下午2:04
*/
public class TextElement implements IMergeImageElement {
private final String TAG = "TextElement";
private String text;
private float textSize;
private int textColor;
private int left;
private int top;
private int align;
private int width;
private int height;
private boolean isRequireElement;
private StaticLayout titleLayout;
private boolean isBoldFont;
public TextElement(String text, float textSize, int textColor,
int left, int top, int align, int width, boolean isRequireElement) {
this.text = text;
this.textSize = textSize;
this.textColor = textColor;
this.left = left;
this.top = top;
this.align = align;
this.width = width;
this.isRequireElement = isRequireElement;
}
public TextElement(String text, float textSize, int textColor,
int left, int top, int align, int width, boolean isRequireElement, boolean isBoldFont) {
this(text, textSize, textColor,
left, top, align, width, isRequireElement);
this.isBoldFont = isBoldFont;
}
@Override
public boolean generateElement() {
try {
Paint paint = new Paint();
TextPaint textpaint = new TextPaint(paint);
textpaint.setTextSize(textSize);
textpaint.setFakeBoldText(isBoldFont);
textpaint.setAntiAlias(true);
textpaint.setColor(textColor);
Layout.Alignment alignment = Layout.Alignment.ALIGN_NORMAL;
if (this.align == 1) {
alignment = Layout.Alignment.ALIGN_NORMAL;
} else if (this.align == 2) {
alignment = Layout.Alignment.ALIGN_CENTER;
} else if (this.align == 3) {
alignment = Layout.Alignment.ALIGN_OPPOSITE;
}
titleLayout = new StaticLayout(text, textpaint,
width, alignment, 1f, 0f, false);
height = titleLayout.getHeight();
Log.d(TAG, ">>>>" + height);
return true;
} catch (Exception e) {
return !isRequireElement;
}
}
public int getHeight() {
return height;
}
@Override
public boolean mergeImage(Canvas canvas) {
if (canvas == null) {
return false;
}
if (titleLayout == null) {
return !isRequireElement;
}
try {
canvas.save();
canvas.translate(left, top);
titleLayout.draw(canvas);
canvas.restore();
return true;
} catch (Exception e) {
return !isRequireElement;
}
}
@Override
public boolean isRequireElement() {
return isRequireElement;
}
}
图片元素
package com.kaily.imagelib.element;
import android.graphics.Bitmap;
import android.graphics.Canvas;
import com.bumptech.glide.Glide;
import com.bumptech.glide.request.target.Target;
import com.kaily.imagelib.BaseApplication;
import com.kaily.imagelib.IMergeImageElement;
import com.kaily.imagelib.utils.BitmapUtils;
/**
* Image元素
*
* @author kaily_zhou
* @date 2018/10/19 下午1:59
*/
public class ImageElement implements IMergeImageElement {
public static final int IMG_LOAD_TYPE_ORIGINAL = 1;
public static final int IMG_LOAD_TYPE_GLIDE = 2;
protected String imgUrl;
protected boolean isRequireElement;
protected Bitmap bitmap;
protected int width;
protected int height;
private float left;
private float top;
private Bitmap orignBitmap;
private int imgLoadType = IMG_LOAD_TYPE_ORIGINAL;
//是否以宽度为标准进行缩放
private boolean isWidthStandard;
public ImageElement(String imgUrl, boolean isRequireElement, float left, float top) {
this.imgUrl = imgUrl;
this.isRequireElement = isRequireElement;
this.left = left;
this.top = top;
}
public ImageElement(Bitmap bitmap, boolean isRequireElement, float left, float top) {
this.orignBitmap = bitmap;
this.isRequireElement = isRequireElement;
this.left = left;
this.top = top;
}
public ImageElement(String imgUrl, boolean isRequireElement, float left, float top, int width, int height) {
this(imgUrl, isRequireElement, left, top);
this.width = width;
this.height = height;
}
public ImageElement(String imgUrl, boolean isRequireElement, float left, float top, int width, int height, int imgLoadType) {
this(imgUrl, isRequireElement, left, top);
this.width = width;
this.height = height;
this.imgLoadType = imgLoadType;
}
public ImageElement(String imgUrl, boolean isRequireElement, float left, float top, int width, int height, int imgLoadType, boolean isWidthStandard) {
this(imgUrl, isRequireElement, left, top, width, height, imgLoadType);
this.isWidthStandard = isWidthStandard;
}
@Override
public boolean generateElement() {
if (orignBitmap != null) {
bitmap = orignBitmap;
return true;
}
if (imgLoadType == IMG_LOAD_TYPE_GLIDE) {
//使用glide加载
try {
bitmap = Glide.with(BaseApplication.getAppContext())
.load(imgUrl)
.asBitmap()
.centerCrop()
.into(Target.SIZE_ORIGINAL, Target.SIZE_ORIGINAL).get();
} catch (Exception e) {
e.printStackTrace();
}
} else {
//使用原始加载
bitmap = BitmapUtils.getBitmapFormUrl(imgUrl);
}
if (!isWidthStandard) {
if (bitmap != null && width > 0 && height > 0) {
bitmap = BitmapUtils.zoomBitmap(bitmap, width, height);
}
} else {
if (bitmap != null && width > 0) {
int originalWidth = bitmap.getWidth();
if (originalWidth > 0) {
float ratio = (float) width / (float) originalWidth;
bitmap = BitmapUtils.scaleBitmap(bitmap, ratio);
if (bitmap != null) {
height = bitmap.getHeight();
}
} else {
bitmap = null;
}
} else {
bitmap = null;
}
}
if (isRequireElement) {
return bitmap != null;
} else {
return true;
}
}
public int getHeight() {
return height;
}
@Override
public boolean mergeImage(Canvas canvas) {
if (canvas == null) {
return false;
}
if (bitmap == null) {
return !isRequireElement;
}
try {
canvas.drawBitmap(bitmap, left, top, null);
return true;
} catch (Exception e) {
return !isRequireElement;
}
}
@Override
public boolean isRequireElement() {
return isRequireElement;
}
}
二维码元素
package com.kaily.imagelib.element;
import android.graphics.Bitmap;
import com.kaily.imagelib.element.ImageElement;
import com.kaily.imagelib.utils.ZxingUtils;
/**
* 二维码生成
*
* @author kaily_zhou
* @date 2018/10/19 下午3:15
*/
public class QRCodeImageElement extends ImageElement {
private String shareUrl;
private int width;
private int height;
private Bitmap defaultIcon;
public QRCodeImageElement(String qrIconUrl, String shareUrl, Bitmap defaultIcon, boolean isRequireElement,
float left, float top, int width, int height) {
super(qrIconUrl, isRequireElement, left, top);
this.shareUrl = shareUrl;
this.width = width;
this.height = height;
this.defaultIcon = defaultIcon;
}
@Override
public boolean generateElement() {
super.generateElement();
if (bitmap != null) {
defaultIcon = bitmap;
}
try {
bitmap = ZxingUtils.createQRImage(shareUrl, width, width, defaultIcon, ZxingUtils.PADDING_SIZE_MIN);
return true;
} catch (Exception e) {
return !isRequireElement;
}
}
}
使用
根据后台配置信息,生成不同类型的元素对象放入集合中,依次调用不同元素绘制方法即可
mergeImage.startMerge(context, new MergeImage.MergeCallBack() {
@Override
public Bitmap mergeProcess() {
//创建合成图片所需要的属性
ImageMergeAttr imageMergeAttr = createImageMergeAttr();
//创建合成图片所需要的元素
List<IMergeImageElement> mergeImageElements = createMergeImageElements(imageShareInfo, imageMergeAttr);
//根据图片元素集合进行图片合成
Bitmap shareBitmap = mergeImageElement(imageMergeAttr.width, imageMergeAttr.height, mergeImageElements);
return shareBitmap;
}
@Override
public void callback(Bitmap bitmap) {
if (mergeCallBack != null) {
mergeCallBack.callback(bitmap);
}
}
});
/**
* 根据图片上Element合成图片
*
* @param sourceBitmapWidth
* @param sourceBitmapHeight
* @param imageElements
* @return
*/
private Bitmap mergeImageElement(int sourceBitmapWidth, int sourceBitmapHeight,
List<IMergeImageElement> imageElements) {
if (sourceBitmapHeight <= 0 || sourceBitmapWidth <= 0) {
return null;
}
if (imageElements == null || imageElements.isEmpty()) {
return null;
}
Bitmap shareBitmap = Bitmap.createBitmap(sourceBitmapWidth, sourceBitmapHeight, Bitmap.Config.ARGB_8888);
Canvas canvas = new Canvas(shareBitmap);
canvas.drawColor(Color.WHITE);
for (IMergeImageElement mergeImageElement : imageElements) {
if (mergeImageElement != null) {
boolean result = mergeImageElement.mergeImage(canvas);
if (!result) {
return null;
}
}
}
return shareBitmap;
}
网友评论