summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorWilliam Wilgus <me.theuser@yahoo.com>2019-08-04 09:48:09 -0500
committerWilliam Wilgus <me.theuser@yahoo.com>2019-08-04 16:57:02 +0200
commitf85df30e3e7da55c6880a321b3d8dc737f7af5b2 (patch)
treec778d743feef43162f53df9c1b642912822f664e
parent4209c097705ce474f955bf1d73ca6ccf1ac6786a (diff)
downloadrockbox-f85df30e3e7da55c6880a321b3d8dc737f7af5b2.tar.gz
rockbox-f85df30e3e7da55c6880a321b3d8dc737f7af5b2.zip
lua add rlimg.lua example script split large includes to separate files
Change-Id: I67cac5bc4ce5525ab30abf9443f6cc1a33190512
-rw-r--r--apps/plugins/lua/include_lua/draw.lua216
-rw-r--r--apps/plugins/lua/include_lua/draw_floodfill.lua95
-rw-r--r--apps/plugins/lua/include_lua/draw_poly.lua103
-rw-r--r--apps/plugins/lua/include_lua/draw_text.lua121
-rw-r--r--apps/plugins/lua/include_lua/image.lua184
-rw-r--r--apps/plugins/lua/include_lua/image_save.lua215
-rw-r--r--apps/plugins/lua/lua.make4
-rwxr-xr-xapps/plugins/lua_scripts/rlimg.lua919
8 files changed, 1464 insertions, 393 deletions
diff --git a/apps/plugins/lua/include_lua/draw.lua b/apps/plugins/lua/include_lua/draw.lua
index 0ee3e93d75..7208b63efb 100644
--- a/apps/plugins/lua/include_lua/draw.lua
+++ b/apps/plugins/lua/include_lua/draw.lua
@@ -29,7 +29,6 @@
29 _draw.ellipse_filled 29 _draw.ellipse_filled
30 _draw.ellipse_rect_filled 30 _draw.ellipse_rect_filled
31 _draw.ellipse_rect 31 _draw.ellipse_rect
32 _draw.flood_fill
33 _draw.hline 32 _draw.hline
34 _draw.image 33 _draw.image
35 _draw.line 34 _draw.line
@@ -39,7 +38,6 @@
39 _draw.rect_filled 38 _draw.rect_filled
40 _draw.rounded_rect 39 _draw.rounded_rect
41 _draw.rounded_rect_filled 40 _draw.rounded_rect_filled
42 _draw.text
43 _draw.vline 41 _draw.vline
44 42
45]] 43]]
@@ -56,21 +54,17 @@ local _draw = {} do
56 setmetatable(_draw, rocklib_image) 54 setmetatable(_draw, rocklib_image)
57 55
58 -- Internal Constants 56 -- Internal Constants
59 local _LCD = rb.lcd_framebuffer()
60 local LCD_W, LCD_H = rb.LCD_WIDTH, rb.LCD_HEIGHT
61 local BSAND = 8 -- blits color to dst if src <> 0 57 local BSAND = 8 -- blits color to dst if src <> 0
62 local _NIL = nil -- nil placeholder 58 local _NIL = nil -- nil placeholder
63 59
64 local _abs = math.abs 60
65 local _clear = rocklib_image.clear 61 local _clear = rocklib_image.clear
66 local _copy = rocklib_image.copy 62 local _copy = rocklib_image.copy
67 local _ellipse = rocklib_image.ellipse 63 local _ellipse = rocklib_image.ellipse
68 local _get = rocklib_image.get 64 local _get = rocklib_image.get
69 local _line = rocklib_image.line 65 local _line = rocklib_image.line
70 local _marshal = rocklib_image.marshal
71 local _min = math.min 66 local _min = math.min
72 local _newimg = rb.new_image 67 local _newimg = rb.new_image
73 local _points = rocklib_image.points
74 68
75 -- line 69 -- line
76 _draw.line = function(img, x1, y1, x2, y2, color, bClip) 70 _draw.line = function(img, x1, y1, x2, y2, color, bClip)
@@ -87,33 +81,22 @@ local _draw = {} do
87 _line(img, x, y, _NIL, y + length, color, bClip) 81 _line(img, x, y, _NIL, y + length, color, bClip)
88 end 82 end
89 83
90 -- draws a non-filled figure based on points in t-points 84 -- draws a non-filled rect based on points in t-points
91 local function polyline(img, x, y, t_points, color, bClosed, bClip) 85 local function polyrect(img, x, y, t_points, color, bClip)
92 if #t_points < 2 then error("not enough points", 3) end 86 local pt_first_last = t_points[1]
93 87 local pt1, pt2
94 local pt_first_last 88 for i = 1, 4, 1 do
95 89 pt1 = t_points[i]
96 if bClosed then 90 pt2 = t_points[i + 1] or pt_first_last-- first and last point
97 pt_first_last = t_points[1]
98 else
99 pt_first_last = t_points[#t_points]
100 end
101
102 for i = 1, #t_points, 1 do
103 local pt1 = t_points[i]
104
105 local pt2 = t_points[i + 1] or pt_first_last-- first and last point
106
107 _line(img, pt1[1] + x, pt1[2] + y, pt2[1] + x, pt2[2] + y, color, bClip) 91 _line(img, pt1[1] + x, pt1[2] + y, pt2[1] + x, pt2[2] + y, color, bClip)
108 end 92 end
109
110 end 93 end
111 94
112 -- rectangle 95 -- rectangle
113 local function rect(img, x, y, width, height, color, bClip) 96 local function rect(img, x, y, width, height, color, bClip)
114 if width == 0 or height == 0 then return end 97 if width == 0 or height == 0 then return end
115 98
116 polyline(img, x, y, {{0, 0}, {width, 0}, {width, height}, {0, height}}, color, true, bClip) 99 polyrect(img, x, y, {{0, 0}, {width, 0}, {width, height}, {0, height}}, color, bClip)
117 100
118 end 101 end
119 102
@@ -240,190 +223,9 @@ local _draw = {} do
240 _copy(dst, src, x, y, 1, 1, _NIL, _NIL, bClip) 223 _copy(dst, src, x, y, 1, 1, _NIL, _NIL, bClip)
241 end 224 end
242 225
243 -- floods an area of targetclr with fillclr x, y specifies the start seed
244 _draw.flood_fill = function(img, x, y, targetclr, fillclr)
245 -- scanline 4-way flood algorithm
246 -- ^
247 -- <--------x--->
248 -- v
249 -- check that target color doesn't = fill and the first point is target color
250 if targetclr == fillclr or targetclr ~= _get(img, x, y, true) then return end
251 local max_w = img:width()
252 local max_h = img:height()
253
254 local qpt = {} -- FIFO queue
255 -- rather than moving elements around in our FIFO queue
256 -- for each read; increment 'qhead' by 2
257 -- set both elements to nil and let the
258 -- garbage collector worry about it
259 -- for each write; increment 'qtail' by 2
260 -- x coordinates are in odd indices while
261 -- y coordinates are in even indices
262
263 local qtail = 0
264
265 local function check_ns(val, x, y)
266 if targetclr == val then
267 y = y - 1
268 if targetclr == _get(img, x, y, true) then -- north
269 qtail = qtail + 2
270 qpt[qtail - 1] = x
271 qpt[qtail] = y
272 end
273 y = y + 2
274 if targetclr == _get(img, x, y, true) then -- south
275 qtail = qtail + 2
276 qpt[qtail - 1] = x
277 qpt[qtail] = y
278 end
279 return fillclr
280 end
281 return _NIL -- signal marshal to stop
282 end
283
284 local function seed_pt(x, y)
285 -- should never hit max but make sure not to end early
286 for qhead = 2, 0x40000000, 2 do
287
288 if targetclr == _get(img, x, y, true) then
289 _marshal(img, x, y, 1, y, _NIL, _NIL, true, check_ns) -- west
290 _marshal(img, x + 1, y, max_w, y, _NIL, _NIL, true, check_ns) -- east
291 end
292
293 x = qpt[qhead - 1]
294 qpt[qhead - 1] = _NIL
295
296 if not x then break end
297
298 y = qpt[qhead]
299 qpt[qhead] = _NIL
300 end
301 end
302
303 seed_pt(x, y) -- Begin
304 end -- flood_fill
305
306 -- draws a closed figure based on points in t_points
307 _draw.polygon = function(img, x, y, t_points, color, fillcolor, bClip)
308 if #t_points < 2 then error("not enough points", 3) end
309
310 if fillcolor then
311 local x_min, x_max = 0, 0
312 local y_min, y_max = 0, 0
313 local w, h = 0, 0
314 -- find boundries of polygon
315 for i = 1, #t_points, 1 do
316 local pt = t_points[i]
317 if pt[1] < x_min then x_min = pt[1] end
318 if pt[1] > x_max then x_max = pt[1] end
319 if pt[2] < y_min then y_min = pt[2] end
320 if pt[2] > y_max then y_max = pt[2] end
321 end
322 w = _abs(x_max) + _abs(x_min)
323 h = _abs(y_max) + _abs(y_min)
324 x_min = x_min - 2 -- leave a border to use flood_fill
325 y_min = y_min - 2
326
327 local fill_img = _newimg(w + 3, h + 3)
328 _clear(fill_img, 0x1)
329
330 for i = 1, #t_points, 1 do
331 local pt1 = t_points[i]
332 local pt2 = t_points[i + 1] or t_points[1]-- first and last point
333 _line(fill_img, pt1[1] - x_min, pt1[2] - y_min,
334 pt2[1]- x_min, pt2[2] - y_min, 0)
335
336 end
337 _draw.flood_fill(fill_img, fill_img:width(), fill_img:height() , 0x1, 0x0)
338 _copy(img, fill_img, x - 1, y - 1, _NIL, _NIL, _NIL, _NIL, bClip, BSAND, fillcolor)
339 end
340
341 polyline(img, x, y, t_points, color, true, bClip)
342 end
343
344 -- draw text onto image if width/height are supplied text is centered
345 _draw.text = function(img, x, y, width, height, font, color, text)
346 font = font or rb.FONT_UI
347
348 local opts = {x = 0, y = 0, width = LCD_W - 1, height = LCD_H - 1,
349 font = font, drawmode = 3, fg_pattern = 0x1, bg_pattern = 0}
350
351 if rb.LCD_DEPTH == 2 then -- invert 2-bit screens
352 --vp.drawmode = bit.bxor(vp.drawmode, 4)
353 opts.fg_pattern = 3 - opts.fg_pattern
354 opts.bg_pattern = 3 - opts.bg_pattern
355 end
356 rb.set_viewport(opts)
357
358 local res, w, h = rb.font_getstringsize(text, font)
359
360 if not width then
361 width = 0
362 else
363 width = (width - w) / 2
364 end
365
366 if not height then
367 height = 0
368 else
369 height = (height - h) / 2
370 end
371
372 -- make a copy of the current screen for later
373 local screen_img = _newimg(LCD_W, LCD_H)
374 _copy(screen_img, _LCD)
375
376 -- check if the screen buffer is supplied image if so set img to the copy
377 if img == _LCD then
378 img = screen_img
379 end
380
381 -- we will be printing the text to the screen then blitting into img
382 rb.lcd_clear_display()
383
384 if w > LCD_W then -- text is too long for the screen do it in chunks
385 local l = 1
386 local resp, wp, hp
387 local lenr = text:len()
388
389 while lenr > 1 do
390 l = lenr
391 resp, wp, hp = rb.font_getstringsize(text:sub(1, l), font)
392
393 while wp >= LCD_W and l > 1 do
394 l = l - 1
395 resp, wp, hp = rb.font_getstringsize(text:sub( 1, l), font)
396 end
397
398 rb.lcd_putsxy(0, 0, text:sub(1, l))
399 text = text:sub(l)
400
401 if x + width > img:width() or y + height > img:height() then
402 break
403 end
404
405 -- using the mask we made blit color into img
406 _copy(img, _LCD, x + width, y + height, _NIL, _NIL, _NIL, _NIL, false, BSAND, color)
407 x = x + wp
408 rb.lcd_clear_display()
409 lenr = text:len()
410 end
411 else --w <= LCD_W
412 rb.lcd_putsxy(0, 0, text)
413
414 -- using the mask we made blit color into img
415 _copy(img, _LCD, x + width, y + height, _NIL, _NIL, _NIL, _NIL, false, BSAND, color)
416 end
417
418 _copy(_LCD, screen_img) -- restore screen
419 rb.set_viewport() -- set viewport default
420 return res, w, h
421 end
422
423 -- expose internal functions to the outside through _draw table 226 -- expose internal functions to the outside through _draw table
424 _draw.hline = hline 227 _draw.hline = hline
425 _draw.vline = vline 228 _draw.vline = vline
426 _draw.polyline = polyline
427 _draw.rect = rect 229 _draw.rect = rect
428 _draw.rounded_rect = rounded_rect 230 _draw.rounded_rect = rounded_rect
429end -- _draw functions 231end -- _draw functions
diff --git a/apps/plugins/lua/include_lua/draw_floodfill.lua b/apps/plugins/lua/include_lua/draw_floodfill.lua
new file mode 100644
index 0000000000..0303e711f2
--- /dev/null
+++ b/apps/plugins/lua/include_lua/draw_floodfill.lua
@@ -0,0 +1,95 @@
1--[[ Lua Floodfill function
2/***************************************************************************
3 * __________ __ ___.
4 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
5 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
6 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
7 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
8 * \/ \/ \/ \/ \/
9 * $Id$
10 *
11 * Copyright (C) 2017 William Wilgus
12 *
13 * This program is free software; you can redistribute it and/or
14 * modify it under the terms of the GNU General Public License
15 * as published by the Free Software Foundation; either version 2
16 * of the License, or (at your option) any later version.
17 *
18 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
19 * KIND, either express or implied.
20 *
21 ****************************************************************************/
22]]
23-- floods an area of targetclr with fillclr x, y specifies the start seed
24-- flood_fill(img, x, y, targetclr, fillclr)
25if not rb.lcd_framebuffer then rb.splash(rb.HZ, "No Support!") return nil end
26do
27
28 local rocklib_image = getmetatable(rb.lcd_framebuffer())
29 local _NIL = nil -- nil placeholder
30 local _get = rocklib_image.get
31 local _line = rocklib_image.line
32 local _marshal = rocklib_image.marshal
33
34 return function(img, x, y, targetclr, fillclr)
35 -- scanline 4-way flood algorithm
36 -- ^
37 -- <--------x--->
38 -- v
39 -- check that target color doesn't = fill and the first point is target color
40 if targetclr == fillclr or targetclr ~= _get(img, x, y, true) then return end
41 local max_w = img:width()
42 local max_h = img:height()
43
44 local qpt = {} -- FIFO queue
45 -- rather than moving elements around in our FIFO queue
46 -- for each read; increment 'qhead' by 2
47 -- set both elements to nil and let the
48 -- garbage collector worry about it
49 -- for each write; increment 'qtail' by 2
50 -- x coordinates are in odd indices while
51 -- y coordinates are in even indices
52
53 local qtail = 0
54
55 local function check_ns(val, x, y)
56 if targetclr == val then
57 y = y - 1
58 if targetclr == _get(img, x, y, true) then -- north
59 qtail = qtail + 2
60 qpt[qtail - 1] = x
61 qpt[qtail] = y
62 end
63 y = y + 2
64 if targetclr == _get(img, x, y, true) then -- south
65 qtail = qtail + 2
66 qpt[qtail - 1] = x
67 qpt[qtail] = y
68 end
69 return fillclr
70 end
71 return _NIL -- signal marshal to stop
72 end
73
74 local function seed_pt(x, y)
75 -- should never hit max but make sure not to end early
76 for qhead = 2, 0x40000000, 2 do
77
78 if targetclr == _get(img, x, y, true) then
79 _marshal(img, x, y, 1, y, _NIL, _NIL, true, check_ns) -- west
80 _marshal(img, x + 1, y, max_w, y, _NIL, _NIL, true, check_ns) -- east
81 end
82
83 x = qpt[qhead - 1]
84 qpt[qhead - 1] = _NIL
85
86 if not x then break end
87
88 y = qpt[qhead]
89 qpt[qhead] = _NIL
90 end
91 end
92
93 seed_pt(x, y) -- Begin
94 end -- flood_fill
95end
diff --git a/apps/plugins/lua/include_lua/draw_poly.lua b/apps/plugins/lua/include_lua/draw_poly.lua
new file mode 100644
index 0000000000..fd76a582b1
--- /dev/null
+++ b/apps/plugins/lua/include_lua/draw_poly.lua
@@ -0,0 +1,103 @@
1--[[ Lua Poly Drawing functions
2/***************************************************************************
3 * __________ __ ___.
4 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
5 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
6 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
7 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
8 * \/ \/ \/ \/ \/
9 * $Id$
10 *
11 * Copyright (C) 2017 William Wilgus
12 *
13 * This program is free software; you can redistribute it and/or
14 * modify it under the terms of the GNU General Public License
15 * as published by the Free Software Foundation; either version 2
16 * of the License, or (at your option) any later version.
17 *
18 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
19 * KIND, either express or implied.
20 *
21 ****************************************************************************/
22]]
23
24--[[ Exposed Functions
25 _poly.polygon
26 _poly.polyline
27]]
28
29if not rb.lcd_framebuffer then rb.splash(rb.HZ, "No Support!") return nil end
30
31local _poly = {} do
32 local BSAND = 8 -- blits color to dst if src <> 0
33 local _NIL = nil -- nil placeholder
34
35 local _abs = math.abs
36 local _copy = rocklib_image.copy
37 local _line = rocklib_image.line
38 local flood_fill = require("draw_floodfill")
39
40 -- draws a non-filled figure based on points in t-points
41 local function polyline(img, x, y, t_points, color, bClosed, bClip)
42 if #t_points < 2 then error("not enough points", 3) end
43
44 local pt_first_last
45
46 if bClosed then
47 pt_first_last = t_points[1]
48 else
49 pt_first_last = t_points[#t_points]
50 end
51
52 for i = 1, #t_points, 1 do
53 local pt1 = t_points[i]
54
55 local pt2 = t_points[i + 1] or pt_first_last-- first and last point
56
57 _line(img, pt1[1] + x, pt1[2] + y, pt2[1] + x, pt2[2] + y, color, bClip)
58 end
59
60 end
61
62 -- draws a closed figure based on points in t_points
63 _poly.polygon = function(img, x, y, t_points, color, fillcolor, bClip)
64 if #t_points < 2 then error("not enough points", 3) end
65
66 if fillcolor then
67 local x_min, x_max = 0, 0
68 local y_min, y_max = 0, 0
69 local w, h = 0, 0
70 -- find boundries of polygon
71 for i = 1, #t_points, 1 do
72 local pt = t_points[i]
73 if pt[1] < x_min then x_min = pt[1] end
74 if pt[1] > x_max then x_max = pt[1] end
75 if pt[2] < y_min then y_min = pt[2] end
76 if pt[2] > y_max then y_max = pt[2] end
77 end
78 w = _abs(x_max) + _abs(x_min)
79 h = _abs(y_max) + _abs(y_min)
80 x_min = x_min - 2 -- leave a border to use flood_fill
81 y_min = y_min - 2
82
83 local fill_img = _newimg(w + 3, h + 3)
84 _clear(fill_img, 0x1)
85
86 for i = 1, #t_points, 1 do
87 local pt1 = t_points[i]
88 local pt2 = t_points[i + 1] or t_points[1]-- first and last point
89 _line(fill_img, pt1[1] - x_min, pt1[2] - y_min,
90 pt2[1]- x_min, pt2[2] - y_min, 0)
91
92 end
93 flood_fill(fill_img, fill_img:width(), fill_img:height() , 0x1, 0x0)
94 _copy(img, fill_img, x - 1, y - 1, _NIL, _NIL, _NIL, _NIL, bClip, BSAND, fillcolor)
95 end
96
97 polyline(img, x, y, t_points, color, true, bClip)
98 end
99
100 -- expose internal functions to the outside through _poly table
101 _poly.polyline = polyline
102end
103return _poly
diff --git a/apps/plugins/lua/include_lua/draw_text.lua b/apps/plugins/lua/include_lua/draw_text.lua
new file mode 100644
index 0000000000..3722931c2c
--- /dev/null
+++ b/apps/plugins/lua/include_lua/draw_text.lua
@@ -0,0 +1,121 @@
1--[[ Lua Draw Text function
2/***************************************************************************
3 * __________ __ ___.
4 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
5 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
6 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
7 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
8 * \/ \/ \/ \/ \/
9 * $Id$
10 *
11 * Copyright (C) 2017 William Wilgus
12 *
13 * This program is free software; you can redistribute it and/or
14 * modify it under the terms of the GNU General Public License
15 * as published by the Free Software Foundation; either version 2
16 * of the License, or (at your option) any later version.
17 *
18 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
19 * KIND, either express or implied.
20 *
21 ****************************************************************************/
22]]
23-- draw text onto image if width/height are supplied text is centered
24
25if not rb.lcd_framebuffer then rb.splash(rb.HZ, "No Support!") return nil end
26
27do
28 -- Internal Constants
29 local rocklib_image = getmetatable(rb.lcd_framebuffer())
30 local _LCD = rb.lcd_framebuffer()
31 local LCD_W, LCD_H = rb.LCD_WIDTH, rb.LCD_HEIGHT
32 local BSAND = 8 -- blits color to dst if src <> 0
33 local _NIL = nil -- nil placeholder
34
35 local _clear = rocklib_image.clear
36 local _copy = rocklib_image.copy
37 local _newimg = rb.new_image
38
39
40 return function(img, x, y, width, height, font, color, text)
41 font = font or rb.FONT_UI
42
43 local opts = {x = 0, y = 0, width = LCD_W - 1, height = LCD_H - 1,
44 font = font, drawmode = 3, fg_pattern = 0x1, bg_pattern = 0}
45
46 if rb.LCD_DEPTH == 2 then -- invert 2-bit screens
47 --vp.drawmode = bit.bxor(vp.drawmode, 4)
48 opts.fg_pattern = 3 - opts.fg_pattern
49 opts.bg_pattern = 3 - opts.bg_pattern
50 end
51 rb.set_viewport(opts)
52
53 local res, w, h = rb.font_getstringsize(text, font)
54
55 if not width then
56 width = 0
57 else
58 width = (width - w) / 2
59 end
60
61 if not height then
62 height = 0
63 else
64 height = (height - h) / 2
65 end
66
67 -- make a copy of the current screen for later
68 --local screen_img = _newimg(LCD_W, LCD_H)
69 local screen_img = _newimg(LCD_W, h * 2)
70 _copy(screen_img, _LCD)
71
72 -- check if the screen buffer is supplied image if so set img to the copy
73 if img == _LCD then
74 img = screen_img
75 end
76
77 -- we will be printing the text to the screen then blitting into img
78 --rb.lcd_clear_display()
79 _clear(_LCD, opts.bg_pattern or 0, 1, 1, LCD_W, h * 2)
80
81 if w > LCD_W then -- text is too long for the screen do it in chunks
82 local l = 1
83 local resp, wp, hp
84 local lenr = text:len()
85
86 while lenr > 1 do
87 l = lenr
88 resp, wp, hp = rb.font_getstringsize(text:sub(1, l), font)
89
90 while wp >= LCD_W and l > 1 do
91 l = l - 1
92 resp, wp, hp = rb.font_getstringsize(text:sub( 1, l), font)
93 end
94
95 rb.lcd_putsxy(0, 0, text:sub(1, l))
96 text = text:sub(l)
97
98 if x + width > img:width() or y + height > img:height() then
99 break
100 end
101
102 -- using the mask we made blit color into img
103 _copy(img, _LCD, x + width, y + height, _NIL, _NIL, _NIL, _NIL, false, BSAND, color)
104 x = x + wp
105 --rb.lcd_clear_display()
106 _clear(_LCD, opts.bg_pattern or 0, 1, 1, LCD_W, h * 2)
107
108 lenr = text:len()
109 end
110 else --w <= LCD_W
111 rb.lcd_putsxy(0, 0, text)
112
113 -- using the mask we made blit color into img
114 _copy(img, _LCD, x + width, y + height, _NIL, _NIL, _NIL, _NIL, false, BSAND, color)
115 end
116
117 _copy(_LCD, screen_img) -- restore screen
118 rb.set_viewport() -- set viewport default
119 return res, w, h
120 end
121end
diff --git a/apps/plugins/lua/include_lua/image.lua b/apps/plugins/lua/include_lua/image.lua
index 2b2a1ce19f..5fd452ea78 100644
--- a/apps/plugins/lua/include_lua/image.lua
+++ b/apps/plugins/lua/include_lua/image.lua
@@ -23,7 +23,6 @@
23 23
24--[[ Exposed Functions 24--[[ Exposed Functions
25 25
26 _img.save
27 _img.search 26 _img.search
28 _img.rotate 27 _img.rotate
29 _img.resize 28 _img.resize
@@ -156,189 +155,6 @@ local _img = {} do
156 return r_img 155 return r_img
157 end 156 end
158 157
159 -- saves img to file: name
160 _img.save = function(img, name)
161 -- bmp saving derived from rockbox - screendump.c
162 -- bitdepth is limited by the device
163 -- eg. device displays greyscale, rgb images are saved greyscale
164 local file
165 local bbuffer = {} -- concat buffer for s_bytes
166 local fbuffer = {} -- concat buffer for file writes, reused
167
168 local function s_bytesLE(bits, value)
169 -- bits must be multiples of 8 (sizeof byte)
170 local byte
171 local nbytes = bit.rshift(bits, 3)
172 for b = 1, nbytes do
173 if value > 0 then
174 byte = value % 256
175 value = (value - byte) / 256
176 else
177 byte = 0
178 end
179 bbuffer[b] = string.char(byte)
180 end
181 return table.concat(bbuffer, _NIL, 1, nbytes)
182 end
183
184 local function s_bytesBE(bits, value)
185 -- bits must be multiples of 8 (sizeof byte)
186 local byte
187 local nbytes = bit.rshift(bits, 3)
188 for b = nbytes, 1, -1 do
189 if value > 0 then
190 byte = value % 256
191 value = (value - byte) / 256
192 else
193 byte = 0
194 end
195 bbuffer[b] = string.char(byte)
196 end
197 return table.concat(bbuffer, _NIL, 1, nbytes)
198 end
199
200 local cmp = {["r"] = function(c) return bit.band(bit.rshift(c, 16), 0xFF) end,
201 ["g"] = function(c) return bit.band(bit.rshift(c, 08), 0xFF) end,
202 ["b"] = function(c) return bit.band(c, 0xFF) end}
203
204 local function bmp_color(color)
205 return s_bytesLE(8, cmp.b(color))..
206 s_bytesLE(8, cmp.g(color))..
207 s_bytesLE(8, cmp.r(color))..
208 s_bytesLE(8, 0) .. ""
209 end -- c_cmp(color, c.r))
210
211 local function bmp_color_mix(c1, c2, num, den)
212 -- mixes c1 and c2 as ratio of numerator / denominator
213 -- used 2x each save results
214 local bc1, gc1, rc1 = cmp.b(c1), cmp.g(c1), cmp.r(c1)
215
216 return s_bytesLE(8, cmp.b(c2) - bc1 * num / den + bc1)..
217 s_bytesLE(8, cmp.g(c2) - gc1 * num / den + gc1)..
218 s_bytesLE(8, cmp.r(c2) - rc1 * num / den + rc1)..
219 s_bytesLE(8, 0) .. ""
220 end
221
222 local w, h = img:width(), img:height()
223 local depth = tonumber(img:__tostring(6)) -- RLI_INFO_DEPTH = 0x6
224 local format = tonumber(img:__tostring(7)) -- RLI_INFO_FORMAT = 0x7
225
226 local bpp, bypl -- bits per pixel, bytes per line
227 -- bypl, pad rows to a multiple of 4 bytes
228 if depth <= 4 then
229 bpp = 8 -- 256 color image
230 bypl = (w + 3)
231 elseif depth <= 16 then
232 bpp = 16
233 bypl = (w * 2 + 3)
234 elseif depth <= 24 then
235 bpp = 24
236 bypl = (w * 3 + 3)
237 else
238 bpp = 32
239 bypl = (w * 4 + 3)
240 end
241
242 local linebytes = bit.band(bypl, bit.bnot(3))
243
244 local bytesperpixel = bit.rshift(bpp, 3)
245 local headersz = 54
246 local imgszpad = h * linebytes
247
248 local compression, n_colors = 0, 0
249 local h_ppm, v_ppm = 0x00000EC4, 0x00000EC4 --Pixels Per Meter ~ 96 dpi
250
251 if depth == 16 then
252 compression = 3 -- BITFIELDS
253 n_colors = 3
254 elseif depth <= 8 then
255 n_colors = bit.lshift(1, depth)
256 end
257
258 headersz = headersz + (4 * n_colors)
259
260 file = io.open('/' .. name, "w+") -- overwrite, rb ignores the 'b' flag
261
262 if not file then
263 rb.splash(rb.HZ, "Error opening /" .. name)
264 return
265 end
266 -- create a bitmap header 'rope' with image details -- concatenated at end
267 local bmpheader = fbuffer
268
269 bmpheader[01] = "BM"
270 bmpheader[02] = s_bytesLE(32, headersz + imgszpad)
271 bmpheader[03] = "\0\0\0\0" -- WORD reserved 1 & 2
272 bmpheader[04] = s_bytesLE(32, headersz) -- BITMAPCOREHEADER size
273 bmpheader[05] = s_bytesLE(32, 40) -- BITMAPINFOHEADER size
274
275 bmpheader[06] = s_bytesLE(32, w)
276 bmpheader[07] = s_bytesLE(32, h)
277 bmpheader[08] = "\1\0" -- WORD color planes ALWAYS 1
278 bmpheader[09] = s_bytesLE(16, bpp) -- bits/pixel
279 bmpheader[10] = s_bytesLE(32, compression)
280 bmpheader[11] = s_bytesLE(32, imgszpad)
281 bmpheader[12] = s_bytesLE(32, h_ppm) -- biXPelsPerMeter
282 bmpheader[13] = s_bytesLE(32, v_ppm) -- biYPelsPerMeter
283 bmpheader[14] = s_bytesLE(32, n_colors)
284 bmpheader[15] = s_bytesLE(32, n_colors)
285
286 -- Color Table (#n_colors entries)
287 if depth == 1 then -- assuming positive display
288 bmpheader[#bmpheader + 1] = bmp_color(0xFFFFFF)
289 bmpheader[#bmpheader + 1] = bmp_color(0x0)
290 elseif depth == 2 then
291 bmpheader[#bmpheader + 1] = bmp_color(0xFFFFFF)
292 bmpheader[#bmpheader + 1] = bmp_color_mix(0xFFFFFF, 0, 1, 3)
293 bmpheader[#bmpheader + 1] = bmp_color_mix(0xFFFFFF, 0, 2, 3)
294 bmpheader[#bmpheader + 1] = bmp_color(0x0)
295 elseif depth == 16 then
296 if format == 555 then
297 -- red bitfield mask
298 bmpheader[#bmpheader + 1] = s_bytesLE(32, 0x00007C00)
299 -- green bitfield mask
300 bmpheader[#bmpheader + 1] = s_bytesLE(32, 0x000003E0)
301 -- blue bitfield mask
302 bmpheader[#bmpheader + 1] = s_bytesLE(32, 0x0000001F)
303 else --565
304 -- red bitfield mask
305 bmpheader[#bmpheader + 1] = s_bytesLE(32, 0x0000F800)
306 -- green bitfield mask
307 bmpheader[#bmpheader + 1] = s_bytesLE(32, 0x000007E0)
308 -- blue bitfield mask
309 bmpheader[#bmpheader + 1] = s_bytesLE(32, 0x0000001F)
310 end
311 end
312
313 file:write(table.concat(fbuffer))-- write the header to the file now
314 for i=1, #fbuffer do fbuffer[i] = _NIL end -- reuse table
315
316 local imgdata = fbuffer
317 -- pad rows to a multiple of 4 bytes
318 local bytesleft = linebytes - (bytesperpixel * w)
319 local t_data = {}
320 local fs_bytes_E = s_bytesLE -- default save in Little Endian
321
322 if format == 3553 then -- RGB565SWAPPED
323 fs_bytes_E = s_bytesBE -- Saves in Big Endian
324 end
325
326 -- Bitmap lines start at bottom unless biHeight is negative
327 for point in _points(img, 1, h, w + bytesleft, 1) do
328 imgdata[#imgdata + 1] = fs_bytes_E(bpp, point or 0)
329
330 if #fbuffer >= 31 then -- buffered write, increase # for performance
331 file:write(table.concat(fbuffer))
332 for i=1, #fbuffer do fbuffer[i] = _NIL end -- reuse table
333 end
334
335 end
336 file:write(table.concat(fbuffer)) --write leftovers to file
337 fbuffer = _NIL
338
339 file:close()
340 end -- save(img, name)
341
342 --searches an image for target color 158 --searches an image for target color
343 _img.search = function(img, x1, y1, x2, y2, targetclr, variation, stepx, stepy) 159 _img.search = function(img, x1, y1, x2, y2, targetclr, variation, stepx, stepy)
344 160
diff --git a/apps/plugins/lua/include_lua/image_save.lua b/apps/plugins/lua/include_lua/image_save.lua
new file mode 100644
index 0000000000..4735af46d7
--- /dev/null
+++ b/apps/plugins/lua/include_lua/image_save.lua
@@ -0,0 +1,215 @@
1--[[ Lua Image save
2/***************************************************************************
3 * __________ __ ___.
4 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
5 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
6 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
7 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
8 * \/ \/ \/ \/ \/
9 * $Id$
10 *
11 * Copyright (C) 2017 William Wilgus
12 *
13 * This program is free software; you can redistribute it and/or
14 * modify it under the terms of the GNU General Public License
15 * as published by the Free Software Foundation; either version 2
16 * of the License, or (at your option) any later version.
17 *
18 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
19 * KIND, either express or implied.
20 *
21 ****************************************************************************/
22]]
23-- save(img, path/name)
24-- bmp saving derived from rockbox - screendump.c
25-- bitdepth is limited by the device
26-- eg. device displays greyscale, rgb images are saved greyscale
27if not rb.lcd_framebuffer then rb.splash(rb.HZ, "No Support!") return nil end
28
29do
30 local rocklib_image = getmetatable(rb.lcd_framebuffer())
31
32 -- internal constants
33 local _NIL = nil -- _NIL placeholder
34 local _points = rocklib_image.points
35
36 -- saves img to file: name
37 return function(img, name)
38 local file
39 local bbuffer = {} -- concat buffer for s_bytes
40 local fbuffer = {} -- concat buffer for file writes, reused
41
42 local function s_bytesLE(bits, value)
43 -- bits must be multiples of 8 (sizeof byte)
44 local byte
45 local nbytes = bit.rshift(bits, 3)
46 for b = 1, nbytes do
47 if value > 0 then
48 byte = value % 256
49 value = (value - byte) / 256
50 else
51 byte = 0
52 end
53 bbuffer[b] = string.char(byte)
54 end
55 return table.concat(bbuffer, _NIL, 1, nbytes)
56 end
57
58 local function s_bytesBE(bits, value)
59 -- bits must be multiples of 8 (sizeof byte)
60 local byte
61 local nbytes = bit.rshift(bits, 3)
62 for b = nbytes, 1, -1 do
63 if value > 0 then
64 byte = value % 256
65 value = (value - byte) / 256
66 else
67 byte = 0
68 end
69 bbuffer[b] = string.char(byte)
70 end
71 return table.concat(bbuffer, _NIL, 1, nbytes)
72 end
73
74 local cmp = {["r"] = function(c) return bit.band(bit.rshift(c, 16), 0xFF) end,
75 ["g"] = function(c) return bit.band(bit.rshift(c, 08), 0xFF) end,
76 ["b"] = function(c) return bit.band(c, 0xFF) end}
77
78 local function bmp_color(color)
79 return s_bytesLE(8, cmp.b(color))..
80 s_bytesLE(8, cmp.g(color))..
81 s_bytesLE(8, cmp.r(color))..
82 s_bytesLE(8, 0) .. ""
83 end -- c_cmp(color, c.r))
84
85 local function bmp_color_mix(c1, c2, num, den)
86 -- mixes c1 and c2 as ratio of numerator / denominator
87 -- used 2x each save results
88 local bc1, gc1, rc1 = cmp.b(c1), cmp.g(c1), cmp.r(c1)
89
90 return s_bytesLE(8, cmp.b(c2) - bc1 * num / den + bc1)..
91 s_bytesLE(8, cmp.g(c2) - gc1 * num / den + gc1)..
92 s_bytesLE(8, cmp.r(c2) - rc1 * num / den + rc1)..
93 s_bytesLE(8, 0) .. ""
94 end
95
96 local w, h = img:width(), img:height()
97 local depth = tonumber(img:__tostring(6)) -- RLI_INFO_DEPTH = 0x6
98 local format = tonumber(img:__tostring(7)) -- RLI_INFO_FORMAT = 0x7
99
100 local bpp, bypl -- bits per pixel, bytes per line
101 -- bypl, pad rows to a multiple of 4 bytes
102 if depth <= 4 then
103 bpp = 8 -- 256 color image
104 bypl = (w + 3)
105 elseif depth <= 16 then
106 bpp = 16
107 bypl = (w * 2 + 3)
108 elseif depth <= 24 then
109 bpp = 24
110 bypl = (w * 3 + 3)
111 else
112 bpp = 32
113 bypl = (w * 4 + 3)
114 end
115
116 local linebytes = bit.band(bypl, bit.bnot(3))
117
118 local bytesperpixel = bit.rshift(bpp, 3)
119 local headersz = 54
120 local imgszpad = h * linebytes
121
122 local compression, n_colors = 0, 0
123 local h_ppm, v_ppm = 0x00000EC4, 0x00000EC4 --Pixels Per Meter ~ 96 dpi
124
125 if depth == 16 then
126 compression = 3 -- BITFIELDS
127 n_colors = 3
128 elseif depth <= 8 then
129 n_colors = bit.lshift(1, depth)
130 end
131
132 headersz = headersz + (4 * n_colors)
133
134 file = io.open('/' .. name, "w+") -- overwrite, rb ignores the 'b' flag
135
136 if not file then
137 rb.splash(rb.HZ, "Error opening /" .. name)
138 return
139 end
140 -- create a bitmap header 'rope' with image details -- concatenated at end
141 local bmpheader = fbuffer
142
143 bmpheader[01] = "BM"
144 bmpheader[02] = s_bytesLE(32, headersz + imgszpad)
145 bmpheader[03] = "\0\0\0\0" -- WORD reserved 1 & 2
146 bmpheader[04] = s_bytesLE(32, headersz) -- BITMAPCOREHEADER size
147 bmpheader[05] = s_bytesLE(32, 40) -- BITMAPINFOHEADER size
148
149 bmpheader[06] = s_bytesLE(32, w)
150 bmpheader[07] = s_bytesLE(32, h)
151 bmpheader[08] = "\1\0" -- WORD color planes ALWAYS 1
152 bmpheader[09] = s_bytesLE(16, bpp) -- bits/pixel
153 bmpheader[10] = s_bytesLE(32, compression)
154 bmpheader[11] = s_bytesLE(32, imgszpad)
155 bmpheader[12] = s_bytesLE(32, h_ppm) -- biXPelsPerMeter
156 bmpheader[13] = s_bytesLE(32, v_ppm) -- biYPelsPerMeter
157 bmpheader[14] = s_bytesLE(32, n_colors)
158 bmpheader[15] = s_bytesLE(32, n_colors)
159
160 -- Color Table (#n_colors entries)
161 if depth == 1 then -- assuming positive display
162 bmpheader[#bmpheader + 1] = bmp_color(0xFFFFFF)
163 bmpheader[#bmpheader + 1] = bmp_color(0x0)
164 elseif depth == 2 then
165 bmpheader[#bmpheader + 1] = bmp_color(0xFFFFFF)
166 bmpheader[#bmpheader + 1] = bmp_color_mix(0xFFFFFF, 0, 1, 3)
167 bmpheader[#bmpheader + 1] = bmp_color_mix(0xFFFFFF, 0, 2, 3)
168 bmpheader[#bmpheader + 1] = bmp_color(0x0)
169 elseif depth == 16 then
170 if format == 555 then
171 -- red bitfield mask
172 bmpheader[#bmpheader + 1] = s_bytesLE(32, 0x00007C00)
173 -- green bitfield mask
174 bmpheader[#bmpheader + 1] = s_bytesLE(32, 0x000003E0)
175 -- blue bitfield mask
176 bmpheader[#bmpheader + 1] = s_bytesLE(32, 0x0000001F)
177 else --565
178 -- red bitfield mask
179 bmpheader[#bmpheader + 1] = s_bytesLE(32, 0x0000F800)
180 -- green bitfield mask
181 bmpheader[#bmpheader + 1] = s_bytesLE(32, 0x000007E0)
182 -- blue bitfield mask
183 bmpheader[#bmpheader + 1] = s_bytesLE(32, 0x0000001F)
184 end
185 end
186
187 file:write(table.concat(fbuffer))-- write the header to the file now
188 for i=1, #fbuffer do fbuffer[i] = _NIL end -- reuse table
189
190 local imgdata = fbuffer
191 -- pad rows to a multiple of 4 bytes
192 local bytesleft = linebytes - (bytesperpixel * w)
193 local t_data = {}
194 local fs_bytes_E = s_bytesLE -- default save in Little Endian
195
196 if format == 3553 then -- RGB565SWAPPED
197 fs_bytes_E = s_bytesBE -- Saves in Big Endian
198 end
199
200 -- Bitmap lines start at bottom unless biHeight is negative
201 for point in _points(img, 1, h, w + bytesleft, 1) do
202 imgdata[#imgdata + 1] = fs_bytes_E(bpp, point or 0)
203
204 if #fbuffer >= 31 then -- buffered write, increase # for performance
205 file:write(table.concat(fbuffer))
206 for i=1, #fbuffer do fbuffer[i] = _NIL end -- reuse table
207 end
208
209 end
210 file:write(table.concat(fbuffer)) --write leftovers to file
211 fbuffer = _NIL
212
213 file:close()
214 end -- save(img, name)
215end
diff --git a/apps/plugins/lua/lua.make b/apps/plugins/lua/lua.make
index d5fb85afbc..388c5d74d3 100644
--- a/apps/plugins/lua/lua.make
+++ b/apps/plugins/lua/lua.make
@@ -16,8 +16,8 @@ LUA_OBJ := $(call c2obj, $(LUA_SRC))
16OTHER_SRC += $(LUA_SRC) 16OTHER_SRC += $(LUA_SRC)
17 17
18LUA_INCLUDEDIR := $(LUA_SRCDIR)/include_lua 18LUA_INCLUDEDIR := $(LUA_SRCDIR)/include_lua
19LUA_INCLUDELIST := $(addprefix $(LUA_BUILDDIR)/,audio.lua blit.lua color.lua draw.lua \ 19LUA_INCLUDELIST := $(addprefix $(LUA_BUILDDIR)/,audio.lua blit.lua color.lua draw.lua draw_floodfill.lua draw_poly.lua \
20 image.lua lcd.lua math_ex.lua print.lua \ 20 draw_text.lua image.lua image_save.lua lcd.lua math_ex.lua print.lua \
21 timer.lua playlist.lua pcm.lua sound.lua \ 21 timer.lua playlist.lua pcm.lua sound.lua \
22 rbcompat.lua printtable.lua) 22 rbcompat.lua printtable.lua)
23 23
diff --git a/apps/plugins/lua_scripts/rlimg.lua b/apps/plugins/lua_scripts/rlimg.lua
new file mode 100755
index 0000000000..801d0c5fac
--- /dev/null
+++ b/apps/plugins/lua_scripts/rlimg.lua
@@ -0,0 +1,919 @@
1--[[
2 __________ __ ___.
3 Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
7 \/ \/ \/ \/ \/
8 $Id$
9 Example Lua RBIMAGE script
10 Copyright (C) 2009 by Maurus Cuelenaere -- some prior work
11 Copyright (C) 2017 William Wilgus
12 This program is free software; you can redistribute it and/or
13 modify it under the terms of the GNU General Public License
14 as published by the Free Software Foundation; either version 2
15 of the License, or (at your option) any later version.
16 This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
17 KIND, either express or implied.
18]]--
19
20require("actions") -- Contains rb.actions & rb.contexts
21-- require("buttons") -- Contains rb.buttons -- not needed for this example
22
23local _math = require("math_ex") -- missing math sine cosine, sqrt, clamp functions
24local _timer = require("timer")
25local _clr = require("color") -- clrset, clrinc provides device independent colors
26local _lcd = require("lcd") -- lcd helper functions
27local _print = require("print") -- advanced text printing
28local _img = require("image") -- image manipulation save, rotate, resize, tile, new, load
29local _img_save = require("image_save")
30local _blit = require("blit") -- handy list of blit operations
31local _draw = require("draw") -- draw all the things (primitives)
32local _draw_floodfill = require("draw_floodfill")
33local _draw_text = require("draw_text")
34
35--local scrpath = rb.current_path()"
36
37--package.path = scrpath .. "/?.lua;" .. package.path --add lua_scripts directory to path
38
39require("printmenu") --menu
40
41--[[ RBIMAGE library functions
42NOTE!! on x, y coordinates + width & height
43----------------------------------------------
44When making a new image you specify the width and height say (10, 20).
45Intutively (at least to me) (0,0) (offset addressing) would reference the first
46pixel (top left) and the last pixel (bottom, right) would be (w-1, h-1) or (9, 19)
47but the original rbimage library (like lua) uses 1-based arrays (ordinal addressing)
48for the image data so the first pixel is (1,1) and the last pixel is (w, h)
49this presents a bit of a problem when interfacing with the internal rockbox
50functions as you must remeber to convert all lua coordinates to 0 based coordinates.
51I have opted to not change this in the name of compatibility with old scripts
52
53NOTE2!! on width & height versus offset_x & offset_y :copy()
54------------------------------------------------------------------------
55The only place where RBIMAGE deviates from (ordinal addressing) is in the blit
56/ copy function sx, sy and dx, dy still refer to the same pixel as all the
57other functions but offset_x, and offset_y are zero based
58Example (assuming same sized images)
59dst:copy(src, 1,1, 1,1, 0, 0)
60would copy the first pixel from src to the first pixel of dst
61dst:copy(src, 1,1, 1,1, dst:width()-1, dst:height()-1) would copy all of src to dst
62this might be a bit confusing but makes reversing images (negative offsets) easier.
63Since offsets are auto calculated if empty or out of range you could call it as
64dst:copy(src, 1,1, 1,1, dst:width(), dst:height()) or even
65dst:copy(src, 1,1, 1,1) if you prefered and get the same result
66]]
67
68--'CONSTANTS' (in lua there really is no such thing as all vars are mutable)
69--------------------------------------------------------
70--colors for fg/bg ------------------------
71local WHITE = _clr.set(-1, 255, 255, 255)
72local BLACK = _clr.set(0, 0, 0, 0)
73local RED = _clr.set(WHITE, 255)
74local GREEN = _clr.set(WHITE, 0, 255)
75local BLUE = _clr.set(WHITE, 0, 0, 255)
76-------------------------------------------
77local clrs
78local CANCEL_BUTTON = rb.actions.PLA_CANCEL
79
80-- EXAMPLES ---------------------------------------------------------------------- EXAMPLES---------------------------------------------------------------------
81function my_blit(dst_val, dx, dy, src_val, sx, sy)
82 -- user defined blit operation
83 --this function gets called for every pixel you specify
84 --you may change pixels in both the source and dest image
85 --return nil to stop early
86
87 if _lcd.DEPTH < 2 then
88 return src_val
89 end
90
91 if dst_val == WHITE and bit.band(dx, 1) == 1 and bit.band(dy, 1) == 1 then
92 return BLACK;
93 elseif dst_val == WHITE then
94 return src_val
95 end
96
97 return dst_val
98end
99
100function create_logo()
101 --[[creates a small logo from data array]]
102
103 -- moves scope of white and black from global to local
104 local WHITE = WHITE
105 local BLACK = BLACK
106
107 --[[small array with 16 bits of data per element (16-bits in y direction)
108 while the number of elements (32) is the x direction.
109 in other words 16 rows X 32 columns, totally abritrary actually
110 you could easily rotate or flip it by changing the for loops below ]]
111 local logo = {0xFFFF, 0xFFFF, 0x8001, 0x8001, 0x9E7F, 0x9E7F, 0x9E7F, 0x9E7F,
112 0x9E3F, 0x9E3F, 0x804F, 0x804F, 0xC0E1, 0xC0F1, 0xFFFD, 0xFFFF,
113 0xFFFF, 0xFFFF, 0x8001, 0x8001, 0xFF01, 0xFF01, 0xFEFB, 0xFEFB,
114 0xFDFD, 0xFDFD, 0xFDFD, 0xFCF9, 0xFE03, 0xFE03, 0xFFFF, 0xFFFF}
115
116 local img, img1, img2, img3
117
118 img = _img.new(_lcd.W, _lcd.H)
119 img:clear(BLACK) --[[always clear an image after you create it if you
120 intend to do any thing besides copy something
121 entirely to it as there is no guarantee what
122 state the data within is in, it could be all
123 0's or it could be every digit of PI ]]
124
125 -- check for an error condition bail if error
126 if(not img or not logo) then
127 return nil
128 end
129
130 local logosz = table.getn(logo)
131 local bits = 16 -- each element contains 16 pixels
132 local data = 0
133
134 for i=1, math.min(logosz, _lcd.W) do
135 for j=0, math.min(bits, _lcd.H) do
136
137 if bit.band(bit.lshift(1, bits - j), logo[i]) > 0 then
138 data = WHITE
139 else
140 data = BLACK
141 end
142 -- Set the pixel at position i, j+1 to the copied data
143 img:set(i, j + 1, data)
144 end
145 end
146
147 -- make a new image the size of our generated logo
148 img1 = _img.new(logosz + 1, bits + 1)
149
150 -- img.copy(dest, source, dx, dy, sx, sy, [w, h])
151 img1:copy(img, 1, 1, 1, 1)
152
153 --[[lua does auto garbage collection, but it is still
154 a good idea to set large items to nil when done anyways]]
155 img = nil
156
157 local sl -- new image size
158 if _lcd.W < _lcd.H then
159 sl = _lcd.W / 3
160 else
161 sl = _lcd.H / 3
162 end
163
164 -- make sl always even by subtracting 1 if needed
165 sl = bit.band(sl, bit.bnot(1))
166 if sl < 16 then
167 sl = 16
168 end
169
170 img2 = _img.new(sl, sl)
171 --img2:clear(BLACK) -- doesn't need cleared since we copy to it entirely
172
173 --[[we are going to resize the image since the data supplied is 32 x 16
174 pixels its really tiny on most screens]]
175 _img.resize(img2, img1)
176
177 img1 = nil
178
179 img3 = _img.new(sl, sl)
180 img3:clear(BLACK)
181
182 if IS_COLOR_TARGET == true then
183 local c_yellow = _clr.set(WHITE, 0xFC, 0xC0, 0x00)
184 local c_grey = _clr.set(WHITE, 0xD4, 0xE3, 0xF3)
185 local c_dkgrey = _clr.set(WHITE, 0xB4, 0xC3, 0xD3)
186 -- if dest pixel == source pixel make dest pixel yellow
187 img3:copy(img2, 1, 1, 1, 1, nil, nil, false, _blit.BDEQS, c_yellow)
188 -- xor src pixel to dest pixel if both are 0 or both are 1 dest = 0
189 img2:copy(img3, 1, 1, 2, 1, nil, nil, false, _blit.BXOR)
190 -- if dest pixel color > src pixel color copy grey to dest
191 img2:copy(img3, 1, 1, 1, 1, nil, nil, false, _blit.BDGTS, c_grey)
192 -- set img3 to grey
193 img3:clear(c_dkgrey)
194 end
195
196 -- make a WHITE square in the middle
197
198 img3:clear(WHITE, 4,4, img3:width() - 3, img3:height() - 3)
199
200 img3:copy(img2, 1, 1, 1, 1, nil, nil, false, _blit.CUSTOM, my_blit)
201 img2 = nil
202 _img_save(img3, "pix.bmp")
203 return img3
204end -- copy_logo
205
206-- draws an olive erm ball and returns it
207function create_ball()
208 local sl -- image size
209 if _lcd.W < _lcd.H then
210 sl = _lcd.W / 5
211 else
212 sl = _lcd.H / 5
213 end
214
215 -- make sl always even by subtracting 1 if needed
216 sl = bit.band(sl, bit.bnot(1))
217 if sl < 16 then
218 sl = 16
219 end
220 local img = _img.new(sl, sl)
221 img:clear(0)
222 _draw.circle_filled(img, sl/2, sl/2, sl/2 - 1, _clr.set(-1, 255), _clr.set(0, 100))
223 _draw.circle_filled(img, sl/3, sl/3, sl/10, _clr.set(-1, 255, 0, 0))
224 return img
225end
226
227-- bounces img around on screen
228function bounce_image(img)
229 local timer = _timer() -- creates a new timer -- saves index
230 local wait
231 -- make a copy of the current screen for later
232 local screen_img = _lcd:duplicate()
233
234 local img_sqy = _img.new(img:width() + img:width() / 8, img:height())
235 local img_sqx = _img.new(img:width(), img:height() + img:height() / 8)
236 _img.resize(img_sqy, img)
237 _img.resize(img_sqx, img)
238
239 -- moves definition of CANCEL_BUTTON from global to local
240 local CANCEL_BUTTON = CANCEL_BUTTON
241--------------------------------------------------------
242 local imgn = img
243 local hold = 0
244 local sx = 1 -- starting x
245 local sy = 1 -- starting y
246
247 local ex = _lcd.W - img:width() - 2
248 local ey = _lcd.H - img:width() - 2
249
250 -- threshold resets speed, inverts image
251 local tx = ex / 5
252 local ty = ey / 5
253
254 local last_x = sx
255 local last_y = sy
256
257 local x = sx
258 local y = sy
259
260 local dx = 1
261 local dy = 1
262 -- negative width\height cause the image to be drawn from the opposite end
263 local fx = _lcd.W
264 local fy = _lcd.H
265
266 local function invert_images()
267 img:invert();
268 img_sqx:invert()
269 img_sqy:invert()
270 end
271
272 local loops = (_lcd.W * _lcd.H) / 2
273 while (loops > 0) do
274
275 if IS_COLOR_TARGET then
276 if bit.band(loops, 128) == 128 then
277 _lcd:copy(imgn, x, y, 1, 1, fx, fy, false, _blit.BOR)
278 _lcd:copy(screen_img, x, y, x, y, imgn:width(), imgn:height(),
279 false, _blit.BDEQC, imgn:get(1,1))
280 else
281 _lcd:copy(imgn, x, y, 1, 1, fx, fy, false, _blit.BSNEC, imgn:get(1,1))
282 end
283 else
284 local blitop
285
286 if imgn:get(1,1) ~= 0 then
287 blitop = _blit.BSNOT
288 else
289 blitop = _blit.BXOR
290 end
291
292 _lcd:copy(imgn, x, y, 1, 1, fx, fy, false, blitop, WHITE)
293 end
294
295 if hold < 1 then
296 imgn = img
297 else
298 hold = hold - 1
299 end
300 _lcd:update()
301
302 x = x + dx
303 y = y + dy
304
305 if y >= ey or y <= sy then
306 dy = (-dy)
307 fy = (-fy)
308 imgn = img_sqy
309 hold = 3
310 if dx < 0 and y < 10 then
311 dx = dx - 5
312 end
313 if dx > tx then
314 dx = 5;
315 dy = 5;
316 invert_images()
317 end
318 end
319
320 if x >= ex or x <= sx then
321 dx = (-dx)
322 fx = (-fx)
323 imgn = img_sqx
324 hold = 3
325 if dy < 0 and x < 10 then
326 dy = dy - 5
327 end
328 if dy > ty then
329 dx = 5;
330 dy = 5;
331 invert_images()
332 end
333 end
334
335 x = _math.clamp(x, sx, ex)
336 y = _math.clamp(y, sy, ey)
337
338 -- copy original image back to screen
339 _lcd:copy(screen_img)
340
341 loops = loops -1
342
343 wait = timer:check(true) --checks timer and updates last time
344 if wait >= 5 then
345 wait = 0
346 elseif wait < 5 then
347 wait = 5 - wait
348 end
349 -- 0 = timeout immediately
350 -- ( -1 would be never timeout, and >0 is amount of 'ticks' before timeout)
351 if rb.get_plugin_action(wait) == CANCEL_BUTTON then
352 break;
353 end
354 end
355
356 timer:stop() -- destroys timer, also returns time since last time
357
358 -- leave the screen how we found it
359 _lcd:copy(screen_img)
360end -- image_bounce
361
362-- draws a gradient using available colors
363function draw_gradient(img, x, y, w, h, direction, clrs)
364 x = x or 1
365 y = y or 1
366 w = w or img:width() - x
367 h = h or img:height() - y
368 local zstep = 0
369 local step = 1
370 if IS_COLOR_TARGET == true then -- Only do this when we're on a color target
371 local z = 1
372 local c = 1
373 clrs = clrs or {255,255,255}
374 local function gradient_rgb(p, c1, c2)
375 -- tried squares of difference but blends were very abrupt
376 local r = c1.r + (p * (c2.r - c1.r) / 10500)
377 local g = c1.g + (p * (c2.g - c1.g) / 10000)
378 local b = c1.b + (p * (c2.b - c1.b) / 09999)
379 return _clr.set(nil, r, g, b)
380 end
381 local function check_z()
382 if z > 10000 and c < #clrs - 1 then
383 z = 1
384 c = c + 1
385 elseif z > 10000 then
386 z = 10000
387 end
388 end
389 if direction == "V" then
390 zstep = math.max(1, (10000 / ((w - 1) / (#clrs - 1)) + bit.band(#clrs, 1)))
391 for i=x, w + x do
392 check_z()
393 _draw.vline(img, i, y, h, gradient_rgb(z, clrs[c], clrs[c + 1]))
394 z = z + zstep
395 end
396 else
397 zstep = math.max(1, (10000 / ((h - 1) / (#clrs - 1)) + bit.band(#clrs, 1)))
398 for j=y, h + y do
399 check_z()
400 _draw.hline(img, x, j, w, gradient_rgb(z, clrs[c], clrs[c + 1]))
401 z = z + zstep
402 end
403 end
404 else -- not a color target but might be greyscale
405 local clr = _clr.set(-1)
406 for i=x, w + x do
407 for j=y, h + y do
408 -- Set the pixel at position i, j to the specified color
409 img:set(i, j, clr)
410 end
411 clr = _clr.inc(clr, 1)
412 end
413 end
414--rb.sleep(1000)
415end -- draw_gradient
416
417function twist(img)
418--[[ local fg
419 if rb.lcd_get_foreground then
420 fg = rb.lcd_get_foreground()
421 end]]
422
423 local ims = {}
424 ims.strip = _img.tile(img, img:width(), _lcd.H + img:height())
425 ims.y_init = {img:height(), 1}
426 ims.y_finl = {1, img:height()}
427 ims.y_inc = {-2, 4}
428 ims.y_pos = nil
429
430 -- together define the width of the overall object
431 local x_off=(_lcd.W/2)
432 local m = _lcd.W
433 local z = -m
434 local zi = 1
435
436 -- angles of rotation for each leaf
437 local ANGLES = {0, 45, 90, 135, 180, 225, 270, 315}
438 local elems = #ANGLES
439 local _XCOORD = {}
440
441 -- color alternates each leaf
442 local colors = { WHITE, _clr.set(0, 0, 0, 0) }
443 local c = 0
444
445 -- calculated position of each point in the sine wave(s)
446 local xs, xe
447
448 --[[--Profiling code
449 local timer = _timer.start()]]
450
451 for rot = 0, 6000, 4 do
452 _lcd:clear(BLACK)
453
454 for y=1, _lcd.H do
455
456 local function get_sines()
457 local sc = m + z
458 if sc == 0 then
459 sc = 1 -- prevent divide by 0
460 elseif sc + z > _lcd.W then
461 zi = -1
462 colors[2] = _clr.inc(colors[2], 1, 0, 50, 0)
463 elseif sc + z < -(_lcd.W) then
464 zi = 1
465 colors[1] = _clr.inc(colors[1], -1, 0, 10, 0)
466 end
467 if colors[2] == colors[1] then
468 colors[2] = _clr.inc(colors[2], 1)
469 end
470 for j = 1, elems do
471 _XCOORD[j] = _math.d_sin(y + ANGLES[j] + rot) / sc + x_off
472 end
473 _XCOORD[0] = _XCOORD[elems] -- loop table for efficient wrap
474 end
475
476 get_sines()
477 for k = 1, elems do
478 xs = _XCOORD[k]
479 xe = _XCOORD[(k+1) % elems]
480 if xs < 1 or xe > _lcd.W then
481 while xs < 1 or xe > _lcd.W do
482 m = m + 1 -- shift m in order to scale object min/max
483 get_sines()
484 xs = _XCOORD[k]
485 xe = _XCOORD[(k+1) % elems]
486 end
487 end
488 c = (c % 2) + 1
489 if xs < xe then
490 -- defines the direction of leaves & fills them
491
492 _lcd:set(xs, y, colors[c])
493 _lcd:set(xe, y, colors[c])
494 _lcd:line(xs + 1, y, xe - 1, y, colors[3 - c], true)
495 end
496 end
497
498 end
499
500 do -- stripes and shifts image strips; blits it into the colors(1) leaves
501 local y
502 local y_col = 1
503 local w = ims.strip:width() - 1
504 local h = ims.strip:height() - 1
505 if ims.y_pos ~= nil then
506 for i = 1, #ims.y_pos do
507 ims.y_pos[i] = ims.y_pos[i] + ims.y_inc[i]
508
509 if (ims.y_inc[i] > 0 and ims.y_pos[i] > ims.y_finl[i])
510 or (ims.y_inc[i] < 0 and ims.y_pos[i] < ims.y_finl[i]) then
511 ims.y_pos[i] = ims.y_init[i]
512 end
513 end
514 else
515 ims.y_pos = {ims.y_init[1], ims.y_init[2]}
516 end
517
518 for ix = 1, _lcd.W, w do
519 y_col = y_col + 1
520 y = ims.y_pos[(y_col % 2) + 1]
521 if _lcd.DEPTH > 1 then
522 _lcd:copy(ims.strip, ix, 1, 1, y, w, h, false, _blit.BDEQC, colors[1])
523 else
524 _lcd:copy(ims.strip, ix, 1, 1, y, w, h, false, _blit.BSAND)
525 end
526 end
527 end
528
529 _lcd:update()
530 z = z + zi
531
532 if rb.get_plugin_action(0) == CANCEL_BUTTON then
533 break
534 end
535 collectgarbage("step")
536 end
537 --[[--Profiling code
538 _print.f("%d", _timer.stop(timer))
539 rb.sleep(rb.HZ * 10)]]
540end -- twist
541
542function draw_target(img)
543
544 local clr = _clr.set(0, 0, 0, 0)
545
546 -- make a copy of original screen for restoration
547 local screen_img = _lcd:duplicate()
548
549 rad_m = math.min(_lcd.W, _lcd.H)
550
551 for s = -_lcd.W /4, 16 do
552 img:copy(screen_img)
553 s = math.max(1, math.abs(s))
554 for r = 1, rad_m /2 - 10, s do
555 clr = _clr.inc(clr, 1, r * 5, r * 10, r * 20)
556 _draw.circle(img, _lcd.CX, _lcd.CY, r, clr)
557 end
558
559 _lcd:update()
560 if rb.get_plugin_action( 20) == CANCEL_BUTTON then
561 z = 16;
562 break;
563 end
564 end
565
566end -- draw_target
567
568function draw_sweep(img, cx, cy, radius, color)
569 local timer = _timer() --creates a new timer saves index
570 local wait
571 local x
572 local y
573 --make a copy of original screen for restoration
574 local screen_img = _lcd:duplicate()
575 _draw.circle(img, cx, cy, radius, color)
576 for d = 630, 270, - 5 do
577 if d % 45 == 0 then
578 img:copy(screen_img)
579 _draw.circle(img, cx, cy, radius, color)
580 l = 0
581 end
582 x = cx + radius * _math.d_cos(d) / 10000
583 y = cy + radius * _math.d_sin(d) / 10000
584
585
586 _draw.line(img, cx, cy, x, y, color)
587 l = l + 1
588 if l > 1 then
589 x1 = cx + (radius - 1) * _math.d_cos(d + 1) / 10000
590 y1 = cy + (radius - 1) * _math.d_sin(d + 1) / 10000
591 _draw_floodfill(img, x1, y1, BLACK, color)
592 end
593 _lcd:update()
594 wait = timer:check(true) --checks timer and updates last time
595 if wait >= 50 then
596 wait = 0
597 elseif wait < 50 then
598 wait = 50 - wait
599 end
600 if rb.get_plugin_action( wait) == CANCEL_BUTTON then
601 break
602 end
603 end
604 timer:stop() --destroys timer, also returns time since last time
605 screen_img = nil
606end -- draw_sweep
607
608function rotate_image(img)
609 local blitop = _blit.BOR
610 local i = 1
611 local d = 0
612 local ximg
613 local x, y, w, h, xr, yr
614
615 ximg = _img.rotate(img, 45) -- image will be largest at this point
616 w = ximg:width()
617 h = ximg:height()
618 xr = (_lcd.W - w) / 2
619 yr = (_lcd.H - h) / 2
620 --make a copy of original screen for restoration
621 local screen_img -- = _lcd:duplicate()
622 screen_img =_img.new(w, h)
623 screen_img :copy(_LCD, 1, 1, xr, yr, w, h)
624 --_print.f("CW")
625
626 --[[--Profiling code
627 local timer = _timer.start()]]
628
629 while d >= 0 do
630 ximg = _img.rotate(img, d)
631 w = ximg:width()
632 h = ximg:height()
633 x = (_lcd.W - w) / 2
634 y = (_lcd.H - h) / 2
635
636 -- copy our rotated image onto the background
637 _lcd:copy(ximg, x, y, 1, 1, w, h, false, blitop)
638 _lcd:update()
639 --restore the portion of the background we destroyed
640 _lcd:copy(screen_img, xr, yr, 1, 1)
641
642 if d > 0 and d % 360 == 0 then
643 _lcd:copy(ximg, x, y, 1, 1, w, h)
644 _lcd:update()
645 if i == 1 then i = 0 end
646 if d == 1440 or i < 0 then
647 if i < 0 then
648 i = i - 5
649 else
650 i = - 5
651 end
652 blitop = _blit.BXOR
653 --_print.f("CCW")
654 --rb.sleep(rb.HZ)
655 else
656 i = i + 5
657 --_print.f("CW")
658 --rb.sleep(rb.HZ)
659 end
660
661 end
662 d = d + i
663
664 if rb.get_plugin_action(0) == CANCEL_BUTTON then
665 break;
666 end
667 end
668
669 _lcd:copy(ximg, x, y, 1, 1, w, h)
670 --[[-- Profiling code
671 _print.f("%d", _timer.stop(timer))
672 rb.sleep(rb.HZ * 10)]]
673end -- rotate_image
674
675-- shows blitting with a mask
676function blit_mask(dst)
677 local timer = _timer()
678 local r = math.min(_lcd.CX, _lcd.CY) / 5
679
680 local bmask = _img.new(_lcd.W, _lcd.H)
681 bmask:clear(0)
682
683 _draw.circle_filled(bmask, _lcd.CX, _lcd.CY, r, WHITE)
684 local color = _clr.set(0, 0, 0 ,0)
685 for z = 0, 100 do
686 z = z + timer:check(true)
687 color = _clr.inc(color, 1, z * 5, z * 10, z * 20)
688 dst:copy(bmask, 1, 1, 1, 1, nil, nil, false, _blit.BSAND, color)
689 _lcd:update()
690
691 if rb.get_plugin_action(0) == CANCEL_BUTTON then
692 break
693 end
694 end
695end -- blit_mask
696
697-- draws an X on the screen
698function draw_x()
699 _draw.line(_LCD, 1, 1, _lcd.W, _lcd.H, WHITE)
700 _draw.line(_LCD, _lcd.W, 1, 1, _lcd.H, WHITE)
701
702 _draw.hline(_LCD, 10, _lcd.CY , _lcd.W - 21, WHITE)
703
704 _draw.vline(_LCD, _lcd.CX, 20 , _lcd.H - 41, WHITE)
705
706 _draw.rect(_LCD, _lcd.CX - 17, _lcd.CY - 17, 34, 34, WHITE)
707 _lcd:update()
708 rb.sleep(100)
709end -- draw_x
710
711--fills an image with random colors
712function random_img(img)
713 local min = _clr.set(0, 0, 0, 0)
714 local max = _clr.set(-1, 255, 255, 255)
715 math.randomseed(rb.current_tick())
716 for x = 1, img:width() do
717 for y = 1, img:height() do
718 img:set(x, y, math.random(min, max))
719 end
720 end
721end -- random_img
722
723function rainbow_img(img)
724--draw a gradient using available colors
725 if IS_COLOR_TARGET == true then
726 --R O Y G B I V
727 clrs = {
728 {r = 255, g = 255, b = 255}, -- white
729 {r = 000, g = 000, b = 000}, -- black
730 {r = 200, g = 000, b = 000}, -- red
731 {r = 255, g = 000, b = 000}, -- red
732 {r = 255, g = 100, b = 033}, -- orange
733 {r = 255, g = 127, b = 000}, -- orange
734 {r = 255, g = 200, b = 033}, -- yellow
735 {r = 255, g = 255, b = 000}, -- yellow
736 {r = 050, g = 255, b = 000}, -- green
737 {r = 000, g = 125, b = 125}, -- green
738 {r = 000, g = 000, b = 255}, -- blue
739 {r = 033, g = 025, b = 200}, -- indigo
740 {r = 075, g = 000, b = 150}, -- indigo
741 {r = 127, g = 000, b = 150}, -- violet
742 {r = 150, g = 000, b = 255}, -- violet
743 {r = 255, g = 255, b = 255}, -- white
744 {r = 000, g = 000, b = 000}, -- black
745 }
746 else
747 end
748 draw_gradient(img, 1, 1, nil, nil, "V", clrs)
749end -- rainbow_img
750
751-- draws a rounded rectangle with text
752function rock_lua()
753 local res, w, h = _lcd:text_extent("W", rb.FONT_UI)
754 w = _lcd.W - 10
755 h = h + 4
756 _draw.rounded_rect_filled(_LCD, 5, 5, w, h, 15, WHITE)
757 _draw_text(_LCD, 5, 5, w, h, nil, BLACK, "ROCKlua!")
758 _lcd:update()
759 rb.sleep(100)
760end -- rock_lua
761
762-- draws a rounded rectangle with long text
763function long_text()
764 local txt = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890"
765 local res, w, h = _lcd:text_extent(txt, rb.FONT_UI)
766 local resp, wp, hp = _lcd:text_extent(" ", rb.FONT_UI)
767 local wait = 0
768 w = w + wp * 3
769 h = h + 4
770 local img = _img.new(w + 1, h)
771 img:clear(BLACK)
772 _draw.rounded_rect_filled(img, 1, 1, w, h, 15, WHITE)
773 _draw_text(img, 1, 2, nil, nil, nil, BLACK, txt)
774
775 for p = -w + 1, w - 1 do
776 wait = 0
777 p = math.abs(p)
778 _lcd:copy(img, 1, _lcd.H - h, w - p, 1)
779 _lcd:update()
780 if p == 0 or w - p == 1 then wait = 100; rb.sleep(50) end
781 if rb.get_plugin_action(wait) == CANCEL_BUTTON then
782 break
783 end
784 end
785
786end -- long_text
787
788-- creates or loads an image to use as logo
789function get_logo()
790 local logo_img = _img.load("/pix.bmp") --loads the previously saved image (if we saved it before)
791
792 --create a logo if an image wasn't saved previously
793 if(not logo_img) then
794 logo_img = create_logo()
795 end
796
797 --fallback
798 if(not logo_img) then
799 -- Load a BMP file in the variable backdrop
800 local base = "/.rockbox/icons/"
801 local backdrop = _img.load("/image.bmp") --user supplied image
802 or _img.load(base .. "tango_small_viewers.bmp")
803 or _img.load(base .. "tango_small_viewers_mono.bmp")
804 or _img.load(base .. "tango_small_mono.bmp")
805 or _img.load(base .. "tango_icons.16x16.bmp")
806 or _img.load(base .. "tango_icons_viewers.16x16.bmp")
807 or _img.load(base .. "viewers.bmp")
808 or _img.load(base .. "viewers.6x8x1.bmp")
809 or _img.load(base .. "viewers.6x8x2.bmp")
810 or _img.load(base .. "viewers.6x8x10.bmp")
811 or _img.load(base .. "viewers.6x8x16.bmp")
812 logo_img = backdrop
813 end
814 return logo_img
815end -- get_logo
816
817-- uses print_table to display a menu
818function main_menu()
819
820 local mt = {
821 [1] = "Rocklua RLI Example",
822 [2] = "The X",
823 [3] = "Blit Mask",
824 [4] = "Target",
825 [5] = "Sweep",
826 [6] = "Bouncing Ball (olive)",
827 [7] = "The Twist",
828 [8] = "Image Rotation",
829 [9] = "Long Text",
830 [10] = "Rainbow Image",
831 [11] = "Random Image",
832 [12] = "Clear Screen",
833 [13] = "Save Screen",
834 [14] = "Exit"
835 }
836 local ft = {
837 [0] = exit_now, --if user cancels do this function
838 [1] = function(TITLE) return true end, -- shouldn't happen title occupies this slot
839 [2] = function(THE_X) draw_x() end,
840 [3] = function(BLITM) blit_mask(_lcd()) end,
841 [4] = function(TARGT) draw_target(_lcd()) end,
842 [5] = function(SWEEP)
843 local r = math.min(_lcd.CX, _lcd.CY) - 20
844 draw_sweep(_lcd(), _lcd.CX, _lcd.CY, r, _clr.set(-1, 0, 255, 0))
845 end,
846 [6] = function(BOUNC) bounce_image(create_ball()) end,
847 [7] = function(TWIST) twist(get_logo()) end,
848 [8] = function(ROTAT) rotate_image(get_logo()) end,
849 [9] = long_text,
850 [10] = function(RAINB)
851 rainbow_img(_lcd()); _lcd:update(); rb.sleep(rb.HZ)
852 end,
853 [11] = function(RANDM)
854 random_img(_lcd()); _lcd:update(); rb.sleep(rb.HZ)
855 end,
856 [12] = function(CLEAR) _lcd:clear(BLACK); rock_lua() end,
857 [13] = function(SAVEI) _LCD:invert(); _img_save(_LCD, "/rocklua.bmp") end,
858 [14] = function(EXIT_) return true end
859 }
860
861 if _lcd.DEPTH < 2 then
862 table.remove(mt, 10)
863 table.remove(ft, 10)
864 end
865
866 print_menu(mt, ft)
867
868end
869--------------------------------------------------------------------------------
870function exit_now()
871 _lcd:update()
872 _lcd:splashf(rb.HZ * 5, "ran for %d seconds", _timer.stop("main") / rb.HZ)
873 os.exit()
874end -- exit_now
875--------------------------------------------------------------------------------
876
877--MAIN PROGRAM------------------------------------------------------------------
878_timer("main") -- keep track of how long the program ran
879
880-- Clear the screen
881_lcd:clear(BLACK)
882
883if _lcd.DEPTH > 1 then
884--draw a gradient using available colors
885if IS_COLOR_TARGET == true then
886 clrs = {
887 {r = 255, g = 000, b = 000}, -- red
888 {r = 000, g = 255, b = 000}, -- green
889 {r = 000, g = 000, b = 255}, -- blue
890 }
891else
892end
893 local w = bit.rshift(_lcd.W, 2)
894 local h = bit.rshift(_lcd.H, 2)
895 draw_gradient(_lcd(), (_lcd.W - w)/2 - 1, (_lcd.H - h)/3 - 1, w, h, "H", clrs)
896 _lcd:update()
897 rb.sleep(rb.HZ)
898end
899
900do
901local img = _img.load("/rocklua.bmp")
902 if not img then
903 rock_lua()
904 else
905 _lcd:image(img)
906 end
907end
908_lcd:update()
909rb.sleep(rb.HZ / 2)
910
911if rb.cpu_boost then rb.cpu_boost(true) end
912
913main_menu()
914
915if rb.cpu_boost then rb.cpu_boost(false) end
916
917exit_now()
918
919-- For a reference list of all functions available, see apps/plugins/lua/rocklib.c (and apps/plugin.h)