imageMagick: hexagonal tiling of many different images (having the same size)

160 Views Asked by At

I have many different PNG images all with the same size (142x163). These are badges for students. You can see three examples below, but there are more of them. I would like to create a single large image where all individual badges are arranged in a hexagonal grid to maximize the printed area. I just need to leave a little space between them to cut them out safely.

I'm wondering what the best way is to go about this.

I have a list of how many badges of each kind I need to print, and I can write code to specify the position (offset) of each individual badge in the hexagonal grid. However, I'm not sure about the correct way to feed this information into a script for ImageMagick to execute.

I guess I need something like: create an image placing badge1.png at position 1, badge2.png at position 2, badge3.png at position 3, badge3.png at position 4, and so on. This could go on for a bit, with 50 to 100 badges (I'm thinking of filling an A3 sheet with 3cm x 3cm badges).

What would the correct syntax be? Would ImageMagick handle this?

Thanks a lot for any insight.

Francesco

[![badge1][1]][1]
[![badge2][2]][2]
[![badge3][3]][3]

badge1 badge2 badge3

EDIT: as required, I'm attaching the script I'm currently using:

magick -background none \
\( ph4campoBstatico.png ph5EqMaxOndeEM.png MMprodVett.png ph4UeV_elettrici.png +smush 8 +repage -set page +0+0 \) \
\( MMsimboli.png ph3dinamicaSNI.png ph1prefissi.png ph1calibroVentesimale.png +smush 8 +repage -set page +76+130 \) \
-layers merge +repage \
-background white -flatten \
result.png

This command works, but it converts an entire "row" to grayscale whenever the first image is grayscale (see output below).

Since the number of files involved is much larger than 8, I tried to write this command in a file "script" and run it as magick -script script. What I find is that I have to prepend -write to the filename. Also, it seems to me that the backslashes at the end of each line are unimportant in the file.

The output of the command is

result.png

Only the first image in the second row should be black and white. The others should be in color. Colors are "removed" from a row only when the first image is grayscale.

5

There are 5 best solutions below

1
fmw42 On BEST ANSWER

Try adding -colorspace sRGB or -type truecolor after reading the images in Imagemagick. Also prepend PNG24: to the output filename if the previous does not work by itself but only for PNG output.

magick -background none \
\( ph4campoBstatico.png ph5EqMaxOndeEM.png MMprodVett.png ph4UeV_elettrici.png -colorspace sRGB +smush 8 +repage -set page +0+0 \) \
\( MMsimboli.png ph3dinamicaSNI.png ph1prefissi.png ph1calibroVentesimale.png -colorspace sRGB +smush 8 +repage -set page +76+130 \) \
-layers merge +repage \
-background white -flatten \
PNG24:result.png
0
PFB On

I think I found a way to achieve what I want. I'm not sure it's the best way, though.

So, inspired by this post, I wrote a script hexScript like this

#!/path/to/magick -script
-define png:color-type=6
( MMderivate.png -repage +0+0 )
( MMderivate.png -repage +150+0 )
( MMderivate.png -repage +300+0 )
( MMsimboli.png -repage +75+130 )
( MMsimboli.png -repage +225+130 )
( MMpercentuali.png -repage +375+130 )
-layers merge -write out.png

which i can run with magick -script hexScript. The output is pretty much what I'm looking for (see below).

Of course, in my case the number of lines like ( file.png -repage +X+Y ) is going to be way larger than six, but I think imagemagick can handle that (the OP in this post talks about thousands of images).

Now I just have to write a code that automatically produces the script I need, based on the information of how many badges of each kind I need.

Any insight for improving this approach is welcome.

Thanks a lot

Francesco

result

9
fmw42 On

Here is an alternate way to do that in Imagemagick. Use smush X to create each row. Smush X is like append with an offset. Then use one -page +X+Y to set the spacing between the two rows. And finally use -layers merge to combine according to the -page offsets. Then flatten over the desired background color or leave as transparent background.

magick -background none \
\( img1.png img2.png img3.png +smush 4 +repage \) \
\( img3.png img1.png img2.png +smush 4 +repage -set page +72+126 \) \
-layers merge +repage \
-background white -flatten \
result.png

enter image description here

magick -background none \
\( img1.png img2.png img3.png +smush 4 +repage \) \
\( img3.png img1.png +smush 4 -set page +72+126 \) \
-layers merge +repage \
-background white -flatten \
result2.png

enter image description here

3
GeeMack On

Given a number of images with the same dimensions, named "tile-*.png", and with transparent backgrounds, you can use ImageMagick v7 to arrange them into a hexagon-oriented grid with a Windows command like the one below...

First, this command draws a hexagon on a 200x200 tile, duplicates it to make several more, 35 in this example, to simulate a bunch of tiles to arrange...

magick -size 200x200 -background none -fill none ^
   -strokewidth 4 -stroke black xc:none ^
   -draw "polygon 22,54 100,10 178,54 178,146 100,190 22,146" ^
   -duplicate 34 tile-%02d.png

enter image description here

This next command will read in all the tiles created by the above command, and arrange them into a grid of a specified number of units wide...

set COLS=5

magick tile-*.png ^
   -background none ^
   -gravity center ^
   -extent %[h]x%[h] ^
   +gravity ^
   +append ^
   +repage ^
   -crop %[fx:%COLS%*h]x%[h] ^
   -splice %[fx:(t%2)*h/2]x0 ^
   -set page +0+%[fx:t*h*0.866] ^
   -layers merge ^
      result.png

That sets the number of columns you want as a Windows variable %COLS%.

Then the ImageMagick command reads in all the images named "tile-*.png" and makes sure they're centered in square tiles.

It appends them all horizontally, crops that into the number of rows required to make the grid, and adjusts the spacing on the ends of the rows.

Next it sets the page geometry on all these horizontal strips of images, in essence moving each one "h*0.866" farther down the page than the previous.

With all the geometry set, the "-layers merge" operation flattens them into the finished grid.

enter image description here

Edisted to add: I'm not able to translate this into a *nix command right now, but converting the carets "^" to backslashes "\" and fixing the syntax on that shell variable should get you most of the way.

3
fmw42 On

This should be the Unix equivalent of GeeMack's solution for Imagemagick

COLS=5

magick tile-*.png \
   -background none \
   -gravity center \
   -extent "%wx%w" \
   +gravity \
   +append \
   +repage \
   -crop "%[fx:$COLS*h]x%h" \
   -splice "%[fx:(t%2)*h/2]x0" \
   -set page "+0+%[fx:t*h*0.866]" \
   -layers merge +repage \
      result.png