Expand a stack of files to equal size

Questions and postings pertaining to the usage of ImageMagick regardless of the interface. This includes the command-line utilities, as well as the C and C++ APIs. Usage questions are like "How do I use ImageMagick to create drop shadows?".
toolforger
Posts: 18
Joined: 2015-09-28T00:39:38-07:00
Authentication code: 1151

Expand a stack of files to equal size

Post by toolforger »

Hi all,

I have a series of images that need to be extended to identical size by adding a border to each.
My plan was to put all images into a stack, tell ImageMagick to extend them all to equal size, and store them to a new directory.
This seems possible, but whenever I try to put together the incantation, I get into a maze of tiny little options, all different but somehow never quite what I wanted.
Anybody got a hint how the basic approach should be? I'm pretty good at varying commands and options, but I'm currently at a loss where to start.
User avatar
fmw42
Posts: 25562
Joined: 2007-07-02T17:14:51-07:00
Authentication code: 1152
Location: Sunnyvale, California, USA

Re: Expand a stack of files to equal size

Post by fmw42 »

What is your IM version and platform?

What command did you try?

Do you know the size you want for all images? If so, then you could try mogrify

Create a new directory to hold the output, say test2.
Cd to the old directory, say test1 that has the images.

Code: Select all

mogrify -path path2/test2 -background somecolor -gravity center -extent WxH *
This will extend all images to size WxH and put a background around them of somecolor, whatever you use for that.

Is that what you want?

See https://www.imagemagick.org/Usage/basics/#mogrify
toolforger
Posts: 18
Joined: 2015-09-28T00:39:38-07:00
Authentication code: 1151

Re: Expand a stack of files to equal size

Post by toolforger »

fmw42 wrote: 2018-02-09T15:55:01-07:00 What is your IM version and platform?
Ubuntu 17.10, with:

Code: Select all

$ identify --version
Version: ImageMagick 6.9.7-4 Q16 x86_64 20170114 http://www.imagemagick.org
Copyright: © 1999-2017 ImageMagick Studio LLC
License: http://www.imagemagick.org/script/license.php
Features: Cipher DPC Modules OpenMP 
Delegates (built-in): bzlib djvu fftw fontconfig freetype jbig jng jpeg lcms lqr ltdl lzma openexr pangocairo png tiff wmf x xml zlib
What command did you try?
I thought compose should work (it loads an image sequence and operates on it as a unit, right?), but it does not have -layers. So on to reading the next command and the next set of options, until everything went into a haze and I really cannot say what exactly I tried.
Do you know the size you want for all images?
I need to put this into a script, and it does not know about the wanted size.
I know I could identify all images, extract the maximum width&height, and then convert every image. The -layers option told me there's a better way, I just didn't find the command which would have it - and maybe -layers doesn't really do what I want.
toolforger
Posts: 18
Joined: 2015-09-28T00:39:38-07:00
Authentication code: 1151

Re: Expand a stack of files to equal size

Post by toolforger »

The best I have been able to come up with was

Code: Select all

montage *.tif/page-0012.tif -compose -layers trim-bounds WHATNOW?
but what's the right command - montage? composite? convert?
All have -layers or -composite -layers, but I don't know how to make them write each image resp. layer to a separate file.
Oh, and which of them is the right command to use? Does it matter which?
User avatar
fmw42
Posts: 25562
Joined: 2007-07-02T17:14:51-07:00
Authentication code: 1152
Location: Sunnyvale, California, USA

Re: Expand a stack of files to equal size

Post by fmw42 »

What do you mean by a stack? ImageMagick does not use that syntax. Do you mean layers or pages of one image? You seem to want to use montage. That puts images side-by-side in a grid. Is that what you want? Can you post an example of what you want for output.

My mogrify command above takes all separate images in a folder and enlarges them with padding to the same size and puts an output for each input into a new directory.

For novices, see

http://www.imagemagick.org/discourse-se ... f=1&t=9620
http://www.imagemagick.org/script/comma ... essing.php
http://www.imagemagick.org/Usage/reference.html
http://www.imagemagick.org/Usage/
toolforger
Posts: 18
Joined: 2015-09-28T00:39:38-07:00
Authentication code: 1151

Re: Expand a stack of files to equal size

Post by toolforger »

"Stack of images" is a generic term - just a bunch of more-or-less aligned images.
In IM terms, it could be a set of images (for those commands that deal with multiple images), or with a set of layers. However, I'm still mapping my requirements to IM, so I' prefer to stick with "stack of images" so that people don't think I want layers and stop considering image sets.

I definitely do not want the images to be on a grid!
The specification is the same as in the first posting: I have a series of images that need to be extended to identical size by adding a border to each.
E.g. I have this:

Code: Select all

00.tif/page-0012.tif TIFF 2547x1490 ...
01.tif/page-0012.tif TIFF 2284x1405 ...
02.tif/page-0012.tif TIFF 2549x1532 ...
03.tif/page-0012.tif TIFF 2546x1547 ...
and I want this:

Code: Select all

00.tif/page-0012.tif TIFF 2549x1532 ...
01.tif/page-0012.tif TIFF 2549x1532 ...
02.tif/page-0012.tif TIFF 2549x1532 ...
03.tif/page-0012.tif TIFF 2549x1532 ...
i.e. all images should have the same size.
I need IM to determine the size on its own; `-layers trim-bounds` seems to do exactly that.

(Putting the images side-by-side is the exact opposite of what I want to do: The images are multiple scans of the same page, and I want to align them for denoising and despeckling. The scanning and some initial processing result in slightly different scan sizes, so I want to add a border to get them back into identical sizes.)

I took a look at the links, but they don't help me much: basic IM usage is easy enough, my problem is that among the multitude of possibile workflows that IM offers, I have been failing to find the one that covers my use case.
User avatar
fmw42
Posts: 25562
Joined: 2007-07-02T17:14:51-07:00
Authentication code: 1152
Location: Sunnyvale, California, USA

Re: Expand a stack of files to equal size

Post by fmw42 »

I am not sure I understand your stack terminology. ImageMagick does not use that terminology. So I need to understand it in ImageMagick terminology?

What is 00.tif/page-0012.tif? Is that a multipage file 00.tif and you want to use only page 12 (starting with 0 or 1 in your numbering?)

Note that -layers trim-bounds, only finds the largest dimension and sets that in the files meta data as its virtual canvas size (page geometry). It does not process the pixel data to extend its size. So you need to find the maximum size from all the images and then use that size to extend each of your images.

If you have a series of individual images of different sizes, you can find the size of the largest using:

Code: Select all

dims=$(convert your_list_of_files -layers trim-bounds -delete 1--1 -format "%P" info:)
If all the files you want to process are in one directory, you can make the list using the unix command ls. If all the files have the same naming convention, you can use wild cards

Code: Select all

dims=$(convert name* -layers trim-bounds -delete 1--1 -format "%P" info:)
You can make a list of files and save it to a text file and use that.

Code: Select all

dims=$(convert @testfile.txt -layers trim-bounds -delete 1--1 -format "%P" info:)
Once you know the size, you can use my mogrify command earlier to process them or write a script to loop over each image and extend it with the max size found from dims. Dims with be in the format WxH.

If your files are multipage files, then

Code: Select all

dims=$(convert *.tif[11] -layers trim-bounds -delete 1--1 -format "%P" info:)
where IM pages start numbering at 0. So I use 11, since that would be the 12th page relative to 0. Use 12 rather than 11, if your 12 is relative to 0

The following will process all your files and expand them filling in with black, but you lose your file names.

Code: Select all

convert *.tiff[11] -layers trim-bounds -background black -coalesce result.tiff
The result will be a multipage tiff with the images extended to the max dimensions as the pages in the file.
toolforger
Posts: 18
Joined: 2015-09-28T00:39:38-07:00
Authentication code: 1151

Re: Expand a stack of files to equal size

Post by toolforger »

What is 00.tif/page-0012.tif?
Just a normal Linux filename.
Is that a multipage file 00.tif and you want to use only page 12 (starting with 0 or 1 in your numbering?)
I have directories 00.tif...15.tif, each containing a set of files page-0000.tif...page-0088.tif.
I need to process file across directories, but that's a minor issue, I simply use *.tif/page-0012.tif (0012 is just an example, the final script will iterate over all filenames).
No multipage tiffs involved.
User avatar
fmw42
Posts: 25562
Joined: 2007-07-02T17:14:51-07:00
Authentication code: 1152
Location: Sunnyvale, California, USA

Re: Expand a stack of files to equal size

Post by fmw42 »

Strange that you use suffixes for directories. I would suggest making a list of your files and process with my layers trim-bounds. Then write a script loop over the same files to extend them using -extent WxH where WxH is the dimensions found from the trim-bounds command. You can save the dims argument and just use that with -extent $dims.
toolforger
Posts: 18
Joined: 2015-09-28T00:39:38-07:00
Authentication code: 1151

Re: Expand a stack of files to equal size

Post by toolforger »

Strange that you use suffixes for directories.
That's off-topic I fear - I have my reasons, but explaining the entire workflow is going to be just a huge distraction.
I would suggest making a list of your files and process with my layers trim-bounds. Then write a script loop over the same files to extend them using -extent WxH where WxH is the dimensions found from the trim-bounds command.
That's certainly more convenient than having to find the max of all widths and heights from `identify` output.
It's still reading each file twice, which I'd like to avoid if at all possible.

Is there no way to load all files as an image sequence, to a -layers trim-bounds on them, and then save each image to a separate file? Possibly the file they originally came from - that would be suboptimal but still more acceptable than having to read everything twice.
(The current plan is to process ca. 2.000.000 batches of 16 image files. That's why I'd like to shave off any image load that isn't strictly necessary.)

BTW "image stack" *is* official IM terminology.
See http://www.imagemagick.org/script/comma ... .php#stack .
I have to admit it's pretty vague though :-)
User avatar
fmw42
Posts: 25562
Joined: 2007-07-02T17:14:51-07:00
Authentication code: 1152
Location: Sunnyvale, California, USA

Re: Expand a stack of files to equal size

Post by fmw42 »

I guess I am not a coder to know what a stack is. But it seems to be just a sequence of images that is input the command line.

I know of no way right now to do what you want in one command. Reading the image dimensions in the command line should be quick (if you add -ping to the command line right after convert/magick), since it is just reading the headers/meta data and not the pixel data.

The reason is that mogrify needs all images in one directory. Convert/magick can handle multiple inputs from different directories but can only write one output file name. So you need to loop over each input file and write it back out to the same directory or a new directory using the same output name as the input name.

Perhaps one of the other users on this forum will know some other way that I do not see at the moment.
snibgo
Posts: 12159
Joined: 2010-01-23T23:01:33-07:00
Authentication code: 1151
Location: England, UK

Re: Expand a stack of files to equal size

Post by snibgo »

Assuming they all fit into memory, you could use "convert" or "magick": read them all in, clone them and "-layers merge" these. That gives you one image that "covers" all the inputs. Make it white or whatever colour you want. Add a NULL: image, swap the last two. Now you can "-composite" all the inputs on to that.

That gives you one image per input, but they will get numbered names unless you clone and save each individual one. If you have 2 million batches, each of 16 images, that's probably worth doing.
snibgo's IM pages: im.snibgo.com
toolforger
Posts: 18
Joined: 2015-09-28T00:39:38-07:00
Authentication code: 1151

Re: Expand a stack of files to equal size

Post by toolforger »

@fmw42
In image processing, an "stack" is just a series of images that you somehow process together. It's typcial terminology in HDR processing, where you have multiple shots of the same scene, put all the images "on top of each other", and use the redundancy to merge these images into an HDR one. This meaning of "stack" is pretty close to the everyday sense: sheets placed on top of each other. This is the usual sense of the word in an image processing context.
For coders, a "stack" is a box that accepts things, but will give them back to you only in the reverse order than they were put in. The real-world analogon would be a stack of plates: In theory you could take out a plate from the middle of the stack, but you don't want to, you take off the top one first. This is the usual sense of the word in a coding context.
In an ImageMagick context, you'll have to look at the context: If the person talking about the order in which images are added or removed from some area, then it's probably the coder sense; if the person is talking about the images processing and doesn't say about the exact order, then it's probably the image processing sense. If it doesn't help, ask whether the person is talking about a stack in the sense that a coder would use the word, or if it's just a bunch of images.
toolforger
Posts: 18
Joined: 2015-09-28T00:39:38-07:00
Authentication code: 1151

Re: Expand a stack of files to equal size

Post by toolforger »

An aside note: Filename generation now seems to be a solved problem. I have been overlooking "Filename References" on https://www.imagemagick.org/script/comm ... essing.php, which mentions (briefly) that the target filename can contain %d. With that Information, I could dig up that %02d will work, too, so IM can not only read NN.tif/page-MMMM.tif via *.tif/page-*.tif, I can also tell it to write %02d.tif/page-%04d.tif so it can preserve the numbering schema.
It's not what I have been asking about, but there have been mentions of filename structure, and indeed it would have become a question over time :-)

The -ping approach sounds like it's avoiding the overhead, so that's one of the things I'll try.

@snibgo Yes, the files easily fit in RAM, each is ~10MB. It may be more than 16 files per batch, but certainly not hundreds of files per batch, so I'm good here.

I have to admit that I do not fully understand your approach though.
Assuming we're dealing with just file1.tif, file2.tif, and file3.tif, what I understood is this:
  • I start with convert file1.tif file2.tif file3.tif, giving me the image sequence file1 file2 file3. (As written the command will also write files, but let's ignore that.)
  • New command: convert file1.tif file2.tif file3.tif -clone 0--1). This would give me the image sequence file1 file2 file3 file1 file2 file3, right?
  • Try convert file1.tif file2.tif file3.tif -clone 0--1 -layers merge. Going by the descriptions, this will give me a single image. This doesn't make sense because the clone step would be redundant.
So I guess we're talking about a stacked set of image sequences ("stack" in the coder sense, which are denoted by parentheses in the IM command line I understand):
  • convert file1.tif file2.tif file3.tif -> file1 file2 file3
  • convert file1.tif file2.tif file3.tif \( -clone 0--1 \) -> file1 file2 file3 (file1 file2 file3)
  • convert file1.tif file2.tif file3.tif \( -clone 0--1 -layers merge \) -> file1 file2 file3 (merged) - or maybe it is file1 file2 file3 merged now? I'll assume the latter.
  • Not sure how to make merged white, but I'll be able to figure that out. I'll just assume the option for that is -white :-)
  • Now I am at something like convert file1.tif file2.tif file3.tif \( -clone 0--1 -layers merge -white NULL: -swap \) (or maybe the closing parentheses is too late?). I have no idea how to apply -composite.
With the output filename stuff out of the way, I am currently considering
convert file00.tif file01.tif file02.tif -layers trim-bounds resized-file%02d.tif
Wouldn't that read file00.tif file01.tif file02.tif, extend the bounds to a common size, and write them to resized-file00.tif resized-file01.tif resized-file02.tif?
snibgo
Posts: 12159
Joined: 2010-01-23T23:01:33-07:00
Authentication code: 1151
Location: England, UK

Re: Expand a stack of files to equal size

Post by snibgo »

There would be a single convert, reading each file only once. Examples use Windows BAT syntax. Adjust for bash. We create three test files:

Code: Select all

convert -size 10x20 xc:cyan file01.tif
convert -size 30x20 xc:yellow file02.tif
convert -size 10x40 xc:magenta file03.tif
We can see that the outputs should be 30x40 pixels.

From the 3 inputs, make 3 outputs of the maximal dimensions. The padding is blue, so we can easily see where it is.

Code: Select all

convert ^
  file01.tif file02.tif file03.tif ^
  ( -clone 0--1 ^
    -layers merge ^
    +repage ^
    +write info: ^
    -fill Blue -colorize 100 ^
  ) ^
  NULL: -insert 0 ^
  -insert 0 ^
  -compose Over -layers composite ^
  out-%%02d.tif
The code within parentheses makes a blue image with the maximal dimensions. We add a null image, and rearrange the order so the image list now contains:

Code: Select all

maximal NULL: file01 file02 file02
"-layers composite" composites each of the 3 file images in turn over the maximal.

EDIT to add: this command reads each input once, but processes each pixel in each input twice. The code within parentheses processes all the pixels, which is logically redundant to merely find the maximal dimensions. Hence, this solution may be slower than one that finds the maximal dimensions without reading all the pixels, even if that needs separate commands.
snibgo's IM pages: im.snibgo.com
Post Reply