美文网首页
图片合成Module

图片合成Module

作者: 激扬飞雪 | 来源:发表于2019-06-25 20:28 被阅读0次

描述

  • 应用场景:需要根据后台配置的模板信息,客户端合成海报类信息图片
  • 将图片合成流程抽离出Module库,供不同项目使用
image

源代码

  • 地址
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;
    }

相关文章

  • 图片合成Module

    描述 应用场景:需要根据后台配置的模板信息,客户端合成海报类信息图片 将图片合成流程抽离出Module库,供不同项...

  • 对图片的设置

    合成图片。下载图片。拉伸图片 //合成图片 UIImageView *imageView = [[UIImageV...

  • 图片合成

    两张图片拼接 参考:https://www.feiyeda.top/http://csshengyao.cn/

  • 图片合成

    前段时间遇到产品一个需求,在移动端上合成生成二维码,并且合成背景图和二维码给用户保存; 当时我在想,链接拼接生成二...

  • js利用canvas合成图片

    转自 前端老徐合成图片 递归方式合成图片

  • 2D图片合成游戏

    2D图片合成游戏,主要是这个放在图片上的合成脚本

  • ffmpeg图片与视频互转

    提取9张图片 图片合成图片

  • 如何用PHP合成两张图片?

    前言:业务需要,进行两张图片的合成。 PHP图片合成类 调用方法:

  • 图片合成与添加文字

    一. 图片合成 确认两张素材图片的像素尺寸,决定合成方法(拼接/叠加),根据方法,计算出合成新图片的尺寸。 将图...

  • 图片合成、GIF图片的合成与解析

    一、普通图片合成(两张以上才有意义) 主要步骤: 创建需要合成的UIImage对象,通过CGImageRef获取i...

网友评论

      本文标题:图片合成Module

      本文链接:https://www.haomeiwen.com/subject/gmtfcctx.html