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