Page 1 of 2

Process images to stdout immediately after they are read from stdin

Posted: 2020-03-16T10:23:21-07:00
by barabanus
Hello!

I've got a movie production pipeline which has a screenshots generator that produces a sequence of PPM to STDOUT. I pipe it to `convert` for postprocessing and then to `ffmpeg` to create the final movie without creation of intermediate files.

The command line looks like this:

Code: Select all

./generate-screenshots.py | convert ppm:- -distort resize 50% png:- | ffmpeg -f image2pipe -framerate 60 -i - movie.mp4
The problem is that ImageMagick accumulates input images until it runs out of memory (aka `No space left on device`).

Is it possible to make ImageMagick push images to STDOUT immediately after it had been read from STDIN and processed? I see no reason for ImageMagick to accumulate images.

Re: Process images to stdout immediately after they are read from stdin

Posted: 2020-03-16T10:44:25-07:00
by snibgo
barabanus wrote:Is it possible to make ImageMagick push images to STDOUT immediately after it had been read from STDIN and processed?
Yes. That's what "magick mogrify" does. Or simply "mogrify" if you use v6.

Re: Process images to stdout immediately after they are read from stdin

Posted: 2020-03-16T10:58:33-07:00
by barabanus
snibgo wrote:
2020-03-16T10:44:25-07:00
Yes. That's what "magick mogrify" does. Or simply "mogrify" if you use v6.
Well, I switched `convert` to `mogrify`, but there were no any difference.

Re: Process images to stdout immediately after they are read from stdin

Posted: 2020-03-16T12:34:44-07:00
by snibgo
"mogrify" has a different syntax to "convert". What was your exact command?

This works fine for me, on Windows 8.1:

Code: Select all

%IMG7%magick toes.png -duplicate 200 png:- | %IMG7%magick mogrify -resize 50% png:- | %IMG7%ffmpeg -f image2pipe -framerate 60 -i - movie.mp4
Looking at the console, and using "taskmgr" I can see that ffmeg starts immediately, and well before before magick ends.

Re: Process images to stdout immediately after they are read from stdin

Posted: 2020-03-16T12:50:41-07:00
by barabanus
snibgo wrote:
2020-03-16T12:34:44-07:00
"mogrify" has a different syntax to "convert". What was your exact command?
Let me simplify the command to demonstrate there's no actual difference which I guess is a bug.

At first, let me start with this command:

Code: Select all

{ for i in $(seq 10000); do convert logo: ppm:-; done } | convert ppm:- -resize 50% png:- >/dev/null
As expected, it generates error `No space left`

But when I use `mogrify` the result is the same:

Code: Select all

{ for i in $(seq 10000); do convert logo: ppm:-; done } | magick mogrify -resize 50% png:- >/dev/null
It generates the same `No space left` error.

Re: Process images to stdout immediately after they are read from stdin

Posted: 2020-03-16T13:17:36-07:00
by snibgo
barabanus wrote:{ for i in $(seq 10000); do convert logo: ppm:-; done } | magick mogrify -resize 50% png:- >/dev/null
Your command is bad. The "convert" writes (to the pipe) in ppm format. The "magick mogrify" tries to read png format from the pipe.

Re: Process images to stdout immediately after they are read from stdin

Posted: 2020-03-16T13:32:05-07:00
by barabanus
snibgo wrote:
2020-03-16T13:17:36-07:00
The "convert" writes (to the pipe) in ppm format. The "magick mogrify" tries to read png format from the pipe.
Is there a way to make it read PPM? Because when I write a sequence of PNGs it discards all PNGs except the first one.

Re: Process images to stdout immediately after they are read from stdin

Posted: 2020-03-16T14:12:59-07:00
by barabanus
Let me report: using PPM format with mogrify evokes `no space left` error in infinite loop:

Code: Select all

$ { while :; do convert logo: ppm:-; done } | mogrify -resize 50% ppm:- >/dev/null
mogrify: unable to write blob '/tmp/magick-8762pDAKAfwG9XPc': No space left on device @ error/blob.c/ImageToFile/2339.
But using MIFF format does not:

Code: Select all

{ while :; do convert logo: miff:-; done } | mogrify -resize 50% miff:- >/dev/null
Ok, this feature does work with MIFF image format. But it's internal ImageMagick format I'm not able to generate. I'll try to find a format which would work.

Re: Process images to stdout immediately after they are read from stdin

Posted: 2020-03-16T16:40:08-07:00
by snibgo
I suppose you have checked that you have plenty of free space on "/tmp"?

Re: Process images to stdout immediately after they are read from stdin

Posted: 2020-03-16T18:48:25-07:00
by magick
Your command is flawed. The mogrify scripts reads the MIFF images indefinitely. It won't move to the -resize until it gets an EOF. As it continually reads the images pushed from the convert command, it continues to consume resources until your host throws an exception (such as out of space). As your command runs, notice the ever growing temporarily file in /tmp/magick-*.

Re: Process images to stdout immediately after they are read from stdin

Posted: 2020-03-16T19:21:38-07:00
by snibgo
Oops, yes, I didn't spot that. IM can cope with hundreds of thousands of images, but not an infinite number.

Re: Process images to stdout immediately after they are read from stdin

Posted: 2020-03-17T05:20:20-07:00
by barabanus
Thank you for your comments. Unfortunately, I haven't found any supported image format which provides immediate image processing from STDIN to STDOUT without waiting for EOF from STDIN.

PNG is not an option because if you feed `mogrify` a sequence of PNGs it will discard all but the first.
PPM is not sent by `mogrify` to STDOUT until EOF from STDIN.

Other formats from `mogrify -list format` haven't worked too.

Is it expected behavior of `mogrify`? Should I request this feature or report the bug?

I found this command to be useful to detect whether mogrify generates data to STDOUT:

Code: Select all

{ while :; do convert logo: ppm:-; done } | mogrify -resize 50% ppm:- | ffmpeg -i - -f gif -y /dev/null

Re: Process images to stdout immediately after they are read from stdin

Posted: 2020-03-17T13:55:57-07:00
by magick
Try `convert ppm:- -resize 50% ppm:-`. Does that make a difference?

Re: Process images to stdout immediately after they are read from stdin

Posted: 2020-03-18T10:20:55-07:00
by barabanus
magick wrote:
2020-03-17T13:55:57-07:00
Try `convert ppm:- -resize 50% ppm:-`. Does that make a difference?
No, there's no difference. I expected from `mogrify` to process images immediately, but `mogrify` instead accumulates input images the same way `convert` does. Is it a bug of `mogrify`? Or should I ask for this functionality from `mogrify`?

Re: Process images to stdout immediately after they are read from stdin

Posted: 2020-03-18T16:46:02-07:00
by magick
Your use case cannot be supported. Many image types permit multiple frames per image file (e.g. MIFF). For these coders, stdin is read indefinitely until an EOF is detected or an exception is thrown. Other image types only permit one image. For these coders, one image is read and the command moves to write the output image, however, the command-line syntax does not provide for restarting. A work-around is to place a loop around the screenshot generator, push the screen shot to a file, convert the file while resizing, then repeat for the next screenshot.