On-screen drawing from lua - now possible. - page 2 - General Discussion and Assistance - CHDK Forum

On-screen drawing from lua - now possible.

  • 32 Replies
  • 7771 Views
*

Offline msl

  • *****
  • 1255
  • A720 IS, SX220 HS 1.01a
    • CHDK-DE links
Re: On-screen drawing from lua - now possible.
« Reply #10 on: 14 / November / 2011, 08:20:40 »
Advertisements
Nice project!

But I see also a some problems. Script commands should work on all cameras equally as possible. The color settings are depends on camera. We have more than 10 color tables. That's a big issue!

I think draw_circle() is not necessary because of different resolutions and aspect ratios. A circle can be adjusted through the function draw_ellipse().

What about set_console_autoredraw()? Can we redraw the draw functions, if it is necessary?

Have you tested the memory management? Have you already tested complex drawings? Perhaps we need a limitation of the possible draw functions in a script.

msl
CHDK-DE:  CHDK-DE links

Re: On-screen drawing from lua - now possible.
« Reply #11 on: 14 / November / 2011, 09:55:47 »
This is just starting material;) But at the moment I can say:

-I know that the color is one of the problems - I can see two possible solutions: 1) wait for reyalp's custom palette 2) use defined colors like for colored icons (only a few cameras unfortunetly). At the moment the only 'working' solution is to set colors as parameters to give the user possibility to change these settings

-A circle drawed as circle is not really circle due to reasons you described. On my sx130 is rather an ellipse. I don't know why does this function (draw circle) already exist in chdk source?

-I tried pictures containing more than 200 drawings. There was no problems with memory. I'm not sure about more complicated. As I described above I tried to do the drawings in other way - to malloc static array containing all drawings' parameters, so they could be redrawed everytime the OSD is redrawed but I had a lot of problems with memory. That's why at the moment I have to stay on calling apropriate draw functions through lua interpreter.

-set_console_autoredraw(0/1) seems to have no influence on the drawing. However, the console_redraw() removes drawings from screen

-there's no way to 'redraw' once removed drawings by single command. They have to be redrawed by drawing whole picture from lua (which can be done as in-script defined function).

---

Writing this text I realized, that it could be done in some specyfic way... Yeah, I have to try something more. I'm thinking, if all the parameters of the present drawings could be stored in a lua string (ot array) variable, not mallocated directly in chdk c routines. This could be much more simple, since lua has it's own memory allocation procedures. This way we could use drawings like (in lua):
Code: [Select]
VARIABLE=draw_init()                   --initializes the drawing (not sure if really important)
VARIABLE=draw_add_line(VARIABLE,ID,x1,y1,x2,y2,cl)  --adds specyfic drawing with ID identifier to VARIABLE
VARIABLE=draw_add_rect(VARIABLE,ID,x1,y1,x2,y2,cl)
draw(VARIABLE)
VARIABLE=draw_remove(VARIABLE,ID)
This way whole picture would be saved in VARIABLE and redrawed everytime we need it.

This would be quite simmilar to the drawing style in pygame (Python library).
if (2*b || !2*b) {
    cout<<question
}

Compile error: poor Yorick

Re: On-screen drawing from lua - now possible.
« Reply #12 on: 14 / November / 2011, 20:15:16 »
Forgive me for a very long post, but here is all I've don to make drawing usefull.

I made a simple lua module (to be stored as CHDK/LUALIB/drawings.lua):

Code: [Select]

SCREEN_DRAWINGS={}

draw={}

draw.add = function( d_type, p1, p2, p3, p4, p5, p6, p7 )
    local n=table.getn(SCREEN_DRAWINGS)+1
    if d_type=="pixel" then
        SCREEN_DRAWINGS[n]={"p",p1,p2,p3}--x,y,cl
        return n;
        end
    if d_type=="line" then
        SCREEN_DRAWINGS[n]={"l",p1,p2,p3,p4,p5}--x1,y1,x2,y2,cl
        return n;
        end
    if d_type=="rect" then
        SCREEN_DRAWINGS[n]={"r",p1,p2,p3,p4,p5,p6}--x1,y1,x2,y2,cl,th
        return n;
        end
    if d_type=="ellipse" then
        SCREEN_DRAWINGS[n]={"e",p1,p2,p3,p4,p5}--x,y,a,b,cl
        return n;
        end
    return false
    end

draw.replace = function( n, d_type, p1, p2, p3, p4, p5, p6, p7 )
    draw.remove(n)
    if d_type=="pixel" then
        SCREEN_DRAWINGS[n]={"p",p1,p2,p3}--x,y,cl
        return n;
        end
    if d_type=="line" then
        SCREEN_DRAWINGS[n]={"l",p1,p2,p3,p4,p5}--x1,y1,x2,y2,cl
        return n;
        end
    if d_type=="rect" then
        SCREEN_DRAWINGS[n]={"r",p1,p2,p3,p4,p5,p6}--x1,y1,x2,y2,cl,th
        return n;
        end
    if d_type=="ellipse" then
        SCREEN_DRAWINGS[n]={"e",p1,p2,p3,p4,p5}--x,y,a,b,cl
        return n;
        end
    return false
    end

draw.get_params = function(n)
    local out={nil}
    if SCREEN_DRAWINGS[n][1] == "p" then out[1]="pixel" end
    if SCREEN_DRAWINGS[n][1] == "l" then out[1]="line" end
    if SCREEN_DRAWINGS[n][1] == "r" then out[1]"rect" end
    if SCREEN_DRAWINGS[n][1] == "e" then out[1]="ellipse" end
    if (out[1]~=nil) then
        for i=2, table.getn(SCREEN_DRAWINGS[n]) do
            out[i]=SCREEN_DRAWINGS[n][i]
            end
        end
    return out
    end

draw.redraw = function()
    draw_clear()
    for i=1,table.getn(SCREEN_DRAWINGS) do
        local d_type=SCREEN_DRAWINGS[i][1]
        if d_type=="p" then
            local x=SCREEN_DRAWINGS[i][2]
            local y=SCREEN_DRAWINGS[i][3]
            local c=SCREEN_DRAWINGS[i][4]
            draw_pixel(x,y,c)
            end
        if d_type=="l" then
            local x1=SCREEN_DRAWINGS[i][2]
            local y1=SCREEN_DRAWINGS[i][3]
            local x2=SCREEN_DRAWINGS[i][4]
            local y2=SCREEN_DRAWINGS[i][5]
            local c=SCREEN_DRAWINGS[i][6]
            draw_line(x1,y1,x2,y2,c)
            end
        if d_type=="r" then
            local x1=SCREEN_DRAWINGS[i][2]
            local y1=SCREEN_DRAWINGS[i][3]
            local x2=SCREEN_DRAWINGS[i][4]
            local y2=SCREEN_DRAWINGS[i][5]
            local c=SCREEN_DRAWINGS[i][6]
            local t=SCREEN_DRAWINGS[i][7]
            draw_rect(x1,y1,x2,y2,c,t)
            end
        if d_type=="e" then
            local x=SCREEN_DRAWINGS[i][2]
            local y=SCREEN_DRAWINGS[i][3]
            local a=SCREEN_DRAWINGS[i][4]
            local b=SCREEN_DRAWINGS[i][5]
            local c=SCREEN_DRAWINGS[i][6]
            draw_rect(x,y,a,b,c)
            end
        end
    end

draw.remove = function(n)
    if (n<=table.getn(SCREEN_DRAWINGS)) then
        for i=1,table.getn(SCREEN_DRAWINGS[n]) do
            SCREEN_DRAWINGS[n][i]=nil
            end
        end
    end


This module provides a really simple way to use the draw functions which are described before. With this module you have a few nice functions.

Usage:

- first you have to load the module:

Code: [Select]
require "drawings"
this will also create special array - SCREEN_DRAWINGS which contains all the data

- now you are able to use functions:

Code: [Select]
draw.add(type,p1,p2,...,color)
this function adds the drawing object of type type to the SCREEN_DRAWINGS. The types are strings and p1,p2..., color are numbers. Type names and corresponding parameters are as follows:

"pixel" - x, y, color
"line" - x1, y1, x2, y2, color
"rect" - x1, y1, x2, y2, color (, thickness )
"ellipse" - x, y, a, b, color

The function draw.add() returns a integer which is the identifier for the created object. It can be asigned to a variable to controll this object in the script (removing, changing coordinates or color)

When you use draw.add() function the drawing does not appear on the screen! It's only added to the array. To make all these changes visible you have to redraw screen using:

Code: [Select]
draw.redraw()

When you have to remove an object from the SCREEN_DRAWINGS table you can simply use:

Code: [Select]
draw.remove(id)

where id is an integer - the object identifier that was returned by draw.add() function when this object was created. Of course draw.remove() does not change the screen display - have to redraw to make changes visible!

Next function is:
Code: [Select]
draw.replace(id, type, p1,p2...color)

This function in fact removes object which identifier is id and creates new one with specified parameters insted. It might be used either for changing parameters of the object or even replacing one type object with the other. Example:

Code: [Select]
require "drawings"

--create a rect
my_rect = draw.add("rect",20,20,50,50,30)

--make it visible
draw.redraw()

--do some waste of time
sleep(3000)

--move this rect 10 pixels rigth
draw.replace(my_rect, "rect", 30,20,50,50,30)

--make the change visible
draw.redraw()

--do some waste of time
sleep(3000)

--replace this rect with a circle with the centre on 100x100
draw.replace(my_rect, "ellipse", 100, 100, 50, 50, 30)

--do dome waste of time
sleep(3000)
print(done!)


Note: in this example variable my_rect holds the id of the rect and after replacing it with ellipse (circle) it still holds the id of the same object, which now is not a rect but a ellipse.

If you need to get the parameters of the object with known id you can use function:

Code: [Select]
parameters = draw.get_params(id)

It returns an array. Note: this can be also done by directly reading SCREEN_DRAWINGS table. In this case the parameters and SCREEN_DRAWINGS[id] holds the same table.


At the end of this post I can sumarize this as potentially very usefull tool. Using a few new lua functions with the new module we can add a very powerfull method to draw almost anything on the screen. There's no reason we could not add to this module functions like:

Code: [Select]
draw.popup_window(title, text, buttons_array,selected_button_number)

which gives lua-writers possibility to write simple GUI applications. Lua scripts with GUI? Great!

PS. I've tested these new functions + module by drawing 5000 lines using script:

Code: [Select]
--[[
@title module draw test
@param l lin
@default l 5000
--]]

require "drawings"

for i=1, l do
    x1=math.random(1,300)
    x2=math.random(1,300)
    y1=math.random(1,300)
    y2=math.random(1,300)
    cl=math.random(1,30)
    draw.add("line",x1,y1,x2,y2,cl)
    end

draw.redraw()

sleep(3000)
print("done!")

This script drawed 5000 lines which took 5 secounds on my sx130is without any crash or 'not enough memory'. I guess that 5000 lines is much more than anybody need...
« Last Edit: 14 / November / 2011, 20:18:53 by outslider »
if (2*b || !2*b) {
    cout<<question
}

Compile error: poor Yorick

On-screen drawing from lua - testers needed!
« Reply #13 on: 18 / November / 2011, 17:12:52 »
Hello again!

Playing with the drawing model I shortly described before I made some changes and now the whole thing is quite usable. I need some feedback to know, what it's to be done to make this feature worth to be added to CHDK (if devs will find it interesting).

The zip below contains:

  • luascript.c - updated version of the /core/luascript.c file which adds a few simple drawing functions. You have to compile your own CHDK to make whole thing working.
  • drawings.lua - a lua module to be placed in /CHDK/LUALIB directory on the SD card. It's a library to make the simple drawing functions much more powerfull and usable
  • DRAW_TEST.lua - a simple script that tries to use above module. It draws some shapes on the screen and prints the apropriate informations on console
  • drawings_readme.txt - readme for drawings usage. Read it and play with it:)


Notes:
  • You have to set the two colors to be used by script (as script parameters)
  • something is wrong with ellipse fill - it's not filled with background color but foreground. Could anybody look on it? I haven't found what's the bug.
  • It would be nice if you try to use drawings functions on your on, not only the provided testing script;)

Thank for all responses!
if (2*b || !2*b) {
    cout<<question
}

Compile error: poor Yorick


Re: On-screen drawing from lua - now possible.
« Reply #14 on: 27 / November / 2011, 15:42:29 »
I have changed a little the drawing module, so the drawings names are now compatible with the grids names (such as "elps" instead of before "ellipse", "rectf" and "elpsf" instead od "rect_f" and "ellipse_f").

I have also changed the "elpsf" call - it seems like ot does not require two collors - it has no 'border'. Now it's the same as in grids. In general.

The zip contains patch to luascript.c file (which is the only change of the source code), drawings.lua module to be placed in /CHDK/LUALIB directory on your sd card and simple script to test this module. And readme of course.

After compiling the patched source you have to only replace ps.fi2 and/or diskboot.bin files. New lua functions enlarges the binaries about 1kB, which is not a lot for new possibilities.

Next time I'll try to add some complex drawings to the drawings.lua module like "add.popup_window" which will be usefull in a gui-scripts point of view.

Also I'm going to write a simple grid editor to be used directly on camera. Very handy in my opinion and even better than drawing a grid on computer (you can see how the grid looks like in its native environment).

Best regards!
if (2*b || !2*b) {
    cout<<question
}

Compile error: poor Yorick

Re: On-screen drawing from lua - now possible.
« Reply #15 on: 27 / November / 2011, 15:46:50 »
Did you get anywhere with being able to draw text ?
Ported :   A1200    SD940   G10    Powershot N    G16

Re: On-screen drawing from lua - now possible.
« Reply #16 on: 27 / November / 2011, 16:02:12 »
A... yes, it is implemented since the previous realase:) As draw_string() as lua command and has "string" name as the drawings object;)
if (2*b || !2*b) {
    cout<<question
}

Compile error: poor Yorick

*

Offline philmoz

  • *****
  • 3102
    • Photos
Re: On-screen drawing from lua - now possible.
« Reply #17 on: 07 / December / 2011, 03:47:55 »
Posting this here instead of the change request thread to avoid cluttering that thread with the color discussion.
http://chdk.setepontos.com/index.php?topic=650.msg77553#msg77553

Suggestions for the color handling:
- use a two dimensional array (or two arrays) either static or outside the get_color function for the 'script_colors' array. e.g. script_colors[0][cl] for record mode and script_colors[1][cl] for playback mode. This will avoid the overhead of filling the array each time get_colors is called.
- add some or all of the COLOR_ICON_REC_xxx and COLOR_ICON_PLY_xxx colors to the palette. again these won't be consistent across all cameras but it does give you more range on some cameras and they should default to reasonable values on others.

Phil.
CHDK ports:
  sx30is (1.00c, 1.00h, 1.00l, 1.00n & 1.00p)
  g12 (1.00c, 1.00e, 1.00f & 1.00g)
  sx130is (1.01d & 1.01f)
  ixus310hs (1.00a & 1.01a)
  sx40hs (1.00d, 1.00g & 1.00i)
  g1x (1.00e, 1.00f & 1.00g)


Re: On-screen drawing from lua - now possible.
« Reply #18 on: 07 / December / 2011, 04:27:20 »
Ok. Forgive me for so many patches in the thread. I have to thank you to be so patient. I thought that local array is better than outside the function, since it takes no memory in a case of no usage of the drawings. Nevertheless you are better programmer than me, so I will follow your suggestions wherever they'll go;)

I'll add ICON colors too. I'll maybe post the patch here and if it'll be approved either I'll post it in [REQ] thread or you'll apply it by yourself.

Again - thank you!
if (2*b || !2*b) {
    cout<<question
}

Compile error: poor Yorick

*

Offline philmoz

  • *****
  • 3102
    • Photos
Re: On-screen drawing from lua - now possible.
« Reply #19 on: 07 / December / 2011, 05:11:33 »
Ok. Forgive me for so many patches in the thread. I have to thank you to be so patient. I thought that local array is better than outside the function, since it takes no memory in a case of no usage of the drawings. Nevertheless you are better programmer than me, so I will follow your suggestions wherever they'll go;)

I'll add ICON colors too. I'll maybe post the patch here and if it'll be approved either I'll post it in [REQ] thread or you'll apply it by yourself.

Again - thank you!

No problem - it's nice to have new people contributing new ideas.

No guarantee I'm a better programmer, just been doing it for a long time :)

With the array, you'd probably find that the extra code needed to initialise the array in the function would probably be larger than the data space required for the pre-initialised static arrays (these get loaded into memory already initialised from the DISKBOOT.BIN file so there's no code needed at startup to set them).

Phil.
CHDK ports:
  sx30is (1.00c, 1.00h, 1.00l, 1.00n & 1.00p)
  g12 (1.00c, 1.00e, 1.00f & 1.00g)
  sx130is (1.01d & 1.01f)
  ixus310hs (1.00a & 1.01a)
  sx40hs (1.00d, 1.00g & 1.00i)
  g1x (1.00e, 1.00f & 1.00g)

 

Related Topics