summaryrefslogtreecommitdiff
path: root/apps/plugins/lua_scripts/rlimg.lua
diff options
context:
space:
mode:
Diffstat (limited to 'apps/plugins/lua_scripts/rlimg.lua')
-rwxr-xr-xapps/plugins/lua_scripts/rlimg.lua919
1 files changed, 919 insertions, 0 deletions
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)