Using a FFI: hhImageJIT

Are you developing tools to extend the LiveCode environment? This is the place to talk about the nuts and bolts of extending our nuts and bolts. If you want to use a LiveCode or third party Environment extension, visit the Using Evironment Extensions forum.

Moderators: Klaus, FourthWorld, heatherlaine, kevinmiller, robinmiller

Post Reply
VIP Livecode Opensource Backer
VIP Livecode Opensource Backer
Posts: 1673
Joined: Thu Feb 28, 2013 11:52 pm
Location: Göttingen, DE

Using a FFI: hhImageJIT

Post by [-hh] » Wed Jun 22, 2016 12:08 am

Hi community members,
because there is not yet an FFI-subForum, I post this here.

I wrote an app (LiveCode standalone) that may go in the direction of what LC will give us soon with it's FFI-interface. It is a GUI to the fastest easy accessible interface I know:

LuaJIT, a jewel of development artwork, the cream of cream in development software.

Most of it is written in "made-to-measure"-Assembler and thus faster than native compiled C. What we use is available JIT (just in time), it has simply to be prepared to very basic Lua and some LuaJIT requirements, see .

The GUI I wrote using LiveCode, does that for you in a lot of cases, there is only for advanced users a module that allows to script the core of the procedures: Yes, you write it in a field and it is then just in time done by LuaJIT!

The app is still in early beta, only small help is available. It is good to know (but you don't have to) what imagedata is.

hhImageJIT v3b5 (LiveCode-GUI using the LuaJIT-FFI)

It's free, just try.
[The apps are closed source, will become open source when finished.]

  • Color.
    Change RGB-channels and apply a 3x3-color-matrix to each pixel (example usage: Sepia effect).
  • Convolve.
    Apply 3x3-5x5-7x7 matrices for 1 to 3 of the channels (example usage: Embossing).
  • Median.
    Apply Median (or other quantiles) filtering from a 3x3 up to a 33x33 surrounding area for each pixel and selected RGB-channels (example usage: Despeckle).
  • Transform (advanced, needs basic Lua).
    Apply math-transforms (example usage: whirl or wave).
  • Advanced (expert level: Touch the CORE).
    Act by script on each channel of each pixel (and its surrounding pixels).
    Very simple, write the following 5 lines to the input field and click "Do Field".

    Code: Select all

    -- your core script for changing color channels
    -- from RGB to BRG (Lua syntax)
    for i=0,n-1 do
    -- n=number of pixels (you don't have to give)
    -- x is one of r, g, b
    -- im[i].x = channel x of input pixel i, zero based
    -- img[i].x = channel x of output pixel i, zero based
Each module is shown/hidden by clicking its name. Clicking one of the 12 small squares at right determines the location on screen.
Median module is set to visible and located at midLeft of screen.
hhImageJit1.png (10.71 KiB) Viewed 1531 times
Clicking the big status oval (yellow, green, hopefully never red) compacts the module window.
The Convolve module. At top options for choosing input channels and which of these are 'convoluted'. Shown is the Gaussian Blur-G7 matrix.
At topLeft there are small buttons, for example for a calculator, in case you need one for your input.
QUIT hhImageJIT: Close the main window / use the main menu.

Two impressions of Edinburgh from an 2048x1364 input. Each
done in < 1 second for 2048x1364 output (here scaled down).
Extract the downloaded zip to any directory. Inside the expanded folder don't change the directory structure. You'll get:

[+] On all platforms
hhImageJit = the app, should work by double-click
hhImagesIN = directory of sample images, for later speed comparison
(the WS-images are from a Wilhelm-Sanke-stack, RichMedia-forum).
hhImagesOUT = directory for your saved artwork
hhPrefs = contains templates for personal menus (edit in a TextEditor).

[+] on Linux additionally
= a directory "fonts" containing three ttf-files which the app needs. Please install these fonts if they are not already in your OS.
= directories "Externals" and "Linux" and a file (don't touch these).

[+] on Windows additionally
= a directory "fonts" that is used by the app (perhaps you have to install the fonts).
= directories "Externals" and "Win32" and a file revsecurity.dll (don't touch these).

[There are also standalones for RaspiB, Raspi2 and Raspi3. The gain in speed is extreme on these machines!
As the source cannot be closed there, the zips are password-protected and I'll give them out under certain conditions to certain persons only. Just ask me via email.
And I'll prepare also versions for iOS and Android later on, but you will never be able to use them or later on my source code via 'official ways', because Apple and Google are very afraid of just-in-time compilation.]

The downloads are at about 15 MByte each (incl. 7 MByte images)

MacOS. Tested on 10.6-10.11 (for 10.12 see +++ below)

Linux. Tested on Debian, Mint, Lubuntu, Xubuntu.

Windows. Tested on Windows 7/8/10.

If you have problems or questions, please ask here in this thread.

Have fun with your artwork!


[+++ Edit: No more crash on 10.12 beta 3]
shiftLock happens

Livecode Opensource Backer
Livecode Opensource Backer
Posts: 21
Joined: Wed Aug 29, 2012 8:51 pm

Re: Using a FFI: hhImageJIT

Post by vince » Wed Jul 20, 2016 5:09 pm

Very cool and great performance! Can you maybe post a small example of how you communicate between LC and LuaJIT?

VIP Livecode Opensource Backer
VIP Livecode Opensource Backer
Posts: 1673
Joined: Thu Feb 28, 2013 11:52 pm
Location: Göttingen, DE

Re: Using a FFI: hhImageJIT

Post by [-hh] » Wed Jul 20, 2016 8:05 pm

If you mean callbacks with 'communicate': These are *very* expensive and I avoid them if possible.
So I mostly use the ordinary "shell" command which is "blocking" LC, but that's what I want for my "short" jobs.

That is
[1] LC creates an input file f0 from script
[2] LC uses "shell" to call luajit with infile f0
[3] [optionally: luaJIT writes an outfile]
[4] luaJIT returns "job done"
[5] [optionally: LC uses the output file]

The first timing you see in "imageJIT" is from before [2] to after [4].

Basic Example.
Take a working example from
into a LC-field "myscript"

Code: Select all

on mouseUp
  put "What I had to do" into job -- just a marker for you
  put "io.write("&quote&job&": Job done."&quote&")" into ljEnd
  put "luajit" into lj -- if available in $PATH
  -- put <fullPathToLuaJIT> into lj -- if not yet in $PATH
  put <fullFilePath> into f0 -- f0 must have extension ".lua"
  put (fld "myscript") &cr& ljEnd &cr into URL("file:" & f0)
  put shell(lj && quote&f0&quote ) into rslt
  if rslt is job&": Job done." then
    -- use the output file that luaJIT wrote for you
  else put rslt into fld "error"
end mouseUp	
Split debugging:
If your script fails then try in the CLI directly with file f0
(I prefer Geany, which has a "compile" menu item).
If you succeed then search the LC error.
shiftLock happens

Livecode Opensource Backer
Livecode Opensource Backer
Posts: 21
Joined: Wed Aug 29, 2012 8:51 pm

Re: Using a FFI: hhImageJIT

Post by vince » Thu Jul 21, 2016 7:35 am

Thanks for this insight in your solution. My process to be handled by luajit is much more time consuming with continuous status communication and control so a blocking call isn't an option. I'm going to see if "read/write process" or TCP socket communication will suit me better.

Post Reply

Return to “Extending LiveCode”