Image Grid Placement

Good morning! Before I start programming, let me check if something like this already exists - it seems so many things already do in g’mich … (which is great)

I would like to place images on fixed sized background of a specific color. There should be N columns and the images are placed left to right (tiger, face, butterfly, balloon, …). The algorithm should fit as many images in a column as there is space on the page and all columns are entered vertically. All images are the same width. If a page is full, a new one should be started.

A hint if something like this already exists would be much appreciated.

A sample page is included.

I think the key question is how to most efficiently produce the individual vertical stripes with the images. Placing them on a page seems to be simple.

foo :
  repeat 60 { sp ? } r2dx 128 to_rgb frame 2,2,255 frame 5,5,0 # Generate random color images
  W,H=600,600 # Size of pages

  # Generate photo montages.
  for $ind<$!
    for $go_on" && "$x+w#$ind<$W {
      for $y+h#$ind<$H { y,ind+=h#$ind,1 if $ind>=$! go_on=0 break fi }
      a[$indy-{$ind-1}] y
    a[$indx-{$ind-1}] x,0.5
  r $W,$H,1,100%,0,0,0.5,0.5

1 Like



I really like this filter which is fast and easy to use.
It might be good to add it to existing mounting filters.

Merci :o)


I am stunned … to do the same in PHP for my website, it took way more lines. Probably will add to limit the maximum height of an image and align it right when it is on the most left column. Left when it is in the most right and center when it is in-between.
Thanks @David_Tschumperle for the script! It will be used to fully do my annual picture book!


I have used the command this morning and just realised, that the algorithm provided places images top down in the first column, them in the second, … till the page is filled. What I actually need is the same layout but the first image should be on the top of the first column, the next one on the top of the second, the third on top of the third column, … once all columns have one picture, the next image goes below the first image on the first column, … this makes it a bit a more natural flow when looking at the pictures (the eye goes left to right=
Of course, I could just swap the both axes of the existing algorithm, but that would give me equal hight per row… and I guess it looks better with equal width as it is above.
Having said that, I would like to thank @David_Tschumperle for the code provided, I have learned quite few things.

Maybe you can try to use name and sort_list to reorder your images as you need them before calling the command?

foo : 
  repeat 60 { sp ? } r2dx 128 to_rgb frame 2,2,255 frame 5,5,0 # Generate random color images with same width
  foreach { to $>,0.5~,0.5~,48,2,1,255 }

  N=$! # Number of input images
  W,H=600,600 # Size of pages
  nb_cols:=floor($W/w#0) # Max number of columns on each page

  # Generate photo montage.
  for $ind<$N {
    repeat $nb_cols { y$>,col$>,sep$>=0,, }
      repeat $nb_cols {
        if ${y$>}+h#$ind<$H
          col$>.=${sep$>}$ind sep$>=,
    while $go_on
    repeat $nb_cols { +a[${col$>}] y }
    a[-$nb_cols--1] x,0.5 => page$page page+=1

  k[$N--1] r $W,$H,1,100%,0,0,0.5,0.5

The arrangement algorithm is then a bit different here, as it may happen that one column can be full but the others can be still being filled with new pictures.

1 Like

Thanks, @prawnsushi - that would not work as you don’t know upfront where a photo would have to end up. @David_Tschumperle has commented it in his last post.

Hello @David_Tschumperle … Now, this is really cool. Thanks so much for your time and effort!

It’s ok, I know he has all the answers and more :wink:
Vers l'infini et au-delà !

One final comment… it worked well for about 200 images, then I got killed with the comment gmic evi1/*.jpg evi2/*.jpg evi3/*.jpg… probably ran out or memory.

My French is rusty… was in France for language training in 2001… but could manage the translation “to infinity and beyond”. Reminds me of Latin… “et si ones non, David facit”.

Indeed, I’ve implemented the script as a filter working on pre-loaded images, as G’MIC commands are mostly done.
It’s easy to transform this command to make it “streamable”, and manage a large number of images.

# Arguments : list of files or file pattern
foo :
  image_width=128 # Width of images
  page_width,page_height=600,600 # Size of pages
  out_filename=page.png # Output filename for pages

  # Retrieve list of image files.
  $=arg repeat $# { files 3,${arg{$>+1}} files.=$sep${} sep=, }
  nb_images:=narg($files) # Number of input images
  nb_cols:=floor($page_width/$image_width) # Max number of columns on each page

  # Generate photo montage.
  for $ind<$nb_images {
    i[0] 0x$nb_cols
      if $!==$nb_cols # Read new image
        arg0 $ind,$files ${}
        r2dx. $image_width frame. 3,3,255 frame. 3,3,0 to_rgb.
      if {$col,h}+h<$page_height a[$col,-1] y ind+=1 nb_attempts:=$ind<$nb_images?0:$nb_cols
      else nb_attempts+=1
    while $nb_attempts<$nb_cols
    a[0-{$nb_cols-1}] x,0.5 r[0] $page_width,$page_height,1,100%,0,0,0.5,0.5
    filename $out_filename,$page
    e "  - Output: "${}
    o[0] ${}
    rm[0] page+=1

In the command above, all is streamed (input and output).

This perfect, @David_Tschumperle, so, thanks a lot.

1 Like