Using MIFF and piping to convert produces unexpected result

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?".
Post Reply
arizonagroovejet
Posts: 28
Joined: 2009-01-20T12:37:52-07:00

Using MIFF and piping to convert produces unexpected result

Post by arizonagroovejet »

I've been messing around with bash scripts on Linux that contain ImageMagick commands with variables that include the $RANDOM.

This produces the a square of the same colour every time I run it:

Code: Select all

mike@mine:~$ export RANDOM=1234; convert -size 50x50 xc:red -modulate 100,50,$((RANDOM%200)) foo.png
I consider the same result every time to be expected behaviour because I'm seeing RANDOM with the same value each time.

This produces a square of a different colour every time I run it:

Code: Select all

mike@mine:~$ export RANDOM=1234; convert -size 50x50 xc:red -modulate 100,50,$((RANDOM%200)) MIFF:-|convert - foo.png
That is not what I expect. I expect the same colour every time.

This produces a square of the same colour every time I run it:

Code: Select all

mike@mine:~$ export RANDOM=1234; convert -size 50x50 xc:"rgb($((RANDOM%255)),$((RANDOM%255)),$((RANDOM%255)))" foo.png
This produces a square of the same colour every time I run it:

Code: Select all

mike@mine:~$ export RANDOM=1234; convert -size 50x50 xc:"rgb($((RANDOM%255)),$((RANDOM%255)),$((RANDOM%255)))" foo.miff;convert foo.miff foo.png
This produces a square of a different colour every time I run it:

Code: Select all

mike@mine:~$ export RANDOM=1234; convert -size 50x50 xc:"rgb($((RANDOM%255)),$((RANDOM%255)),$((RANDOM%255)))" MIFF:-|convert - foo.png

Can anyone explain to me why piping MIFF:- to convert produces a random result when the other methods don't?



Code: Select all

mike@mine:~$ cat /etc/os-release
NAME=openSUSE
VERSION="13.1 (Bottle)"
VERSION_ID="13.1"
PRETTY_NAME="openSUSE 13.1 (Bottle) (x86_64)"
ID=opensuse
ANSI_COLOR="0;32"
CPE_NAME="cpe:/o:opensuse:opensuse:13.1"
BUG_REPORT_URL="https://bugs.opensuse.org"
HOME_URL="https://opensuse.org/"
ID_LIKE="suse"
mike@mine:~$ convert -version
Version: ImageMagick 6.8.6-9 2014-07-21 Q16 http://www.imagemagick.org
Copyright: Copyright (C) 1999-2013 ImageMagick Studio LLC
Features: DPC OpenMP
Delegates: bzlib djvu fftw fontconfig freetype jng jp2 jpeg lcms ltdl lzma pango pangocairo png png tiff webp wmf x xml zlib

mike@mine:~$ 
I get the same results with 6.8.8-3 on Mac OS X built from MacPorts. I tried using 6.8.9 on Linux using prebuilt binaries from source but failed to get anything but error messages.
User avatar
fmw42
Posts: 25562
Joined: 2007-07-02T17:14:51-07:00
Authentication code: 1152
Location: Sunnyvale, California, USA

Re: Using MIFF and piping to convert produces unexpected res

Post by fmw42 »

It is not an issue with MIFF: It happens with other intermediate formats such as PNG and GIF

It seems to have to do with using all caps for variable which is usually a system variable. I am not a unix expert so am not sure of the terminology.

But if you make RANDOM into random, it seems to work for me on IM 6.8.9.9 Q16 Mac OSX

Code: Select all

export random=1234; convert -size 50x50 xc:red -seed 100 -modulate 100,50,$((random%200)) MIFF:-|convert - foo.png
arizonagroovejet
Posts: 28
Joined: 2009-01-20T12:37:52-07:00

Re: Using MIFF and piping to convert produces unexpected res

Post by arizonagroovejet »

fmw42 wrote:It is not an issue with MIFF: It happens with other intermediate formats such as PNG and GIF
So it does. I got so hung up on why the results weren't what I was expecting I didn't think to try other formats.
fmw42 wrote: It seems to have to do with using all caps for variable which is usually a system variable. I am not a unix expert so am not sure of the terminology.

But if you make RANDOM into random, it seems to work for me on IM 6.8.9.9 Q16 Mac OSX

Code: Select all

export random=1234; convert -size 50x50 xc:red -seed 100 -modulate 100,50,$((random%200)) MIFF:-|convert - foo.png
That produces the same result every time but as far as I can tell that's because there's no longer any randomness rather than because a pseudo random number generator is being given the same seed each time. $random is just a regular variable not the same as $RANDOM.

Your command produces the same result as

Code: Select all

export foo=1234; convert -size 50x50 xc:red 100 -modulate 100,50,$((foo%200)) MIFF:-|convert - foo.png
and as

Code: Select all

export bob=1234; convert -size 50x50 xc:red -modulate 100,50,$((bob%200)) MIFF:-|convert - foo.png
and

Code: Select all

convert -size 50x50 xc:red -modulate 100,50,$((1234%200)) MIFF:-|convert - foo.png
I don't understand what the -seed is supposed to be doing in your command. The only examples I can find of -seed relate to +noise.
User avatar
fmw42
Posts: 25562
Joined: 2007-07-02T17:14:51-07:00
Authentication code: 1152
Location: Sunnyvale, California, USA

Re: Using MIFF and piping to convert produces unexpected res

Post by fmw42 »

The seed was left in by accident from a test I did.

If RANDOM is a system call and is giving you a random number, then it should always produce different colors, unless there is a way to set the seed value for RANDOM. In IM you can use the fx expression random(), e.g. -fx "random()". If you provide -seed somenumber before -fx, then it will always give the same random value. If you leave -seed out, then you get a different random number each time you run the command.

I guess I am not sure I understand you issue. Why would you expect the get the same color if you are using some means of providing a random value to the code. If you are providing a fixed number each time, then you should get a fixed color.

It seemed to me that you were providing a fixed value via RANDOM, but for some reason RANDOM was not keeping the fixed value when you exported it. That was why I suggested that you use lower case, random.

If you want to generate random values and control whether it is the same color or not, then use -fx "random()" and use -seed if you want the same random color each time.

try

hue=`convert xc: -seed 100 -format "%[fx:round(200*random())]" info:`
convert -size 50x50 xc:red -modulate 100,50,$hue result.png

if you want it completely random, then remove -seed 100
snibgo
Posts: 12159
Joined: 2010-01-23T23:01:33-07:00
Authentication code: 1151
Location: England, UK

Re: Using MIFF and piping to convert produces unexpected res

Post by snibgo »

This seems to be the way that bash works with piping, and nothing to to with IM. For example:

Code: Select all

$ export RANDOM=1234;echo $RANDOM
7764

$ export RANDOM=1234;echo $RANDOM
7764

$ export RANDOM=1234;echo $RANDOM|cat -
30403

$ export RANDOM=1234;echo $RANDOM|cat -
24918
snibgo's IM pages: im.snibgo.com
User avatar
fmw42
Posts: 25562
Joined: 2007-07-02T17:14:51-07:00
Authentication code: 1152
Location: Sunnyvale, California, USA

Re: Using MIFF and piping to convert produces unexpected res

Post by fmw42 »

I think it is different with lower case variables, as I mentioned above. But I am not expert enough in unix to know exactly why other than all caps, possibly, means some kind of environment variable. But perhaps there is no such RANDOM environment variable and so the pipe loses it.

Code: Select all

export random=1234;echo $random
1234

export random=1234;echo $random
1234

export random=1234;echo $random|cat -
1234

export random=1234;echo $random|cat -
1234
arizonagroovejet
Posts: 28
Joined: 2009-01-20T12:37:52-07:00

Re: Using MIFF and piping to convert produces unexpected res

Post by arizonagroovejet »

snibgo wrote:This seems to be the way that bash works with piping, and nothing to to with IM.
But the image is generated before the pipe, isn't it? PNG:- means create an image in the PNG:- format and write it to stdout. MIFF:- means create an image in the MIFF format and write it to stdout. So these two commands

Code: Select all

$ export RANDOM=1234; convert -size 50x50 xc:red -modulate 100,50,$((RANDOM%200)) foo.miff
$ export RANDOM=1234; convert -size 50x50 xc:red -modulate 100,50,$((RANDOM%200)) MIFF:-
are creating the same thing, the only difference is that in one the image is being written to stdout and in the other it's being written to a file. Right? And if that is right, then how can the resulting image be different after it's put through a pipe then written straight to a file with convert?
snibgo
Posts: 12159
Joined: 2010-01-23T23:01:33-07:00
Authentication code: 1151
Location: England, UK

Re: Using MIFF and piping to convert produces unexpected res

Post by snibgo »

"man bash" says RANDOM (capitals) is a shell variable:

Code: Select all

 RANDOM Each time this parameter is referenced, a random integer between
        0 and 32767 is generated.  The sequence of random numbers may be
        initialized by assigning a value to RANDOM.  If RANDOM is unset,
        it loses its special properties,  even  if  it  is  subsequently
        reset.
"random" (lower case) will be just an ordinary variable.
snibgo's IM pages: im.snibgo.com
arizonagroovejet
Posts: 28
Joined: 2009-01-20T12:37:52-07:00

Re: Using MIFF and piping to convert produces unexpected res

Post by arizonagroovejet »

fmw42 wrote: If RANDOM is a system call and is giving you a random number, then it should always produce different colors, unless there is a way to set the seed value for RANDOM.
It is and there is "RANDOM is an internal Bash function (not a constant) that returns a pseudorandom [1] integer in the range 0 - 32767."
Given the same seed it always produces the same sequence of numbers. RANDOM=1234 is seeding it with a value 1234

Code: Select all

case:tmp mike$ export RANDOM=1234
case:tmp mike$ for i in {1..5};do echo -n "${RANDOM} ";done;echo
1960 1307 12725 23832 32319 
case:tmp mike$ export RANDOM=1234
case:tmp mike$ for i in {1..5};do echo -n "${RANDOM} ";done;echo
1960 1307 12725 23832 32319 
case:tmp mike$ for i in {1..5};do echo -n "${RANDOM} ";done;echo
26039 18587 12983 14234 5389 
case:tmp mike$ for i in {1..5};do echo -n "${RANDOM} ";done;echo
28779 4357 32678 2889 1199 
case:tmp mike$ for i in {1..5};do echo -n "${RANDOM} ";done;echo
28840 21102 7218 7439 9476 
case:tmp mike$ export RANDOM=1234
case:tmp mike$ for i in {1..5};do echo -n "${RANDOM} ";done;echo
1960 1307 12725 23832 32319 
case:tmp mike$ 
http://tldp.org/LDP/abs/html/randomvar.html

I'll have a play with -fx "random()" as you suggest

thanks,

mike
arizonagroovejet
Posts: 28
Joined: 2009-01-20T12:37:52-07:00

Re: Using MIFF and piping to convert produces unexpected res

Post by arizonagroovejet »

I still don't understand exactly what is happening, I still can't answer the question I posed in post @ Thu Oct 30, 2014 12:30 pm but it seems to be something to do with bash running stuff after the pipe in a subshell. Maybe.

This produces a different result each time:

Code: Select all

$ export RANDOM=1234; convert -size 50x50 xc:red -modulate 100,50,$((RANDOM%200)) PNG:-|cat > foo.png
but these both use process substitution hence avoiding a subshell and produce the same result each time

Code: Select all

$ cat > foo.png <(export RANDOM=1234;convert -size 50x50 xc:red -modulate 100,50,$((RANDOM%200)) PNG:-)
$ convert <(export RANDOM=1234;convert -size 50x50 xc:red -modulate 100,50,$((RANDOM%200)) PNG:-)  foo.jpg
I arrived at this rabbit hole by way of generating multiple images in a loop then piping the result to montage and being puzzled that this produces a different result each time

Code: Select all

$ export RANDOM=1234;for i in {1..25};do convert -size 100x100 xc:red -modulate 100,50,$((RANDOM%200)) MIFF:-;done|montage - -geometry +0+0 foo.png
I think it should produce the same result each time, because as I said in the post I cite above, surely the images are all created by the time they reach the pipe. Yet, somehow the result is different each time.
From trial and error I've found that if I put everything before the pipe in to a subshell I get the same result each time

Code: Select all

$ (export RANDOM=1234;for i in {1..25};do convert -size 100x100 xc:red -modulate 100,50,$((RANDOM%200)) MIFF:-;done)|montage - -geometry +0+0 foo.png
I really do not understand why putting everything before the pipe in a subshell results in the predictable outcome I expect, but it does.
User avatar
fmw42
Posts: 25562
Joined: 2007-07-02T17:14:51-07:00
Authentication code: 1152
Location: Sunnyvale, California, USA

Re: Using MIFF and piping to convert produces unexpected res

Post by fmw42 »

I do not understand unix that well. But you can avoid the subshell by using -fx random() function with -seed if you want the same result each time for the given seed. I mentioned this above. Thus you do not have to rely upon the shell RANDOM function.
arizonagroovejet
Posts: 28
Joined: 2009-01-20T12:37:52-07:00

Re: Using MIFF and piping to convert produces unexpected res

Post by arizonagroovejet »

fmw42 wrote:I do not understand unix that well. But you can avoid the subshell by using -fx random() function with -seed if you want the same result each time for the given seed. I mentioned this above. Thus you do not have to rely upon the shell RANDOM function.
Yeah, I know but I still think there is a question over what ImageMagick is doing. It seems completely illogical to me that this produces the same result each time

Code: Select all

$ export RANDOM=1234; convert -size 50x50 xc:red -modulate 100,50,$((RANDOM%200)) foo.png
yet this does not

Code: Select all

$ export RANDOM=1234; convert -size 50x50 xc:red -modulate 100,50,$((RANDOM%200)) PNG:- | cat > foo.png
because as I understand it the convert commands are identical except one writes to a file and the other to stdout, so the output should be the same.

Using -fx random works but it's on overly complex way of getting a random number and assigning it to a variable. This does the same thing and it also produces the same result each time despite the output of ImageMagick going through a pipe. Which makes me more confused as to why the second command above doesn't produce the same result each time.

Code: Select all

$ export RANDOM=1234; h=$((RANDOM%200));convert -size 50x50 xc:red -modulate 100,50,$h PNG:- | cat > foo.png 
snibgo
Posts: 12159
Joined: 2010-01-23T23:01:33-07:00
Authentication code: 1151
Location: England, UK

Re: Using MIFF and piping to convert produces unexpected res

Post by snibgo »

The result are reproducible if we use "echo" instead of "convert".

I don't think this is an ImageMagick issue.
snibgo's IM pages: im.snibgo.com
Post Reply