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!
This commit is contained in:
Adrien Destugues
2017-03-21 21:48:39 +01:00
parent 32b3996cb8
commit f4bfaeca89
18 changed files with 3274 additions and 0 deletions

View File

@@ -0,0 +1,141 @@
-- ostro_zx.lua : converts a color image into a
-- ZX-like image (8+8 fixed colors with color clash)
-- using Ostromoukhov's error diffusion algorithm.
--
-- Version: 03/21/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('../../thomson/lib/ostromoukhov.lua')
-- get screen size
local screen_w, screen_h = getpicturesize()
OtherDither = {}
function OtherDither:new(a)
local o = { -- default ZX values
-- width of the screen
width=a and a.width or 256,
-- height of the screen
height=a and a.height or 192,
-- size of Nx1 clash size
clash_size=a and a.clash_size or 8,
-- normalize the picture levels (like in imagemagick)
normalize=a and a.normalize or 0.005,
-- put a pixel
pset=a and a.pset or function(self,x,y,c)
if c<0 then c=-c-1 end
self.screen[x+y*self.width] = c
end,
-- init gfx data
setGfx=a and a.setGfx or function(self)
self.screen={}
end,
-- update gfx to screen
updatescreen=a and a.updatescreen or function(self)
for i=0,255 do setcolor(i,0,0,0) end
for y=0,self.height-1 do
for x=0,self.width-1 do
putpicturepixel(x,y,self.screen[x+y*self.width] or 0)
end
end
-- refresh palette
for i,v in ipairs(self.pal) do
local r=v % 16
local g=math.floor(v/16) % 16
local b=math.floor(v/256) % 16
setcolor(i+thomson._palette.offset-1,
thomson.levels.pc[r+1],
thomson.levels.pc[g+1],
thomson.levels.pc[b+1])
end
updatescreen()
end,
-- palette with thomson ordering (to use thomson's
-- lib support)
pal= a and a.pal or {
0x000,0xF00,0x00F,0xF0F,0x0F0,0xFF0,0x0FF,0xFFF,
0x000,0x200,0x002,0x202,0x020,0x220,0x022,0x222
}
}
setmetatable(o, self)
self.__index = self
return o
end
-- Converts ZX coordinates (0-255,0-191) into screen coordinates
function OtherDither:to_screen(x,y)
local i,j;
if screen_w/screen_h < self.width/self.height then
i = x*screen_h/self.height
j = y*screen_h/self.height
else
i = x*screen_w/self.width
j = y*screen_w/self.width
end
return math.floor(i), math.floor(j)
end
-- return the Color @(x,y) in linear space (0-255)
-- corresonding to the other platform screen
OtherDither._getLinearPixel = {} -- cache
function OtherDither:getLinearPixel(x,y)
local k=x+y*self.width
local p = self._getLinearPixel and self._getLinearPixel[k]
if not p then
local x1,y1 = self:to_screen(x,y)
local x2,y2 = self:to_screen(x+1,y+1)
if x2==x1 then x2=x1+1 end
if y2==y1 then y2=y1+1 end
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()
if self._getLinearPixel then
self._getLinearPixel[k]=p
end
end
return self._getLinearPixel and p:clone() or p
end
function OtherDither:ccAcceptCouple(c1,c2)
-- bright colors can't mix with dimmed ones
return c1~=c2 and ((c1<=8 and c2<=8) or (c1>8 and c2>8))
end
function OtherDither:dither()
local NORMALIZE=Color.NORMALIZE
Color.NORMALIZE=self.normalize
local dither=OstroDither:new(self.pal)
dither.ccAcceptCouple = function(dither,c1,c2) return self:ccAcceptCouple(c1,c2) end
dither.clash_size = self.clash_size
dither.attenuation = .9
self:setGfx()
dither:ccDither(self.width,self.height,
function(x,y) return self:getLinearPixel(x,y) end,
function(x,y,c) self:pset(x,y,c) end,
true,
function(y)
thomson.info("Converting...",
math.floor(y*100/self.height),"%")
end,true)
-- refresh screen
setpicturesize(self.width,self.height)
self:updatescreen()
finalizepicture()
Color.NORMALIZE=NORMALIZE
end

View File

@@ -0,0 +1,27 @@
-- ostro_zx.lua : converts a color image into a
-- Oric image (8+8 fixed colors with color clash)
-- using Ostromoukhov's error diffusion algorithm.
--
-- Version: 03/21/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/ostro_other.lua')
OtherDither:new{
width=240,
height=200,
clash_size=6,
pal={0x000,0x00F,0x0F0,0x0FF,0xF00,0xF0F,0xFF0,0xFFF},
pset=function(self,x,y,c)
if x<6 then c=0 end
if c<0 then c=-c-1 end
self.screen[x+y*self.width] = c
end
}:dither()

View File

@@ -0,0 +1,17 @@
-- ostro_zx.lua : converts a color image into a
-- ZX image (8+8 fixed colors with color clash)
-- using Ostromoukhov's error diffusion algorithm.
--
-- Version: 03/21/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/ostro_other.lua')
OtherDither:new{width=256,height=192,clash_size=8}:dither()