Page 1 of 1

Calculation of the focal length (in one run)

Posted: 2011-08-10T09:41:16-07:00
by whugemann
I am working on a Windows batch file that performs a correction for lens distortion. At the start, I have to identify the focal length of the photograph by

identify -format "%[EXIF:FocalLength]" testimage.jpg

Typically, EXIF data on focal length is given as a fraction, i.e. something like 27/1, meaning 27 mm, or 82/10, meaning 8.2 mm. In order to use this value in a comparison (with a list of focal lengths for which the correction parameters are known), I have to evaluate that fraction. I do this by means of IM's fx command in a two-step approach:

1) I assign the fraction to a environment variable.
2) I evaluate the content of the environment variable.

In a Windows batch file:

Code: Select all

SETLOCAL EnableDelayedExpansion
FOR /F %%i in ('identify -format "%%[EXIF:FocalLength]" %1') DO SET FL=%%i
FOR /F %%i in ('convert xc: -format "%%[fx:!FL!]" info:') DO SET FL=%%i
The focal length is then contained in the environment variable FL.

My question: Is there any way to combine these two statements into one, that is evaluating the EXIF fractional value directly with IM?

Re: Calculation of the focal length (in one run)

Posted: 2011-08-10T10:01:04-07:00
by fmw42
From http://www.imagemagick.org/Usage/basics/#set, I tried

convert P1050408.JPG -set filename:focal "%[EXIF:FocalLength]" -format "%[fx:'%[filename:focal]']" info:

but it did not work with the message

convert: unable to parse expression `[filename:focal]' @ error/fx.c/FxGetSymbol/1880.

Perhaps I am doing it wrong or likely it is the divide symbol / in the FocalLength that is messing it up.

This works:
convert rose: -set filename:my_area '%wx%h' 'rose-%[filename:my_area].png'

but this does not
convert rose: -set filename:my_area '%w/%h' 'rose-%[filename:my_area].png'

However, this inability to do fx computations on string formats in one step is something I have mentioned before.

Anthony, can you add this to IM 7 wish list.

Re: Calculation of the focal length (in one run)

Posted: 2011-08-10T11:29:18-07:00
by whugemann
I think your last examples doesn't work because the slash has a special meaning in filenames. When I created a subdirectory named "rose-70" before calling the IM command, it stored a file named "46.png" into it.

Re: Calculation of the focal length (in one run)

Posted: 2011-08-10T17:06:39-07:00
by anthony
whugemann wrote:My question: Is there any way to combine these two statements into one, that is evaluating the EXIF fractional value directly with IM?
In IMv6 no.

IN IMv7 maybe...

I plan to ensure that IMv7 allows you better access to the global defines and per-image settings, both for any arguments and for -fx arguments. My plan however was for substitutions in FX expressions to be a 'values' that is in the same way FX currently handles internal assignments. For example, I was planing on allowing this...

Code: Select all

   -define a=10  -fx 'r*log(a)'
That was the extent of my planned change.

The following is rambling thoughts as to solutions for IMv7

However to actually 'execute' an expression stored in a 'variable' such as EXIF:FocalLength would require the equivalent of a shell 'eval' or the ability to define a FX like function declaration. Alternately it would require string functions! That is the ability manipulate strings and not just numbers, so that you can 'split' the string into two numbers.

This is very similar to the UNIX 'awk' command (also perl) where all variables can be either a string or a number. How the variable contents is treated (as a number or a string) depends on the operators around it. Note that a string that does not contain a number, but is used in a numerical operation results in a value of zero).

Now in "awk" a variable assigned a string values of say "114/10" would actually have a value of 114, It would not be thought of as being 11.4. However in awk you could use string manipulation to extract the two numbers (assuming a '/' is present in the string) and divide them. Not exactly a nice solution either.

Now currently FX treats all variables, even its pre-assigned variables like 'r' and 's.r' purely as a number. It does not currently allow string manipulation. But if it did, it could do the same as awk, but it would not be as simple as an 'eval' solution.

Eval however is 'dangerous' and a major security hazard. It is something to be avoided as much as possible as it is far to 'general purpose'! For example what if a hacker sets a special focal length string that was designed to 'crack' your photo web application!


Anyone has any thoughts or suggestions?

Re: Calculation of the focal length (in one run)

Posted: 2011-08-10T17:59:28-07:00
by fmw42
why not just combine the functions of string formats into -fx, similar to -format "%w" is equivalent to -format "%[fx:w]"

Re: Calculation of the focal length (in one run)

Posted: 2011-08-10T18:00:44-07:00
by fmw42
fmw42 wrote:why not just combine the functions of string formats into -fx, similar to -format "%w" is equivalent to -format "%[fx:w]"
In practice it might be easier said than done. But it seems functionally reasonable. Why do we need such overlapping concepts, at least for those string formats that are numeric.

Re: Calculation of the focal length (in one run)

Posted: 2011-08-10T18:48:02-07:00
by whugemann
Eval however is 'dangerous' and a major security hazard. It is something to be avoided as much as possible as it is far to 'general purpose'! For example what if a hacker sets a special focal length string that was designed to 'crack' your photo web application!
I know about the security problems of eval(). I do however not quite see how a hacker could take advantage of it unless you give him/her full control over the command line input. Anyway, fx does already evaluate strings fed to it, see my example, where I store the string in an environment variable and then feed it to fx. With this interim step, I already get IM to do this.

A simple workaround for this special case would also be an additional EXIF variable that provides the focal length as a real value or, better, an additional parameter that tells IM to deliver any fractional EXIF parameter as a real value. AFAIK, EXIF stores all real values as fractions, such that this is a general problem.

Re: Calculation of the focal length (in one run)

Posted: 2011-08-10T18:56:47-07:00
by anthony
fmw42 wrote:From http://www.imagemagick.org/Usage/basics/#set, I tried

Code: Select all

convert P1050408.JPG -set filename:focal "%[EXIF:FocalLength]" -format "%[fx:'%[filename:focal]']" info:
That will not work for a number of reasons.
  1. fx does not understand single quotes
  2. fx can not at this time access either per-image set or global define strings.
  3. also fx does not understand strings - period. It only work with numbers and fx internal variables
  4. even if it did it would have to parse the variables twice once to get the value and then to 'execute' the value.
Anthony, can you add this to IM 7 wish list.
The second point is planned to be handled IMv7
the last point is equivalent to an 'eval' and is a security hole, as there is nothing to prevent users from setting EXIF:FocalLength to some unexpected string!

However I also can see the need for fx to handle strings and string functions. Perhaps in a similar way that 'awk' handles variables (numbers vs strings). But if I did it will probably not be backward compatible, and that I want to try an preserve as much as possible. It would actually be a project in and of itself, and can be done separately to what I currently plan for command line changes. As such it would probably be a done as a separate programming task, in parallel.

ASIDE: doing this may also allow better formatted responses from FX expressions by allowing 'sprintf()' string functions.
However adding string and meta-data access to FX would mean we will now be providing two completely different methods of generating format strings and argument handling...
  • Simple Percent Escaped (mostly static) strings
  • Calculated FX string expressions, including formatting

Re: Calculation of the focal length (in one run)

Posted: 2011-08-10T19:06:34-07:00
by anthony
whugemann wrote:
Eval however is 'dangerous' and a major security hazard. It is something to be avoided as much as possible as it is far to 'general purpose'! For example what if a hacker sets a special focal length string that was designed to 'crack' your photo web application!
I know about the security problems of eval(). I do however not quite see how a hacker could take advantage of it unless you give him/her full control over the command line input. Anyway, fx does already evaluate strings fed to it, see my example, where I store the string in an environment variable and then feed it to fx. With this interim step, I already get IM to do this.

A simple workaround for this special case would also be an additional EXIF variable that provides the focal length as a real value or, better, an additional parameter that tells IM to deliver any fractional EXIF parameter as a real value. AFAIK, EXIF stores all real values as fractions, such that this is a general problem.
The problem is the expression is not coming from a scripted command line! It is coming from an input image, which is typically user input and therefore suspect in many situations. I believe it is 'just a string'. It may not actually conform to the expected expression, but could be ANYTHING!

It would be better if that input was 'parsed' in some way so fx actually gets what it expects, otherwise it errors.

Re: Calculation of the focal length (in one run)

Posted: 2011-08-10T19:25:59-07:00
by anthony
fmw42 wrote:why not just combine the functions of string formats into -fx, similar to -format "%w" is equivalent to -format "%[fx:w]"
First about Percent Escapes...

Actually currently you can not use "%[w]" which is a little silly really!
That is instead of "%wx%h" you can not make the format string clearer by using "%[w]x%[h]"
on the other hand you can use "%[width]x%[height]" :-)

Code: Select all

convert rose: -format '%[width]x%[height]' info:
70x46

now about FX expressions...

Percent escape values names currently DO NOT match FX expression variable names. For 'w' it does, almost...

For example in FX "w" is actually a short hand for "s.w" or "u[t].w" So it does still match up. not not all escapes do
and many percent escapes are distinctly "strings" for exampe %l and %G

Next what if you want to get get a value that you have assigned to each image. For example supose you have created a "pixel_count" .. for example...

Code: Select all

  convert rose: granite: logo: -set pixel_count '%[fx:w*h]'  -format '%[pixel_count]' info:
3220
16384
307200
But you want to use "pixel_count" in an FX expression! How should it be accessed?
Suggestions..
  • use '$' EG: $pixel_count , s.$pixel_count , u[2].$pixel_count
    note the first would be either a global define or a setting from the current image 's'
  • use [..] EG: [pixel_count] , s.[pixel_count] , u[2].[pixel_count]
  • use %[..] that is make %[ be a different 'token' to just % (much like the difference between = and =<)
    EG: %[pixel_count] , s.%[pixel_count] , u[2].%[pixel_count]

Re: Calculation of the focal length (in one run)

Posted: 2011-08-10T19:32:33-07:00
by fmw42
anthony wrote:
fmw42 wrote:why not just combine the functions of string formats into -fx, similar to -format "%w" is equivalent to -format "%[fx:w]"


Actually currently you can not use "%[w]" which is a little silly really!
I never said "%[w]" only "%w".

I expect you are just making a point, however.