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