forked from len0rd/rockbox
		
	
		
			
				
	
	
		
			205 lines
		
	
	
	
		
			7.3 KiB
		
	
	
	
		
			Lua
		
	
	
	
	
	
			
		
		
	
	
			205 lines
		
	
	
	
		
			7.3 KiB
		
	
	
	
		
			Lua
		
	
	
	
	
	
| --[[ Lua Image functions
 | |
| /***************************************************************************
 | |
|  *             __________               __   ___.
 | |
|  *   Open      \______   \ ____   ____ |  | _\_ |__   _______  ___
 | |
|  *   Source     |       _//  _ \_/ ___\|  |/ /| __ \ /  _ \  \/  /
 | |
|  *   Jukebox    |    |   (  <_> )  \___|    < | \_\ (  <_> > <  <
 | |
|  *   Firmware   |____|_  /\____/ \___  >__|_ \|___  /\____/__/\_ \
 | |
|  *                     \/            \/     \/    \/            \/
 | |
|  * $Id$
 | |
|  *
 | |
|  * Copyright (C) 2017 William Wilgus
 | |
|  *
 | |
|  * This program is free software; you can redistribute it and/or
 | |
|  * modify it under the terms of the GNU General Public License
 | |
|  * as published by the Free Software Foundation; either version 2
 | |
|  * of the License, or (at your option) any later version.
 | |
|  *
 | |
|  * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
 | |
|  * KIND, either express or implied.
 | |
|  *
 | |
|  ****************************************************************************/
 | |
| ]]
 | |
| 
 | |
| --[[ Exposed Functions
 | |
| 
 | |
|     _img.search
 | |
|     _img.rotate
 | |
|     _img.resize
 | |
|     _img.tile
 | |
|     _img.new
 | |
|     _img.load
 | |
| 
 | |
| -- Exposed Constants
 | |
|     _img.RLI_INFO_ALL
 | |
|     _img.RLI_INFO_TYPE
 | |
|     _img.RLI_INFO_WIDTH
 | |
|     _img.RLI_INFO_HEIGHT
 | |
|     _img.RLI_INFO_ELEMS
 | |
|     _img.RLI_INFO_BYTES
 | |
|     _img.RLI_INFO_DEPTH
 | |
|     _img.RLI_INFO_FORMAT
 | |
|     _img.RLI_INFO_ADDRESS
 | |
| 
 | |
| ]]
 | |
| 
 | |
| --[[Other rbimage Functions:
 | |
| --------------------------------------------------------------------------------
 | |
| img:_len() or #img -- returns number of pixels in image
 | |
| 
 | |
| img:__tostring([item]) or tostring(img) -- returns data about the image item = 0
 | |
|                                          is the same as tostring(img) otherwise
 | |
|                                          item = 1 is the first item in list
 | |
|                                          item = 7 is the 7th item
 | |
|                                          item = 8 is the data address in hex
 | |
|                                         -- See Constants _img.RLI_INFO_....
 | |
| 
 | |
| img:_data(element) -- returns/sets raw pixel data
 | |
|                       NOTE!! this data is defined by the target and targets with
 | |
|                       different color depth, bit packing, etc will not be
 | |
|                       compatible with the same image's data on another target
 | |
| ]]
 | |
| --------------------------------------------------------------------------------
 | |
| if not rb.lcd_framebuffer then rb.splash(rb.HZ, "No Support!") return nil end
 | |
| 
 | |
| local _img = {} do
 | |
| 
 | |
|     local rocklib_image = getmetatable(rb.lcd_framebuffer())
 | |
|     setmetatable(_img, rocklib_image)
 | |
| 
 | |
|     -- internal constants
 | |
|     local _NIL = nil -- _NIL placeholder
 | |
|     local _math = require("math_ex") -- math functions needed
 | |
|     local LCD_W, LCD_H = rb.LCD_WIDTH, rb.LCD_HEIGHT
 | |
| 
 | |
|     local _copy    = rocklib_image.copy
 | |
|     local _get     = rocklib_image.get
 | |
|     local _marshal = rocklib_image.marshal
 | |
|     local _points  = rocklib_image.points
 | |
| 
 | |
|     -- returns new image -of- img sized to fit w/h tiling to fit if needed
 | |
|     _img.tile = function(img, w, h)
 | |
|         local hs , ws = img:height(), img:width()
 | |
|         local t_img = rb.new_image(w, h)
 | |
| 
 | |
|         for x = 1, w, ws do _copy(t_img, img, x, 1, 1, 1) end
 | |
|         for y = hs, h, hs do _copy(t_img, t_img, 1, y, 1, 1, w, hs) end
 | |
|         return t_img
 | |
|     end
 | |
| 
 | |
|     -- resizes src to size of dst
 | |
|     _img.resize = function(dst, src)
 | |
|         -- simple nearest neighbor resize derived from rockbox - pluginlib_bmp.c
 | |
|         -- pretty rough results highly recommend building one more suited..
 | |
|         local dw, dh = dst:width(), dst:height()
 | |
| 
 | |
|         local xstep = (bit.lshift(src:width(), 8) / (dw)) + 1
 | |
|         local ystep = (bit.lshift(src:height(), 8) / (dh))
 | |
| 
 | |
|         local xpos, ypos = 0, 0
 | |
|         local src_x, src_y
 | |
| 
 | |
|         -- walk the dest get src pixel
 | |
|         local function rsz_trans(val, x, y)
 | |
|             if x == 1 then
 | |
|                 src_y = bit.rshift(ypos,8) + 1
 | |
|                 xpos = xstep - bit.rshift(xstep,4) + 1
 | |
|                 ypos = ypos + ystep;
 | |
|             end
 | |
|             src_x = bit.rshift(xpos,8) + 1
 | |
|             xpos = xpos + xstep
 | |
|             return (_get(src, src_x, src_y, true) or 0)
 | |
|         end
 | |
|         --/* (dst*, [x1, y1, x2, y2, dx, dy, clip, function]) */
 | |
|         _marshal(dst, 1, 1, dw, dh, _NIL, _NIL, false, rsz_trans)
 | |
|     end
 | |
| 
 | |
|     -- returns new image -of- img rotated in whole degrees 0 - 360
 | |
|     _img.rotate = function(img, degrees)
 | |
|         -- we do this backwards as if dest was the unrotated object
 | |
|         degrees = 360 - degrees
 | |
|         local c, s = _math.d_cos(degrees), _math.d_sin(degrees)
 | |
| 
 | |
|         -- get the center of the source image
 | |
|         local s_xctr, s_yctr = img:width() / 2, img:height() / 2
 | |
| 
 | |
|         -- get the the new center of the dest image at rotation angle
 | |
|         local d_xctr = ((math.abs(s_xctr * c) + math.abs(s_yctr * s))/ 10000) + 1
 | |
|         local d_yctr = ((math.abs(s_xctr * s) + math.abs(s_yctr * c))/ 10000) + 1
 | |
| 
 | |
|         -- calculate size of rect new image will occupy
 | |
|         local dw, dh = d_xctr * 2 - 1, d_yctr * 2 - 1
 | |
| 
 | |
|         local r_img = rb.new_image(dw, dh)
 | |
|         -- r_img:clear() -- doesn't need cleared as we walk every pixel
 | |
| 
 | |
|         --[[rotation works on origin of 0,0 we need to offset to the center of the
 | |
|             image and then place the upper left back at the origin (0, 0)]]
 | |
|         --[[0,0|-----| ^<  |-------| v> 0,0|-------|
 | |
|                |     |    |  0,0  |       |       |
 | |
|                |_____|   |_______|       |_______|  ]]
 | |
| 
 | |
|         -- walk the dest get translated src pixel, oversamples src to fill gaps
 | |
|         local function rot_trans(val, x, y)
 | |
|             -- move center x/y to the origin
 | |
|             local xtran = x - d_xctr;
 | |
|             local ytran = y - d_yctr;
 | |
| 
 | |
|             -- rotate about the center of the image by x degrees
 | |
|             local yrot = ((xtran * s) + (ytran * c)) / 10000 + s_yctr
 | |
|             local xrot = ((xtran * c) - (ytran * s)) / 10000 + s_xctr
 | |
|             -- upper left of src image back to origin, copy src pixel
 | |
|             return _get(img, xrot, yrot, true) or 0
 | |
|         end
 | |
|         _marshal(r_img, 1, 1, dw, dh, _NIL, _NIL, false, rot_trans)
 | |
|         return r_img
 | |
|     end
 | |
| 
 | |
|     --searches an image for target color
 | |
|     _img.search = function(img, x1, y1, x2, y2, targetclr, variation, stepx, stepy)
 | |
| 
 | |
|         if variation > 128 then variation = 128 end
 | |
|         if variation < -128 then variation = -128 end
 | |
| 
 | |
|         local targeth = targetclr + variation
 | |
|         local targetl = targetclr - variation
 | |
| 
 | |
|         if targeth < targetl then
 | |
|             local swap = targeth
 | |
|             targeth = targetl
 | |
|             targetl = swap
 | |
|         end
 | |
| 
 | |
|         for point, x, y in _points(img, x1, y1, x2, y2, stepx, stepy) do
 | |
|             if point >= targetl and point <= targeth then
 | |
|                 return point, x, y
 | |
|             end
 | |
|         end
 | |
|         return nil, nil, nil
 | |
|     end
 | |
| 
 | |
|     --[[ we won't be extending these into RLI_IMAGE]]
 | |
|     -- creates a new rbimage size w x h
 | |
|     _img.new = function(w, h)
 | |
|         return rb.new_image(w, h)
 | |
|     end
 | |
| 
 | |
|     -- returns new image -of- file: name (_NIL if error)
 | |
|     _img.load = function(name)
 | |
|         return rb.read_bmp_file("/" .. name)
 | |
|     end
 | |
| 
 | |
|     -- expose tostring constants to outside through _img table
 | |
|     _img.RLI_INFO_ALL     = 0x0
 | |
|     _img.RLI_INFO_TYPE    = 0x1
 | |
|     _img.RLI_INFO_WIDTH   = 0x2
 | |
|     _img.RLI_INFO_HEIGHT  = 0x3
 | |
|     _img.RLI_INFO_ELEMS   = 0x4
 | |
|     _img.RLI_INFO_BYTES   = 0x5
 | |
|     _img.RLI_INFO_DEPTH   = 0x6
 | |
|     _img.RLI_INFO_FORMAT  = 0x7
 | |
|     _img.RLI_INFO_ADDRESS = 0x8
 | |
| end -- _img functions
 | |
| 
 | |
| return _img
 | |
| 
 |