Page 1 of 1

Inconsistent behavior with "-define distort:viewport"

Posted: 2016-12-15T18:39:46-07:00
by GeeMack
Using IM 7.0.3-10 on Windows 10 64, I've come across an inconsistency when using "-define distort:viewport". If I define the viewport with simple WxH dimensions, the result of this command is a 360x240 image as I would expect...

Code: Select all

magick logo: -define distort:viewport=320x240 -distort SRT 0 test0.png
The discrepancy occurs if I try to use percent escapes or FX expressions to define that viewport. All these commands result in output images that are still the same 640x480 dimensions as the input "logo:"...

Code: Select all

magick logo: -define distort:viewport=320x%w -distort SRT 0 test1.png

magick logo: -define distort:viewport=320x%[w] -distort SRT 0 test2.png

magick logo: -define distort:viewport=320x%[fx:120+120] -distort SRT 0 test3.png

magick logo: -define distort:viewport="%[fx:w/2]x240" -distort SRT 0 test4.png
I've tried this with and without quote marks around the expressions, with simple escapes like "%w", with square brackets like "%[w]", and with complete FX expressions like "%[fx:w*2]". None of them change the viewport dimensions, but just plain 360x240 does.

When I use "-set option:distort:viewport" as an alternative, there are no issues with any escapes, FX expressions, or quote marks.

Re: Inconsistent behavior with "-define distort:viewport"

Posted: 2016-12-15T18:59:58-07:00
by snibgo
In v6, I think it was always the case that "-define" couldn't use expressions but "-set" often could.

I'm not so sure about v7.

Re: Inconsistent behavior with "-define distort:viewport"

Posted: 2016-12-15T22:39:59-07:00
by anthony
-define does not use the expressions, but saves them for later use. That was because define often had to 'save' the percent escapes until later when an image is read. Also -define does not attache to images but globally, where -set are attached to images. The quintessential case of this was -label which is essentially the same as a -define label. The label could not be 'assigned' to the image until after image has been read in.

This means that you have two sets of values. globally defined values, and values set to an actual image.

So when the "distort" operate looks up the "viewport' it could look up a value that is assigned (set) to a specific image it is working on, OR it could use a global version of the "viewport" that is "defined" with all images.

In IMv6 the defined values were copied into a structure that was attached to all images, and was copied just before EVERY operation! IMv7 however only gives each image a point to the global defines they should be using (saves a lot of processing).

You can see what values are 'set' (per-image) and what are 'defined' (globally) using special percent escapes in "-format" "-identify" operations.

See IM Exmaples. Basics... Attributes-Properties (set) and Artifacts (define).
http://www.imagemagick.org/Usage/basics/#settings


You can get a listing of the current settings/defined in a running IM command using some special percent escapes (this was also back ported to IMv6!)

Code: Select all

magick ... \
   -print "__Properties__\n%[*]" \
   -print "__Artifacts__\n%[artifact:*]" \
   -print "__Options__\n%[option:*]" \
   ...
So using this with your define...

Code: Select all

convert logo: -define distort:viewport="%[fx:w/2]x240"   \
   -print "__Properties__\n%[*]" \
   -print "__Artifacts__\n%[artifact:*]" \
   -print "__Options__\n%[option:*]" \
   null:
__Properties__
date:create=2016-12-16T15:40:37+10:00
date:modify=2016-12-16T15:40:37+10:00
__Artifacts__
distort:viewport=%[fx:w/2]x240
filename=logo:
__Options__
distort:viewport=%[fx:w/2]x240
filename=logo:
From which you can see that define, did not expand the percent escapes. (so distort couldn't really interpret it)

Re: Inconsistent behavior with "-define distort:viewport"

Posted: 2016-12-15T23:05:34-07:00
by GeeMack
anthony wrote:-define does not use the expressions, but saves them for later use. [...]
Thanks for the thorough explanation!

Re: Inconsistent behavior with "-define distort:viewport"

Posted: 2016-12-15T23:11:09-07:00
by anthony
If you mean that percent escapes in "define" does not expand percent escapes when used in IMv6, WHEN it is actually used...

That is just a 'new feature' of IMv7 coming from the same cade that is used to set 'labels' on images as they are read in (a IMv6 feature expanded to more general use).

For example in IMv6... This worked...

Code: Select all

  convert -label '%wx%h'  logo: rose: -format '%l\n' info:
640x480
70x46
With the label being assigned to the images as they are read in... Converting from a global artifact to per-image properity

Code: Select all

convert -label '%wx%h'  logo: rose: \
   -format "__Properties__\n%[*]__Artifacts__\n%[artifact:*]\n" \
  info:
__Properties__
date:create=2016-12-16T16:07:51+10:00
date:modify=2016-12-16T16:07:51+10:00
label=640x480
__Artifacts__
filename=rose:
format=__Properties__\n%[*]__Artifacts__\n%[artifact:*]\n
get-property=480
label=%wx%h

__Properties__
date:create=2016-12-16T16:07:51+10:00
date:modify=2016-12-16T16:07:51+10:00
label=70x46
__Artifacts__
filename=rose:
format=__Properties__\n%[*]__Artifacts__\n%[artifact:*]\n
get-property=46
label=%wx%h
BUT the -"label" (which is just a "-define label" did not interpret the percent escape.

IMv7 however expands percent escapes for ALL artifacts -- matched to the image it is destined for -- when it is requested.
So when distort asked for a "viewport" and it failed to find a "viewport" properity for a specific image it will get then get the global artifact "viewport" but with percent escapes updated to that specific image.


WHY did I do this?

That means if you have a sequence of say 20 images. you can give a global define (with a percent escaped formula that is calculated) for ALL the images, but then have a specific setting for just ONE of the images (pre-calculated) overriding the global default.

Basically it made sense (in the ligt of way label works) to have -define use 'delayed percent escapes'. It had to be done, so I made it more general.

It is just that this did not get back ported to IMv6, and it may not be even possible to do this! The two just work differently.