heuer / segno

Python QR Code and Micro QR Code encoder
https://pypi.org/project/segno/
BSD 3-Clause "New" or "Revised" License
606 stars 52 forks source link

How can I encode non-unicode binary data #109

Closed nanikamado closed 2 years ago

nanikamado commented 2 years ago

Encoding bytes into a QR code and decoding it produces data that is different from the original one.

code:

import segno
from pyzbar.pyzbar import decode, ZBarSymbol
from PIL import Image

byte = b'\xb8\xd6\x90\xaf'

print(byte) # --> b'\xb8\xd6\x90\xaf'

qrcode = segno.make(byte, micro=False, mode='byte')

qrcode.save('test.png', scale=10)

ds = decode(Image.open("test.png"), symbols=[ZBarSymbol.QRCODE])

print(ds[0].data) # --> b'\xef\xbd\xb8\xef\xbe\x96\xe6\x98\x9f'
heuer commented 2 years ago

Thanks for your issue. I think it's an issue how zbar tries to interpret the data. I added a test case for it. The trick is to decode the data from UTF-8 and to encode the data Shift-JIS. Then the you'll get the expected result.

It's written a bit different to avoid the Pillow dependency, though. https://github.com/heuer/segno/commit/11062bf76ebe999aafedb47f88431e71631bb82b

nanikamado commented 2 years ago

You are right, this seems to be a problem with zbar. I tried rqrr, a QR reader written in Rust, and it decoded the test.png to the original data correctly.

code:

use image;
use rqrr;

fn main() {
    let img = image::open("test.png").unwrap().to_luma8();
    let mut img = rqrr::PreparedImage::prepare(img);
    let grids = img.detect_grids();
    let mut content = Vec::new();
    grids[0].decode_to(&mut content).unwrap();
    println!("{:x?}", content); // --> [b8, d6, 90, af]
}

Thank you.