go-qrcode
go-qrcode copied to clipboard
Feature(image-compression): PNG bit depth must be 1
The QR codes generated by https://github.com/skip2/go-qrcode are much smaller. I compared and the main difference is that bit depth is 24 while it's enough only 1 bit (black/white).
Also the PNG format is basically a gzip-ed BMP image. So we can also play with it's compression. Currently the default compression is used but it make sense to use maximum compression by default. It will make generation slightly slower but just a little bit. The images are often transmitted over internet and network bandwidth is more critical than CPU time. It would be nice to be able to generate BMP images so that they can be compressed freely by a developer with a compressor that best fits to their needs.
I just checked the skip2/go-qrcode sources and yes, the Best PNG compression is used:
encoder := png.Encoder{CompressionLevel: png.BestCompression}
I found that I can use a custom compressor but still I have a large legacy codebase to change. Will you accept a PR with changing of the compression level?
I changed code to use the best compression and for the alphanum json-like string of 641 length:
- current 1258
- with best 1215
So the diff is only 43 bytes. Not that much. Maybe for larger strings it will be more saving but larger strings are highly unlikely.
Looks like in fact we can do opposite and use no compression. I tried and result is 12813 bytes e.g. about 10 times more. So just a normal compression level looks a good enough.
Meanwhile the skip2/go-qrcode generated a qr code of only... 641 bytes. So maybe the main reason is the bit depth and compression may be not needed.
I created a Gist to compare https://gist.github.com/stokito/4285f23844c8c51eb4f41adcc374af26
That's the weakness of this project since I didn't think about image compression in this library. I feel grateful for your suggestion, and it's a little time-consuming for me to apply compression tech in code, I'm not familiar with this technology, so you could not see the effect in time, also you can create any pull request to speed the progress. you seem to be good at this, hah~
I got that since I used github.com/fogleman/gg
to enhance the image output function, but it's using *image.RGBA
which uses color.RGBA
32bit however skip2 is using image.Paletted
and color.Gray16
16bit to represent colors.
- https://github.com/fogleman/gg/blob/8febc0f526adecda6f8ae80f3869b7cd77e52984/context.go#L60
- https://github.com/skip2/go-qrcode/blob/da1b6568686e89143e94f980a98bc2dbd5537f13/qrcode.go#L308-L310
- https://github.com/golang/go/blob/19309779ac5e2f5a2fd3cbb34421dafb2855ac21/src/image/image.go#L1134-L1145
Interesting. I don't know how it must be implemented properly. You see, there is also a support of built-in images which makes all more complicated
The most feasible way to achieve your purpose is to implement another writer that output image in skip2's
way. Actually, this is also the greatest purpose why I refactored this repository into v2. At the same time, I'm sorry about I can't change the standard
writer because it's designed to support the powerful shape of QR Code, although we can hack in ImageEncoder
progress to compress the output images, it's an ugly code, doesn't it?
Well, according to a test from my gist the difference is at least twice smaller image. For me me it seems like something that is highly good thing to improve
Yup, I'll try to implement another simple writer to test whether we can generate a smaller image. plz stay focused on this issue, I'll update here if I get any progress.
Hi, thank you I tried it and results are impressive. On my data set the resulted file 1.4Kb instead of current 37kb. That means that I can now just store it in DB and return in JSON field base64 encoded. Because now I have to upload the QR code image to AWS S3.
Here I created a benchmark to comapare https://github.com/stokito/go-qrcode-libs-compare
Content length: 274
qr-yeqown-none.png: 300085
qr-yeqown-speed.png: 5459
qr-yeqown.png: 3820
qr-yeqown-best.png: 3524
qr-yeqown-current.jpeg: 37153
qr-yeqown-v2.jpg: 35978
qr-yeqown-v2.png: 3846
qr-yeqown-v2-compressed.png: 1491
qr-yeqown-v2-compressed-1px.png: 1000
qr-skip2-best-1px.png: 1003
qr-skip2-best-1px-alphanum.png: 849
The most confusing thing is that the qr-yeqown-v2-compressed-1px.png
image is exactly pixel by pixel the same as generated qr-yeqown-v2-compressed-1px.png
but their size is still differs.
I don't know what why they differs but this is interesting.
Thank you!