BetterQR
- 20 Devlogs
- 49 Total hours
A QR code package for python with improved features.
A QR code package for python with improved features.
This will be my last patch of the day.
This isnt fully fixed, Im having some hard time figuring out whats the main core issue. It is somewhat fixed.
Ran more tests and got feedback from ~15 people. Made them test the commands and try to find bugs. There were many bugs people were available to find. This is session focuses on fixing some of them
encoder.py, the capacity check treats every Micro QR data codeword as a full 8 bits — but for M1 and M3 symbols, the last data codeword is only a 4-bit nibble per spec. The checker accepts data that’s 4 bits too big, and the extra bits get silently truncated at render time..logo() crashes every time: core.py builds a logo_info dict with a key "padding", but matrix.py leads logo_info["padding_px"] , instant KeyError the moment anyone calls .logo(...).
--terminal-style compact output has padding bugs asymmetric left/right padding and a stray extra row, so piping it anywhere that cares about exact dimensions breaks.There are some more bugs that will be fixed in the next session.
The 9 hours was logged in span of the last week. Didn`t get to devlog due to internet outage here in Sri Lanka.
_hex_to_rgb 3-char hex crash:#000, #FFF, #F00 etc. caused invalid literal for int() with base 16: ''. Added expansion of 3-char to 6-char before parsinglogo() crash: 'QR' object has no attribute '_version_size'``logo() tried to compute size_px = int(self._version_size * ratio) but _version_size doesn’t exist on the QR object at call time (the matrix hasn’t been built yet). Fixed to compute size_px lazily inside _get_logo_info() from module_count × box_size × ratio.logo(border=True) crash: invalid literal for int() with base 16: 'Tr'The _logo_border attribute stores a bool, but was passed directly as border_color to embed_image() which called _hex_to_rgb(True) → _hex_to_rgb("True") → crash. Fixed to pass "#000000" if self._logo_border else None.
image_ops.py + animation.py — _hex_to_rgb None guardif not c: return (0, 0, 0) guard so passing None as a color never crashes._color() validator didn’t strip surrounding shell-added quotes from color strings like “#FF0000”, causing # to be split off the hex digits. Fixed to strip " and ' before processing.logo() parameter docs (border is bool, not int)- Fixed double ```bash` in installation sectionREADME.md and DOCUMENTATION.md- Made a landing site with help of Claude.Bug hunting has started. I have been looking for any bugs in the hidden corners and have found many of them. Like the embedded logo QR codes throw an error , microQR m4 type just crashes everything,etc. I also have used the library in actual code to test as well.
Used my front-end skills to to the best and locked in and designed a good looking website for BetterQR. Looks fine for now. Will do some changes later. Made it a single page website cause easier load for Github Pages.
(v2 is not out, expect it earlier this week)
I initially planned to release this today, but realized something. The embedded logo thing and microqr is now failing on me. and Im lazy to fix this now so I’ll be fixingit tomorrow.
So I thought why not make a website. So Im have been working on a small landing website with vanilla html and probably host it on GitHub Pages as well.
Doing stuff related to publishing the new version. Im noy going to be going in details cause Im at school 
I have ran multiple CI/CD tests and have noted that most animations and data type qr codes fail. I think its mostly from wrong placements.
data -> output when a helper flag is active.sms: not smsto:._write_format_info function bugsThe _write_format_info function as two major bugs.
bit_idx=i in write_bit (which applies 14-i) but should write (fmt >> i) & 1 (vbit). The bit indices are swapped.size-8) ad uses wrong bit indices.These are only like 1/4 of the bugs. These were the easiest to document so listed them here.
After running the new CI/CD Tests most pass but some fail. I traced back the issues and fixed half of them.
1, Micro QR auto-version: _min_version doesn’t enforce mode compatibility (M1=numeric only, M2=no byte, etc.) and uses wrong mode-indicator bit count in the needed formula.
2. WiFi/Geo/SMS/Phone/Email/VCard: The helper objects need to be passed as str() to QR() — the test is likely calling them directly. The __str__ methods need to produce correct strings, and some may have format issues.
3. Animations: GIF decode — need to verify each frame.
4. small_border: border=1 means only 4px quiet zone which may confuse decoders.
(i have been fixing them but not produce a result yet)
Writing the test scripts from scratch cause the last CI/CD pipelines are kind of glitched. Used claude a little this time to structure it.
Trying to fix some bugs, scrolling through stack overlay rn (yes stack overflow and not ai, IM NOT A BOOMER trust)
I have identified all of the bugs (hopefully) and marked everything that has to be fixed.
build_matrix writes all bits including the full 8-bit last data CW, then starts ECC. For M1/M3, the correct order is: 10 data CW (80 bits) + 4-bit partial + 6 ECC CW (48 bits). The current code writes all 17 CW as bits sequentially which gives the WRONG bit order.So I fixed the bit placement in build_matrix for M1/M3encode_data to use zero padding for Micro QR and handle the M1/M3 last-4-bit rule.fix _apply_mask to use Micro QR mask conditions (indices 1,4,6,7 of standard) for micro QR, and add a separate _MICRO_MASK_CONDITIONS list._min_version capacity checker, which has the same wrong cc_bits valuesAs my last devlog I identified that there is some errors in matrix and table files. I started looking through the table data and found some errors.
bs.append(mode, 4) — always writes a 4-bit mode indicator. But for Micro QR, mode indicators are 1–4 bits depending on the version, not always 4 bitsThe _data_placement_order function skips col 6 (standard QR timing column). For Micro QR, col 0 is the timing column that should be skipped. But since col 0 and row 0 are already marked as reserved via timing pattern placement, the if not reserved[row][c] check already handles it. The col == 6 skip is only needed because in standard QR col 6 is a function column that isn’t individually reserved — but since we now properly reserve col 0 for Micro QR, it’s already handled. The issue is the function always skips col 6, which in Micro QR is a valid data column.M1-M3 silently get clobbered by M4’s values.I’m still going through the code to find the errors first, Then I’ll start to fix them one-by-one cause I’m tired of fixing one and get another 2 bugs out of nowhere.
After introducing CI/CD Integrations and Test Scripts I have noticed all the generated QR codes fail or unreadable. Im currently tracking the issue behind this. And the main assumption is to something with the src/matrix.py or src/tables.py cause thats the main logic behind the validity. So im curretly digging through the code to find the bugs. I have fixed some of them but when i fix one bug two bug appears. 😭
Implemented few tests that gets triggered during a push / pull request that tests if the generated QR codes are valid and working as intented. Results are sent to a private discord server via a webhook.
Working on making the generated QR Codes fully compliant with the ISO Standards.
(attached is a fail qr code LOL)
I have successfully released the first version of it. So I have been working on adding some more features for the next version.
This is one of the most requested feature here. It is little tricky to make it work. But most logic for this has been programmed.
Drastically reduced SVG file size by merging modules into a single element.
Added HMAC-SHA256 signing and bitwise XOR obfuscation to protect sensitive QR data.
Automatically detects low contrast between foreground and background. Includes auto_fix_contrast to force scannable colors.
I did my first beta release to PyPI and tested out. It worked pretty well. Got some suggestions from Reddit as well.
Wrote the entire documentation , reamd.md , changelog and contribution.md to improve the repo.
Release the first official version with some improvements.
Currently working on adding microQR codes and security warnings for Crypto qr codes
First version release on pypi, run pip install betterqr to install. Gotta work on the readme and website now
Completed the base qr engine finally after hours of coding and debugging. Now it can generate basic qr codes with texts and links.
Currently worked on the QR code engine that generates the QR code. Also did some CLI work to make it work. Created some GH workflows as well
Currently writing the core for the package. I have added the basic starter classes like the Wifi QR and contact QR