Adrien Destugues f4bfaeca89 Add scripts to color-reduce pictures with constraints
Scripts for various Thomson machines, Oric and ZX. All the hard work of
Samuel Devulder, with extensive research on color palette reduction
algorithms, lots of testing, research and debugging.

Thanks a lot!
2017-03-21 21:48:39 +01:00

83 lines
2.1 KiB
Lua

-- ostro_to8.lua : convert a color image to a BM16
-- (160x200x16) thomson image using the Ostromoukhov's
-- error diffusion algorithm.
--
-- Version: 02-jan-2017
--
-- Copyright 2016-2017 by Samuel Devulder
--
-- 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; version 2 of the License.
-- See <http://www.gnu.org/licenses/>
run('lib/thomson.lua')
run('lib/ostromoukhov.lua')
run('lib/color_reduction.lua')
-- run('lib/zzz.lua')
-- get screen size
local screen_w, screen_h = getpicturesize()
-- Converts thomson coordinates (0-159,0-199) into screen coordinates
local function thom2screen(x,y)
local i,j;
if screen_w/screen_h < 1.6 then
i = x*screen_h/200
j = y*screen_h/200
else
i = x*screen_w/320
j = y*screen_w/320
end
return math.floor(i*2), math.floor(j)
end
-- return the Color @(x,y) in normalized linear space (0-1)
-- corresonding to the thomson screen (x in 0-319, y in 0-199)
local function getLinearPixel(x,y)
local x1,y1 = thom2screen(x,y)
local x2,y2 = thom2screen(x+1,y+1)
if x2==x1 then x2=x1+1 end
if y2==y1 then y2=y1+1 end
local p = Color:new(0,0,0);
for j=y1,y2-1 do
for i=x1,x2-1 do
p:add(getLinearPictureColor(i,j))
end
end
p:div((y2-y1)*(x2-x1)) --:floor()
return p
end
local red = ColorReducer:new():analyzeWithDither(160,200,
getLinearPixel,
function(y)
thomson.info("Collecting stats...",math.floor(y/2),"%")
end)
-- BM16 mode
thomson.setBM16()
-- define palette
local palette = red:boostBorderColors():buildPalette(16)
thomson.palette(0, palette)
-- convert picture
OstroDither:new(palette, 0)
:dither(thomson.h,thomson.w,
function(y,x) return getLinearPixel(x,y) end,
function(y,x,c) thomson.pset(x,y,c) end,
true,
function(x) thomson.info("Converting...",math.floor(x*100/160),"%") end)
-- refresh screen
setpicturesize(320,200)
thomson.updatescreen()
finalizepicture()
-- save picture
thomson.savep()