Language comparisons: "Lua" - simpler and faster than RevTalk?

Wilhelm Sanke sanke at hrz.uni-kassel.de
Tue Mar 9 17:10:33 EST 2010


A quote from a website: "An increasing number of software developers are 
making use of the simplicity and power behind employing a Lua script 
interface".

I came across "Lua" when searching for image-filter algorithms on the web.

"Lua" is being described for example as "an extensible extension 
language (especially for C-languages)" and is written in C itself - 
similar here to the Rev engine which is written in C++. Generally - 
judging on the basis of my limited experience with Lua - I do not think 
that Lua is simpler than RevTalk, but when it comes to image processing 
a few features stand out as even more "higher-level", and in that sense 
"simpler", than RevTalk.

As Lua remains nearer to C, I assume that the execution of Lua scripts 
will be faster than such written in RevTalk. I do not know whether Lua 
scripts are compiled at runtime or build time.

A number of image tools integrate Lua in the form of flter plug-ins or 
for other tasks:

- "Adobe Photoshop Lightroom" uses Lua for its user interface and to 
create plugins (see the "Lightroom SDK Guide").

- "Gimp", the open-source and cross-platform Photoshop competitor uses 
"Gluas", a Lua environment plug-in - ("Gluas is a GIMP plug-in providing 
an environment for testing algorithms for image processing, using the 
Lua interpreter. The environment contains a simple editor for entering 
the algorithms.")

- "DogLua" is based on a 'gluas' plugin spec developed initially for GIMP.

Other programs in this category are

- "Dogwaffle",  "Artweaver", "Anim Studio", "TwistedBrush", "TexGen 
0.61" ("is designed to meet all your needs of creating textures"), and 
also a new "Lua Image Processor".--

I want to address here only three aspects of Lua:

1. Coordinates of pixel positions and its RGB elements

A typical skeleton script in Lua looks like this:

  "for y=0, height-1 do
    for x=0, width-1 do
     r,g,b = get_rgb(x,y)

-- do your stuff here, in this case
-- process the rgb values

      set_rgb (x,y,r,g,b)
     end
    progress(y/height)
   end"

A near equivalent to this in RevTalk would be:

"repeat with i = 0 to theight -1
   repeat with j = 0 to twidth -1
    put chartonum(char i * twidth * 4 + j * 4 + 2 of idata) into R
    put chartonum(char i * twidth * 4 + j * 4 + 3 of idata) into G
    put chartonum(char i * twidth * 4 + j * 4 + 4 of idata) into B

-- manipulate the RGB values here

    put numtochar(R) into char i * twidth * 4 + j * 4 + 2 of idata
    put numtochar(G) into char i * twidth * 4 + j * 4 + 3 of idata
    put numtochar(B) into char i * twidth * 4 + j * 4 + 4 of idata
  end repeat
end repeat"

To speed up this Rev skeleton script the computations could  of course 
be condensed and placed also outside the inner loop, at least partially:

"put twidth * 4 into trow
repeat with i = 0 to theight -1
  put i * trow into ti
   repeat with j = 0 to twidth -1
    put ti + j * 4 into tij
    put chartonum(char tij + 2 of idata) into R
    put chartonum(char tij + 3 of idata) into G
    put chartonum(char tij + 4 of idata) into B

-- manipulate the RGB values here

    put numtochar(R) into char tij + 2 of idata
    put numtochar(G) into char tij + 3 of idata
    put numtochar(B) into char tij + 4 of idata

  end repeat
end repeat".

It is obvious that Lua needs only the two plain x,y coordinates to 
determine the position of a pixel and its RGB components. The more 
complex computations necessary in the Rev script are running internally 
"under the hood" of Lua - predefined in C, meaning that in this case Lua 
is using syntax elements of a higher level than Rev.

Even if you use binaryDecode and -Encode functions instead of chartonum 
and numtochar triples in Rev, although visually they seem more like the 
Lua syntax " r,g,b = get_rgb(x,y)" and "set_rgb (x,y,r,g,b)", the amount 
of additional computations remains the same.

If you place

"GET binaryDEcode("CCC",char (tij +2) to (tij +4) of idata,R,G,B)
      #manipulate the data here
   PUT binaryEncode("CCC",R,G,B) into char (tij +2) to (tij +4) of idata"

inside the Rev scripts above (instead of the six chartonum/numtochar 
lines) the execution of the script will be even noticeable slower.
I tested this with a simple color-rotating script (shifting R -->G, 
G-->B, B -->R). The decode-encode variant proved to be 4 times slower 
here than with using chartonum-numtochar.

The nested repeat-loop approach is indispensable when the position and 
spacial arrangement of color pixels play a role, like when creating 
mirrors, gradients, frames, blur, jitter, adding a grid overlay, matrix 
operations, applying changes to a selected area of an image etc. If all 
color pixels are processed in the same way, for example when adding a 
specific hue to all pixels, changing saturation, contrast, gamma 
correction, threshold filters a single repeat loop is sufficient with 
"repeat for each" or "repeat with n = 1 to tlength".

In such cases "put after timagevar" can be used (with var "timagevar" 
set to empty before).
Comparing the speed, I found that

"put binaryEncode("CCCC",A,R,G,B) after timagevar" (# note that there 
are now *4* elements inside the encode function)

is about 1/3 faster than

"put numtochar(0) & numtochar(255) & numtochar(0) & numtochar(0) after 
timagevar".

But if  you have "pre-processed" the RGB values with numtochar before

  then " put tb & Rb & Gb & Bb after TimageVar"

will be twice as fast as using binaryEncode.


2. Direct access to HSV/HSL values in Lua

Unlike RevTalk "Lua" allows direct access to HSV values - Hue, 
Saturation, and Value (Luminance). The syntax is similar to getting and 
setting RGB values:

" h,s,v = get_hsv(x,y)" and
"set_hsv (x,y,h,s,v)"

In the "define colors" dialog" as part of Rev's object inspector, from 
which you can open the respective OS-specific dialog, you can choose HSV 
values by clicking on the spectrum or entering values into the HSV 
fields, but you cannot directly set HSV values in a Rev script.

In the Metacard IDE the functions "RGBtoHSV" and "HSVtoRGB" are 
available, historic scripts from Scott Raney which since the beginning 
of Metacard can be found in substack "Color Chooser" as part of the 
property inspector (e.g. in group "HSV" of card 1001 of stack "Color 
Chooser").

The Rev stack "revcolorchooser" in folder "Toolset" is identical to the 
MC stack, but it is a remnant from Metacard times, an "orphan", i.e it 
is no longer an integral part of the Rev IDE as it has been replaced by 
the color dialog of the specific platform used (From the Rev docs - 
concerning "answer color", but not only - : "This dialog box is 
displayed by the operating system, not by Revolution".).

Using the two functions is fast when you need to access and convert the 
values of a single color, for example that of a graphic. But when you 
intend to manipulate the colors of each pixel of an image, e.g. when 
shifting the hue for a certain percentage of the spectrum, using 
"RGBtoHSV" and "HSVtoRGB" is very, very slow.

Presently I am putting together a stack  "Exploring Hues" in which I 
make frequent use of the two functions, which I had also integrated into 
my  "Imagedata Toolkit" of 2006, where a corresponding group can be 
opened from button "Hues dialog".--

As both "Lua" and the Rev engine are based on "C" it must be easy to add 
direct access to HSV values via the Rev engine, too. What we could use 
at least, would be C-externals for the "RGBtoHSV" and "HSVtoRGB"  functions.

3. RGB-color range from 0 to 1 in Lua

This is only a side aspect, but one worth mentioning. RGB values in Lua 
are in the range of 0 to 1 instead of between 0 and 255 like in Rev. 
This has an interesting consequence because in a number of cases it can 
facilitate computations because you only need to divide by 1 instead of 
255 - as in the following Lua "duotone" script:


"function DoDuo

--basically map the image to a gradient created from the 2 colors.

for y = 0, height - 1 do
   for x = 0, width - 1 do
     r, g, b = get_rgb(x, y)

      av=(r+g+b)/3
      av2=1-av

      r=(r2*av)+(r3*av2)
      g=(g2*av)+(g3*av2)
      b=(b2*av)+(b3*av2)

     set_rgb(x, y, r, g, b)
   end
   progress(y2)
end"

The center part of the above script

     "av=(r+g+b)/3
      av2=1-av

      r=(r2*av)+(r3*av2)
      g=(g2*av)+(g3*av2)
      b=(b2*av)+(b3*av2)"

when ported to RevTalk would read

     "put ((r+g+b)/3) into av
       put 255 - av into av2
       put R2*av/255 + R3*av2/255 into R
       put G2*av/255 + G3*av2/255 into G
       put B2*av/255 + B3*av2/255 into B"

You see that a divison by 255 has been added at six places, replacing - 
as it were - a "virtual" division by 1 , and additionally "1" in 
calculating the  "av2" value has also been replaced by 255. The generic 
calculation behind this is as follows: The maximum value of the 
respective color range "tmax" - 1 in the case of Lua, 255 with Rev ( or 
the max of any other possible color range) - is used to adapt all values 
to the format of the specific color range:

     "put ((r+g+b)/3) into av
       put tmax - av into av2
       put R2*av/tmax + R3*av2/tmax into R
       put G2*av/tmax + G3*av2/tmax into G
       put B2*av/tmax + B3*av2/tmax into B"

You need to be careful when porting scripts from Lua to Rev to find out 
where you have to put in 255 for 1.

=============

Stack "Imagedata Toolkit" already contained a number of ported Lua 
filters, among them "Kuwahara", "Jitter", and "B-contrast". The Lua 
"B-contrast" algorithm was later also used by Mark Waddingham as an 
example in his tutorials (in one of the Rev Newsletters) to build externals.

In the meantime I have collected about twenty more Lua-filter scripts 
from various sources and ported them to Rev. I am working on a "Lua 
filters" stack which will be released shortly. The stack will contain 
image filters like "dynamic range", "pixelate", "bayer", "color 
diffusion", "flip & mix", "half lua" (image inside image), "threshold", 
"atmosphère lunaire", "negative", "night vision", "grid", "sunset 
gradient", "quad mirror", "replace colors", "lua blur", "jitter-blur", 
"duotone" etc. along with additional filters developed from or inspired 
by Lua algorithms - "tritone", "quadtone", "relief grid" and other 
variants.--

What about a "Lua" plugin for Rev as in "Gimp"?

Thank you for your patience - in case you read this text up to this point.

Kind regards,

Wilhelm Sanke
<http://www.sanke.org/MetaMedia>




More information about the use-livecode mailing list