Reverse engineering of mixed tiles of QR code

人盡茶涼 提交于 2019-12-04 18:37:45

The task ahead is a special case of a general mathematical field, combinatorics. (Sorry, I'm not a native English speaker, and I'm not a mathematician either. So I'm not sure if this is the correct English technical term for the field.)

Combinatorics has a few generally proofed rules about how many combinations/orders of N distinct objects are possible if there are N slots for the objects and each object must be placed into one slot at a time.

Take the most simple example first: 1 element, 1 slot. There is only one option.

Next, two elements: a + b, and two slots: 1 + 2. There are two options:

  1. a,b
  2. b,a.

Three elements: a + b + c, and three slots: 1 + 2 + 3. There are now six options:

  1. a,b,c
  2. a,c,b
  3. b,a,c
  4. b,c,a
  5. c,a,b
  6. c,b,a.

This general rule (which can easily be proven by applying the generic mathematical proof method of complete induction) is:

"For N elements, there are N! different arrangements."

where N! denotes the factorial of N, meaning to be the product of all positive integers less than or equal to N. For example:

5! = 5 * 4 * 3 * 2 * 1 = 120

As you can see the factorial function is growing rather fast... :-)

Your general requirement is equivalent to put 22 tiles into 22 positions. A quick -- har!,har! :) -- calculation shows that

22! = 1.124.000.727.777.607.680.000

22! is (coincidentally!) 22 digits long. It also contains 4 trailing zeroes (which constitute 18.18% of the whole number).

So I propose some job sharing between us:

  1. Your part is this: please start to generate or write the "textfile with all the combinations" you suggested in your question.
  2. My part: I will, by the time you're done with it, be able to provide you a simple shell script to generate all the QR codes you are looking at.

But before you start to write your textfile with all the combinations, please consider this:

  1. My script will read the text file as input line by line.
  2. Each line will run trigger 1 ImageMagick command to generate the appropriate QR code image.
  3. So you need to provide a text file that holds 1.124.000.727.777.607.680.000 different lines.
  4. Since all your text file's lines need to be different from each other (otherwise they'll represent dublettes of two or more combinations), they need a minimum of 23 bytes (22 bytes to name the 22 different tile names -- you can be lazy and name them as single letters -- plus an EOL/CR/NL character).
  5. Hence, your text file size is a minimum of 2.4728016 * 1022 Bytes long.
  6. So make sure, before you start writing the file, that your computer has enough hard disk space to hold that file.
  7. The disk needs to be able to hold 23 billion of TeraBytes (for your text file alone)! That is 23 ZetaBytes (How much storage, again, is the NSA creating for itself in its new data center in Bluffdale?)
  8. Oh, and while you're at it, when shopping for large harddisks: maybe you can also consider the space that we'll need for all the QR code images which my ImageMagick script will generate...

I guess you have already a strategy how to select the one (or the few) correct sample(s) out of the totality of eventually re-stitched together QR code you are looking for.


Update

I do not want to be totally mean to you. :-)

Maybe you have some other means to reduce the number of 22 "uncertain" tiles... In that case the following hints will help you to arrange all 25 tiles as a 5x5 grid into one image.

Create a 5x5 montage of 25 different images

ImageMagick has the montage command. This allows you to stitch together different images into lines, columns or grids as one single image.

  1. Create 25 different images first.
    (These will represent 25 different values of gray, as 100x100 pixels of gray patches.)

     for i in $(seq -w 1 25); do
       saturation="$(( $(echo x${i} | sed 's#x0*##') * 10 ))"
       color="srgb(${saturation},${saturation},${saturation})"
    
       convert          \
         -size 100x100  \
          xc:"${color}" \
          graypatch_${i}.png
      done
    
  2. Tile these 25 images into two different grids.
    (The first grid will be ordered along the gray values, the second one will be random.)

     montage            \
       -geometry +1+1   \
        graypatch_*.png \
        grid1.png
    
     montage            \
       -geometry +1+1   \
        $(ls -1 graypatch_*.png | sort -R) \
        grid2.png
    

The -geometry +1+1 parameters are not really required. I only put them in in order to get the small white space into the grid...

The first montage command uses the 25 gray patches as input in the order the shell expands the * wildcard. This order will be alphabetical. Alphabetical order will at the same time match an order of increasing darkness of the gray value, due to the algorithm I chose for the creation of the original 25 patches.

This is the resulting grid1.png:

The first grid is indeed ordered according to the "25 Shades of Grey" (heh,heh!).

This is the resulting grid2.png:

The trick here was to use sort -R. (Note, that the -R for random sorting is only for GNU sort.)

Putting 3 patches into a fixed positions (NW, NE and SW corners)

As the previous examples demonstrate:

  1. If you have 25 images, montage will automatically create a 5x5 grid.
  2. The individual images will be positioned in the order they appear on the command line: left-to-right first, then top-to-bottom.

Assuming, you name the 3 tiles with fixed positions as:

  • 1.jpg, 2.jpg and 3.jpg

Assuming, you name the 22 tiles with "uncertain" positions as:

  • {a,b,c,d,e,f,g,...u,v,w}.jpg

Then:

  1. To position 1.jpg into the NW corner, put it as the first image on the command line.
  2. To position 2.jpg into the NE corner, put it as the fifth image on the command line.
  3. To position 1.jpg into the SW corner, put it as the twentyfirst image on the command line.

The rest of your 22 JPEGs you can place into the other positions as you like.

But remember: you have 1.124.000.727.777.607.680.000 different choices for these... :-)


Update 2

The OP has added some more info (though not all that was requested):

  • Each individual tile has 94x94 pixels.
  • The complete QR-Code has 470x470 pixels.

His idea to *"solve it as all puzzles are solved: print out, cut manually to 25 tiles, and combine it" does not look too promising to me...

However, here is some structural information which may help to fix a few of the 22 undetermined tiles into a specific location (or rule them out for other places when puzzling). It is a 45x45 QR code example (originally provided on Wikipedia as "QR Code Structure Example 3" by Bobmath - Licensed under Creative Commons Attribution-Share Alike 3.0):

Maybe the OP has a chance to put correct and/or plausible version and format information patterns in place, as well as alignment and timing patterns (on top of the 3 position patterns he already knows)...

The most promising strategy to me seems go forward in the following order:

  1. Identify these six tiles which contain the alignment patterns first
  2. Find out how many choices you have to place these two (out of the previously identified six) alignment pattern tiles which go in between the 3 position pattern tiles (remember: they need to provide a valid timing pattern too)
  3. Can you pay your hard disk storage now? :-)

Trivia fact: in a 470x470 module QR code there should appear 7 * 7 - 3 = 49 -3 = 46 alignment patterns.


Update 3

After OP provided a ZIP file with the 5 individual tiles inside, under the filenames tile_0.png, tile_1.png, ... tile_24.png, it now looks that the job is much easier than I originally reckoned. What I had not taken into account (what also was not clear from the OP's question, or what I made wrong assumptions about):

  1. The original QR code contains the full "quite zone".
  2. The 25 separated tiles are not cut sharply along the QR module borders, but right through the meat of these modules.

These two facts together make it much more easy to piece together the puzzle he posed.

To give everyone an idea of how the 25 pieces look like, I've created a grid of them, with the following characteristics:

  1. Each tile is annotated with the name of its originating file.
  2. Each tile is separated 3 pixels apart from the next rows and next columns.
  3. There is a colored background to clearly show the (white) "quiet zone" strips.

(Update -- unfortunately, the OP edited my illustration and masked 9 out of 25 tiles with a big black square, so you won't be able to see what it looked like any more. But if you are clever... :) Here is the result :

Looking at these tiles, taking into account the white "quiet zone" edge strips where they are visible, the following things can be stated right away:

Assuming each tile's orientation is still the original one...

  1. tile_24.png belongs into the top right corner of the final QR code image.
  2. tile_11.png belongs into the top left corner of the final QR code image.
  3. tile_6.png belongs into the bottom left corner of the final QR code image.
  4. tile_4.png belongs into the bottom right corner of the final QR code image.
  5. 12 tiles, tile_8.png, tile_9.png, tile_10.png, tile_13.png, tile_14.png, tile_15.png, tile_16.png, tile_17.png, tile_18.png, tile_19.png, tile_22.png and tile_23.png, due to their quiet zone edge strip belong to an edge position.
  6. There are even more restrictions (such as "tile_17.png, tile_22.png and tile_13.png belong to the top edge, with 17 probably at second position, next to 11")...
  7. ...but I won't solve the complete puzzle here.

Update 4

Hmmm... just staring at above image for about 5 minutes and taking some more notes, I came up with this:

 11  17  22  13  24
 18  21   7   2   9
 14   0  20   3  10
 15   5   1  12  23
  6  16   8  19   4

That's my last hint in this matter. :-)


I don't even know what the award is :-(     

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!