从二维码中提取数据并创建一个带有颜色的新二维码

Extract the data from QR Codes and create a new QR code with colour

有人听说过这个吗?提取QR Codes(所有二维码必须在相同的宽度和高度{square})并从每个QR Code中获取数据,并将它们组合起来。然后从每个二维码中获取每个像素值并将它们更改为hexadecimal。 你会给出#FFFFFFFF#FF000000#00000000(白色、黑色、透明)之类的(但是对于黑色和白色QR Code,它只会是其中的2个)。然后对于每个 QR 代码中的每个值,通过创建一个 new colour QR Code 颜色根据每个十六进制的值和新的内容颜色 QR Code 将具有从之前的 QR Codes.

中提取的内容

比如我现在做的是把QR Code中的8个数字提取出来,然后合并内容,然后新建一个colour QR Code.

到现在为止,我卡在了这个过程的中间。通过将值更改为 hexadecimal,我已成功提取每个 QR Code 的内容和像素。问题是如何将 hexadecimal 值从每个 QR code 更改为 ARGB(alpha、红色、绿色、蓝色)颜色并创建新颜色 QR Code

不过,我有 Google 的提示,有人说 MatrixToImageWriter 会很有用。但是那里并没有太多对我相似和有用的工作。好吧,我需要一些帮助。但是,我不确定它是否对我有用。

PS: 如果有人愿意,我可以在这里附上我的作品。

PSS:我正在使用 Zxing 库扫描并从每个 QR Code.

中获取结果

我刚刚编写了所需的 decode/encode 方法;矩阵看起来不同,因为我用 QR Droid application and the output QR code with ZXing 创建了输入 QR 码,它可能使用不同级别的纠错;尽管如此,两者都有相同的目的地URL,这是我的。

依赖项来自存储库 google()mavenCentral():

dependencies {

    implementation "androidx.appcompat:appcompat:1.0.2"

    // https://mvnrepository.com/artifact/com.google.zxing
    implementation "com.google.zxing:core:3.3.3"
    implementation "com.google.zxing:android-core:3.3.0"
}

使用的布局资源:

<?xml version="1.0" encoding="utf-8"?>
<androidx.appcompat.widget.LinearLayoutCompat
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="horizontal"
    android:gravity="center">

    <androidx.appcompat.widget.AppCompatImageView
        android:id="@+id/inputImage"
        android:src="@drawable/qrcode"
        android:layout_height="200dp"
        android:layout_width="200dp"
        android:padding="8dp"/>

    <androidx.appcompat.widget.AppCompatImageView
        android:id="@+id/outputImage"
        android:layout_height="200dp"
        android:layout_width="200dp"
        android:padding="8dp"/>

</androidx.appcompat.widget.LinearLayoutCompat>

以及BitMatrix的操纵;当 String 可用时,encode() 方法就足够了;只是为了一个完整的例子而添加了这两种方法(它从一个 AppCompatImageView 读取 Bitmap 然后写入另一个 AppCompatImageView):

import android.graphics.Bitmap;
import android.graphics.drawable.BitmapDrawable;
import android.os.Bundle;
import android.util.Log;

import androidx.annotation.ColorInt;
import androidx.appcompat.app.AppCompatActivity;
import androidx.appcompat.widget.AppCompatImageView;

import com.google.zxing.BarcodeFormat;
import com.google.zxing.BinaryBitmap;
import com.google.zxing.LuminanceSource;
import com.google.zxing.MultiFormatReader;
import com.google.zxing.MultiFormatWriter;
import com.google.zxing.NotFoundException;
import com.google.zxing.RGBLuminanceSource;
import com.google.zxing.Result;
import com.google.zxing.WriterException;
import com.google.zxing.common.BitMatrix;
import com.google.zxing.common.HybridBinarizer;

public class MainActivity extends AppCompatActivity {

    private AppCompatImageView mInputImage;
    private AppCompatImageView mOutputImage;

    @Override
    protected void onCreate(Bundle savedInstanceState) {

        super.onCreate(savedInstanceState);
        this.setContentView(R.layout.layout_main);

        this.mInputImage = this.findViewById(R.id.inputImage);
        this.mOutputImage = this.findViewById(R.id.outputImage);

        Bitmap bitmap = ((BitmapDrawable) this.mInputImage.getDrawable()).getBitmap();
        String data = this.decode(bitmap);

        bitmap = this.encode(data, bitmap.getWidth(), bitmap.getHeight(), 0xFFFFD034,0xFF06425C);
        this.mOutputImage.setImageBitmap(bitmap);
    }

    private String decode(Bitmap bitmap) {

        String data = null;
        MultiFormatReader reader = new MultiFormatReader();
        int[] intArray = new int[bitmap.getWidth() * bitmap.getHeight()];
        bitmap.getPixels(intArray, 0, bitmap.getWidth(), 0, 0, bitmap.getWidth(), bitmap.getHeight());
        LuminanceSource source = new RGBLuminanceSource(bitmap.getWidth(), bitmap.getHeight(), intArray);
        BinaryBitmap binary = new BinaryBitmap(new HybridBinarizer(source));

        try {
            Result result = reader.decode(binary);
            data = result.getText();
        } catch (NotFoundException e) {
            e.printStackTrace();
        }

        Log.d("ZXing", "decoded: " + data);
        return data;
    }

    private Bitmap encode(String contents, int width, int height, @ColorInt int foreground, @ColorInt int background) {

        MultiFormatWriter writer = new MultiFormatWriter();
        BitMatrix matrix = null;
        Bitmap bitmap = null;

        try {
            matrix = writer.encode(contents, BarcodeFormat.QR_CODE, width, height);
        } catch (WriterException e) {
            e.printStackTrace();
        }

        if(matrix != null) {
            int[] pixels = new int[width * height];
            for (int y = 0; y < height; y++) {
                int offset = y * width;
                for (int x = 0; x < width; x++) {
                    pixels[offset + x] = matrix.get(x, y) ? foreground : background;
                }
            }
            bitmap = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888);
            bitmap.setPixels(pixels, 0, width, 0, 0, width, height);
        }

        return bitmap;
    }
}

结果看起来像这样;其中左边一个是输入矩阵,右边一个是输出矩阵:

好吧,经过几天的互联网挖掘。我找到了解决方案,我认为有一天它会对其他人有所帮助。

 QRCodeWriter qw = new QRCodeWriter();

try {
    HashMap<EncodeHintType, Object> hints = new HashMap<>();
    hints.put(EncodeHintType.CHARACTER_SET, "utf-8");
    hints.put(EncodeHintType.MARGIN, margin);
    BitMatrix matrix = qw.encode(msg, BarcodeFormat.QR_CODE, width, height, hints);
    Bitmap bmp = Bitmap.createBitmap(width, height, Bitmap.Config.RGB_565);
    for (int x = 0; x < width; x++) {
        for (int y = 0; y < width; y++) {
            bmp.setPixel(x, y, matrix.get(x, y) ? Color.BLACK : Color.WHITE);
        }
    }
    return bmp;
} catch (WriterException e) {
    e.printStackTrace();
}

要更改 QR 码的颜色,如果你有一个像我一样的 arraylist 存储所有 hex 字符串。您可以使用 for 循环并插入 hex 字符串。

根据代码更改颜色,

 for (int x = 0; x < width; x++) {
    for (int y = 0; y < width; y++) {
        bmp.setPixel(x, y, matrix.get(x, y) ? Color.BLACK : Color.WHITE);
    }
}

Color.Black 可以替换为 arraylist (在我的例子中,我将其替换为我的 colorArray )并且 Color.White 是背景的颜色二维码。

好吧,希望有一天能对某人有所帮助。 编码愉快.