Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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

Has anyone heard of this before ? Extract the QR Codes (all the QR Codes must be in same Width and Height {square}) and get the data from each QR Code, and combine them. Then get the every pixel value from each QR Code and change them to hexadecimal. You will give #FFFFFFFF, #FF000000, #00000000 (white,black, transparent) and the like (but for black and white QR Code, it would only 2 of them). Then for each value from each QR Code, by creating a new colour QR Code which the colour is according to the value from each hexadecimal and the content of the new colour QR Code will have the content that was extracted from the previous QR Codes.

For example, what I am doing now is extract 8 numbers of QR Code and combine the content, then create a new colour QR Code.

By now, I am stuck in the middle of the process. I have successfully extracted the content and the pixel of each QR Code by changing the value to hexadecimal. the problem is how can I can change the hexadecimal value from each QR code to ARGB (alpha, Red, Green, Blue) colour and create a new colour QR Code.

However, I have tip from Google, some say MatrixToImageWriter would be useful. But there is not really much work there that is similar and useful to me. Well, I need some help here. However, I am not sure whether it will be useful for me or not.

PS: I can attach my work here if someone want to.

PSS: I am using the Zxing library to scan and get the result from each QR Code.

like image 636
Kopi Bryant Avatar asked Mar 04 '19 07:03

Kopi Bryant


People also ask

Can you combine 2 QR Codes?

All in one QR code refers to adding multiple links using one QR code. This type of solution is called the Multi-URL QR code. Multi-URL QR has four types of features such as Multi-URL QR code for location, time redirection, amount of scans and language redirection.


2 Answers

I've just wrote the desired decode/encode methods; the matrix look different because I've created the input QR code with the QR Droid application and the output QR code with ZXing, which might use a different level of error correction; nevertheless both have the same destination URL, which is mine.

The dependencies originate from repositories google() and 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"
}

The layout resource used:

<?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>

And the manipulation of the BitMatrix; where the encode() method should suffice, when having the String available; just added both methods for the sake of a complete example (it reads the Bitmap from one AppCompatImageView and then writes to another one 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;
    }
}

The result looks alike this; where the left one is the input matrix and the right one is the output matrix:

QR Codes, Input & Output Matrix

like image 71
Martin Zeitler Avatar answered Nov 12 '22 13:11

Martin Zeitler


Well, after few days of digging from the Internet. I have found the solution and I think it would help someone else someday.

 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();
}

To change the color of the QR Code and if you have an arraylist like mine that store all the hex String. You can using for loops and to insert the hex String.

For changing the color, based on the code,

 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);
    }
}

The Color.Black can be replace with the arraylist (in my case, I replace it with my colorArray) and Color.White is the color for the background of a QR Code.

Well, hope it helps someone somedays. Happy coding.

like image 30
Kopi Bryant Avatar answered Nov 12 '22 13:11

Kopi Bryant