DEV Community

Cover image for Let's develop a QR Code Generator, part VI: mask optimization

Let's develop a QR Code Generator, part VI: mask optimization

Massimo Artizzu on August 19, 2021

In part 5 we've created our first QR Code. Our code is not complete, but rather it's specific to our case (version 2, byte mode) and we've applied ...
Collapse
 
bpeel profile image
Neil Roberts

Presumably rule 3 is to try to remove patterns in the QR code that might look like the finder pattern. Ie, if you take a 1-pixel-high cross section of the finder pattern it will look like 1011101. Note that in the spec it talks about ratios, not the actual pattern. So presumably you are also supposed to check for 11001111110011 and so on. For example there could be a huge scaled-up finder pattern in the middle of the QR code that would confuse the reader, but this rule would penalize that.

It’s not totally clear to me from the spec whether the quiet zone around the QR code is supposed to count towards the 4 modules of white space, but I think it would make a lot of sense if it did.

Collapse
 
latestversion profile image

Oh and btw, yes, rule 3 iseems very much to be there to prevent finder pattern-like constructs. Section 7.8.1: "The module pattern 1011101 particularly found in the finder pattern should be avoided in other areas of the symbol as much as possible."

Collapse
 
maxart2501 profile image
Massimo Artizzu

Good catch! I've updated the article accordingly.

Collapse
 
latestversion profile image

Your reflection on ratios is very interesting. Given how that wording stands out compared to the rest of the formulations in the standard, I think you are right.

Interestingly, the author of Project Nayuki (nayuki.io/page/creating-a-qr-code-...) has taken the approach of including the quiet zone in the evaluation. It makes sense, as you say, but at the same time I think it would have been mentioned in the standard if it was deemed necessary. While things still pop up that I have missed, I have not yet seen anything hinting towards including the quiet zones being necessary.

Overall, I think the standard is too vague on a range of issues.

ETA: Although I think excluding quiet zones is totally justified as the standard to my knowledge never mentions them in regards to masking.

Collapse
 
maxart2501 profile image
Massimo Artizzu • Edited

I didn't consider the quiet zone as part of the field to search for pattern, since it would produce 18 matches out of the box for any QR code, because of the finder patterns. Also because the quiet zone is there just to make it easier for reader to identify a QR code, nothing more. It delivers no information, and while it's specified that it should be 4 modules wide at least, common readers are fine with narrower borders.

But it might actually create legit matches of the pattern, soooo... Unclear? Fortunately it's all for just an optimization and doesn't affect the correctness of the resulting matrix.

Edit: thinking about it again, that specific sequence would actually match the middle part of the finder patterns including the quiet zone, and we don't want to find it in other parts. If that's the point, we don't want it to be anywhere in the final result except for the finder patterns, and that would actually include the quiet zone.

So, in the end, I think this article and the corresponding code need to be amended for that part.

Collapse
 
latestversion profile image

It is unclear whether we should include the format (and version) information before we do the mask evaluations or not.

What speaks for it is of course that it makes sense to reduce unwanted patterns rising from the combination of format version bits and data/ECC bit.

On the other hand, section 7.1, in the description of steps 6 and 7, makes it clear that the format and version info should be generated after a mask has been selected.

Further, section 7.7.2 says that "Modules positions for the format information and version information shall be left temporarily blank" (when placing the functional patterns). The unmasked symbol in Figure 23 (as an example of masking) is also without format information.

There is also no mentioning of how to place the format information in between the section on data placement and masking. The specifics regarding format information comes after masking.

All in all, I (currently, ha!) believe the format information can (should) be placed after mask evaluation.

Collapse
 
darius profile image
Darius B.-O.

One question regarding rule 3:
Does'nt Row 2 Coloumn 14 - 24 (counting from 0) contain the reverse pattern? (green box)

Image description

I wrote my own code for this Rule in Java and it found a total of 4 patterns including the 3 from your example. And when checking manually the area on the QR-code seems to fit the reverse pattern.
Or did I miss something like that we are only checking for either for the normal XOR the reversed pattern?

Collapse
 
_1253ace9f95284d5de033 profile image
龔宏裕

I think this is because the code in the tutorial has a bug. The upperbound of columnIndex and rowIndex :

for (let columnIndex = 0; columnIndex < size - 11; columnIndex++) {
    /* ... */
}
  // Checking the columns...
  for (let rowIndex = 0; rowIndex < size - 11; rowIndex++) {
   /* ... */
}
Enter fullscreen mode Exit fullscreen mode

By example of version = 2, i.e. size = 25, the columnIndex loops from 0 to 13. The last 14-24 part will miss. Try changing the code to columnIndex <= size -11 or columnIndex < size - 10, and rowIndex as well.

After adjustment the penalty score will be 580, 535, 415, 615, 677, 579, 512, 819.

Collapse
 
maxart2501 profile image
Massimo Artizzu

The code definitely has bugs. I hope I'll fine the patience to come back and fix everything.
Another problem is surely cause by my (probably) incorrect interpretation of the role of the "quiet zone", so there's also that.

Collapse
 
latestversion profile image
latestversion

Skipping column 6 (the vertical timing pattern) prodcues the same result as the example in the standard, but to be honest I can't really justify it from the rules in the standard. Apparently the standard author has taken the same approach, but I don't understand which rule that specifies that behaviour. In my view, we could as well have a single file going downwards the side of the vertical timing pattern. Just like we can have single files going up (only up?) an alignment pattern. Very frustrating.

Collapse
 
bouiboui_lebarde_51a31ec profile image
Bouiboui LE BARDE

I've done a python code by myself, and apparently, the mask 1 contains 3 paterns that follow rule 3, (I found a Final Penalty Score of 535 instead of 495). I wanted to know if that was right or not because if it is definitely 535 I will have to recode a little bit. Thanks !