个性二维码生成(android开发)

@二维码生成

个性二维码

第一次接触二维码开发,对二维码刚有所了解的时候,就得到要做个性二维码 的需求。看着网络上的个性二维码,陷入了沉思。 心里千万遍问自己,这到底是什么实现原理呢?后面找来找去,各种资料都翻上来了:在朋友的帮助下,找到一篇有用的文章,并在此文章的引导下,完成了个性二维码的开发。感谢作者。即下发的原理参考链接

原理参考

链接: link.

图片参考:

在这里插入图片描述

代码片

上面原理参考有了大体实现原理的代码了,但是还漏了三四个方法,花了两天白了头给补上了。。。
(File 对应后台传过来的图片,我这边给转成file文件使用)


 /**
     绘制个性二维码
     */
    public Bitmap createAreBitmap(Context context, String str, int width, boolean isDeleteWhiteGap,
                                  ErrorCorrectionLevel level,List<ArtQrcodeBean> artQrcodeBeans)
            throws WriterException, NullPointerException {
        Hashtable<EncodeHintType, Object> hints = new Hashtable<>();
        if (null != level) {
            hints.put(EncodeHintType.ERROR_CORRECTION, level);// 指定纠错等级
        }
        hints.put(EncodeHintType.CHARACTER_SET, "UTF-8");//指定编码格式
        if (TextUtils.isEmpty(str)) {
            return null;
        }
        if (matrix == null){
            matrix = new QRCodeWriter().encode(str, BarcodeFormat.QR_CODE,
                    0, 0, hints);

            if (isDeleteWhiteGap) {
                matrix = deleteWhite(matrix);//删除白边
            }
        }
        if (formatBitMatrix(matrix)){

            this.artQrcodeBeans = artQrcodeBeans;

            int codeWidth = width/codeNumPerLine;
            int remainder = width%codeNumPerLine;
            int matrixWidth = width;
            if (remainder > 0){//调整初始图片的宽度,凑整,让每个码元点占用整数个像素点
                codeWidth++;
                matrixWidth = codeWidth*codeNumPerLine;
            }
            judgeRule();
            getAllRects();
            searchfRect();
            Bitmap bitmap = Bitmap.createBitmap(matrixWidth,matrixWidth, Bitmap.Config.ARGB_8888);
            Canvas canvas = new Canvas(bitmap);

            Paint paint = new Paint();
            paint.setColor(Color.WHITE);
            canvas.drawRect(0,0,bitmap.getWidth(),bitmap.getHeight(),paint);
            codeUnit = codeWidth;
            drawPicture(canvas,paint,codeWidth);

            Bitmap bitmap1 = Bitmap.createBitmap(bitmap.getWidth()-codeWidth,bitmap.getHeight()-codeWidth, Bitmap.Config.ARGB_8888);
            Canvas canvas1 = new Canvas(bitmap1);
            canvas1.drawBitmap(bitmap,0,0,null);
            return  bitmap1;
        }
        return  null;
    }

    /**
     * 格式化BitMatrix,找出其中所有的码元点
     * @param bitMatrix
     * @return
     */
    private boolean formatBitMatrix(BitMatrix bitMatrix){
        boolean success = false;
        int matrixLength = bitMatrix.getWidth();
        int matrixHeight = bitMatrix.getHeight();
        if (matrixLength == matrixHeight && matrixLength>(LOCATOR_WIDTH+1)*2){
            success = true;
            codeNumPerLine = matrixLength;

            leftLocator.set(0,0,LOCATOR_WIDTH,LOCATOR_WIDTH);
            rightLocator.set(matrixLength-LOCATOR_WIDTH-codeUnit,0,matrixLength,LOCATOR_WIDTH);
            bottomLocator.set(0,matrixLength-LOCATOR_WIDTH-codeUnit,LOCATOR_WIDTH,matrixLength);
            //遍历,得出所有的码元
            for (int x = 0; x < matrixLength; x++) {
                StringBuilder sb = new StringBuilder("列"+x);
                StringBuilder sb_p = new StringBuilder("point");
                //先列遍历,在行遍历
                for (int y = 0; y < matrixLength; y++) {
                    //查看此element是否为有信息的码元点(二维码黑色部分)
                    boolean info = bitMatrix.get(x,y);
                    MyPoint point = new MyPoint(x,y);
                    if (info){
                        String pointStr = "["+y+","+x+"]";
                        if (!isElementInRect(leftLocator,point) && !isElementInRect(rightLocator,point) &&
                                !isElementInRect(bottomLocator,point) ){
//以列优先的顺序存放,故需要把下标的行列反过来,便于操作
                            int columnRow = y+x*matrixLength;
                            //存储码元在可用码元矩阵中的列行坐标
                            this.codeElements.put(columnRow,point);
                            codeElementList.add(point);
                            sb.append(pointStr);
                        }else {
                            sb_p.append(pointStr);
                        }
                    }
                }
                sb_p.append(" in locator");
            }
        }
        return success;
    }
/**
 * 遍历形状集合Shape,查找出所有的矩形框,将其中的码元标记为已发现,并添加到outElements集合里
 * @param shape
 */
private void adjustRect(RectShape shape) {
    for (int i = 0; i < shape.getAllPoints().size(); i++) {
        for (int j = 0; j < codeElements.size(); j++) {
            if ( shape.getAllPoints().get(i).equals(codeElements.valueAt(j))){
                outElements.put(codeElements.keyAt(j),codeElements.valueAt(j));
            }
        }
    }
}

private boolean containt(MyPoint point){
    if (point == null ||point.isAdd())
        return false;
    return codeElementList.contains(point) ;
}

private void drawPicture( Canvas canvas, Paint paint ,int codeWidth) {
    //先画三个定位符
    Bitmap locatorBitmap = BitmapFactory.decodeFile(codeEyeFile.getAbsolutePath());
    Bitmap locatorIcon = Bitmap.createScaledBitmap(locatorBitmap,LOCATOR_WIDTH*codeWidth,LOCATOR_WIDTH*codeWidth,true);
    canvas.drawBitmap(locatorIcon, leftLocator.left*codeWidth,leftLocator.top*codeWidth,paint);
    canvas.drawBitmap(locatorIcon,rightLocator.left*codeWidth,rightLocator.top*codeWidth,paint);
    canvas.drawBitmap(locatorIcon,bottomLocator.left*codeWidth,bottomLocator.top*codeWidth,paint);

    Random rand = new Random();
    //再画找到的所有矩形框
    for (int index1 = 0; index1 < allRects.size(); index1++) {
        int shapeId = allRects.keyAt(index1);//key为此集合中相同的shapeId
        SparseArray<MyPoint> rects = allRects.valueAt(index1);
        RectShape shape = SHAPES.get(shapeId);
        if (shape.getFileList()!= null && shape.getFileList().size() != 0){
            int size2 = rects != null?rects.size():0;
            List<Bitmap>   bitmaps1 = new ArrayList<>();
            for (int i = 0; i < shape.getFileList().size(); i++) {
                if (shape.getFileList().get(i)  != null){
                    Bitmap bmp = BitmapFactory.decodeFile(shape.getFileList().get(i) .getAbsolutePath());
                    Bitmap shapeIcon = Bitmap.createScaledBitmap(bmp,(int) shape.getWidth()*codeUnit,(int) shape.getHeight()*codeUnit,true);
                    bitmaps1.add(shapeIcon);
                }
            }
            int num = 0;
            for (int index2 = 0; index2 < size2; index2++) {
                MyPoint point = rects.valueAt(index2);
                if (point != null){

                    if (bitmaps1.size() != 1){
                        num =  rand.nextInt(bitmaps1.size());
                    }

                    Bitmap bitmap = bitmaps1.get(num);
                    canvas.drawBitmap(bitmap,point.x * codeUnit,point.y*codeUnit,paint);
                }
            }
            for (int i = 0; i < bitmaps1.size(); i++) {
                bitmaps1.get(i).recycle();
            }
        }
    }

    if ( fileType11List.size() != 0){
        //再画剩下的单个码元
        List<Bitmap> codeBitmaps = new ArrayList<>();
        for (int i = 0; i < fileType11List.size(); i++) {
            Bitmap singleBitmap = BitmapFactory.decodeFile(fileType11List.get(i).getAbsolutePath());
            Bitmap codeBmp = Bitmap.createScaledBitmap(singleBitmap,codeUnit,codeUnit,true);
            codeBitmaps.add(codeBmp);
        }
        int size = codeElements.size();
        int num = 0;
        for (int singleIndex = 0; singleIndex < size; singleIndex++) {
            MyPoint point = codeElements.valueAt(singleIndex);

            if (point != null){
                if (codeBitmaps.size() != 1){
                    num =  rand.nextInt(codeBitmaps.size());
                }
                Bitmap bitmap = codeBitmaps.get(num);
                canvas.drawBitmap(bitmap,point.x * codeUnit,point.y*codeUnit,paint);
            }
        }
        for (int i = 0; i < codeBitmaps.size(); i++) {
            codeBitmaps.get(i).recycle();
        }
        System.gc();
    }
}

/*除白边*/
private BitMatrix deleteWhite(BitMatrix matrix) {
    int[] rec = matrix.getEnclosingRectangle();
    int resWidth = rec[2] + 1;//右
    int resHeight = rec[3] + 1;//下

    BitMatrix resMatrix = new BitMatrix(resWidth, resHeight);
    resMatrix.clear();
    for (int i = 0; i < resWidth; i++) {
        for (int j = 0; j < resHeight; j++) {
            if (matrix.get(i + rec[0], j + rec[1]))
                resMatrix.set(i, j);
        }
    }
    return resMatrix;
}


```javascript
public class MyPoint extends Point {
    private boolean isAdd = false;
    public MyPoint() {
    }

    public MyPoint(int x, int y) {
        super(x, y);
    }

    public MyPoint(@NonNull Point src) {
        super(src);
    }

    public boolean isAdd() {
        return isAdd;
    }

    public void setAdd(boolean add) {
        isAdd = add;
    }
}

不明白可以私我
源码下载

bean类等
public class ArtQrcodeBean implements Parcelable {
private Bitmap codeEyeBitmap;
private String img_url;
private int rule;
private Bitmap bitmap;

protected ArtQrcodeBean(Parcel in) {
    codeEyeBitmap = in.readParcelable(Bitmap.class.getClassLoader());
    img_url = in.readString();
    rule = in.readInt();
    bitmap = in.readParcelable(Bitmap.class.getClassLoader());
}

public static final Creator<ArtQrcodeBean> CREATOR = new Creator<ArtQrcodeBean>() {
    @Override
    public ArtQrcodeBean createFromParcel(Parcel in) {
        return new ArtQrcodeBean(in);
    }

    @Override
    public ArtQrcodeBean[] newArray(int size) {
        return new ArtQrcodeBean[size];
    }
};

public Bitmap getBitmap() {
    return bitmap;
}

public void setBitmap(Bitmap bitmap) {
    this.bitmap = bitmap;
}


public String getImg_url() {
    return img_url;
}

public void setImg_url(String img_url) {
    this.img_url = img_url;
}

public int getRule() {
    return rule;
}

public void setRule(int rule) {
    this.rule = rule;
}

public Bitmap getCodeEyeBitmap() {
    return codeEyeBitmap;
}

public void setCodeEyeBitmap(Bitmap codeEyeBitmap) {
    this.codeEyeBitmap = codeEyeBitmap;
}

@Override
public int describeContents() {
    return 0;
}

@Override
public void writeToParcel(Parcel dest, int flags) {
    dest.writeParcelable(codeEyeBitmap, flags);
    dest.writeString(img_url);
    dest.writeInt(rule);
    dest.writeParcelable(bitmap, flags);
}

}

public class RectShape extends Shape {
private RectF mRect = new RectF();

public RectShape() {}

@Override
public void draw(Canvas canvas, Paint paint) {
    canvas.drawRect(mRect, paint);
}

@Override
public void getOutline(Outline outline) {
    final RectF rect = rect();
    outline.setRect((int) Math.ceil(rect.left), (int) Math.ceil(rect.top),
            (int) Math.floor(rect.right), (int) Math.floor(rect.bottom));
}

/**
 * chf
 * TYPE_33:指代 x轴3个点,y轴3个点的矩阵
 */
private int resID;

// private File file;
private List bitmapList;
private int type;
public static final int TYPE_32 = 32;
public static final int TYPE_23 = 23;
public static final int TYPE_22 = 22;
public static final int TYPE_12 = 12;
public static final int TYPE_13 = 13;
public static final int TYPE_21 = 21;
public static final int TYPE_31 = 31;
public static final int TYPE_41 = 41;
public static final int TYPE_14 = 14;
private List allPoints = new ArrayList<>();

// public File getFile() {
// return file;
// }
//
// public void setFile(File file) {
// this.file = file;
// }

public List<Bitmap> getBitmapList() {
    return bitmapList;
}

public void setBitmapList(List<Bitmap> bitmapList) {
    this.bitmapList = bitmapList;
}

public int getResID() {
    return resID;
}

public void setResID(int resID) {
    this.resID = resID;
}

public int getType() {
    return type;
}

public void setType(int type) {
    this.type = type;
}

public List<MyPoint> getAllPoints() {
    return allPoints;
}

public void setAllPoints(List<MyPoint> allPoints) {
    this.allPoints = allPoints;
}

@Override
protected void onResize(float width, float height) {
    mRect.set(0, 0, width, height);
}

/**
 * Returns the RectF that defines this rectangle's bounds.
 */
protected final RectF rect() {
    return mRect;
}

@Override
public RectShape clone() throws CloneNotSupportedException {
    final RectShape shape = (RectShape) super.clone();
    shape.mRect = new RectF(mRect);
    return shape;
}

@Override
public boolean equals(Object o) {
    if (this == o) {
        return true;
    }
    if (o == null || getClass() != o.getClass()) {
        return false;
    }
    if (!super.equals(o)) {
        return false;
    }
    RectShape rectShape = (RectShape) o;
    return Objects.equals(mRect, rectShape.mRect);
}

@Override
public int hashCode() {
    return Objects.hash(super.hashCode(), mRect);
}

}

评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值