Code:
function get_rgb_cubic_row(x,y,offset)
local r0,g0,b0, r1,g1,b1, r2,g2,b2, r3,g3,b3
r0,g0,b0 = get_rgb(x,y)
r1,g1,b1 = get_rgb(x+1,y)
r2,g2,b2 = get_rgb(x+2,y)
r3,g3,b3 = get_rgb(x+3,y)
return cubic(offset,r0,r1,r2,r3), cubic(offset,g0,g1,g2,g3), cubic(offset,b0,b1,b2,b3)
end
function get_rgb_bicubic (x,y)
local xi,yi -- integer coordinates
local dx,dy -- offset from coordinates
local r,g,b
xi=math.floor(x)
yi=math.floor(y)
dx=x-xi
dy=y-yi
r0,g0,b0 = get_rgb_cubic_row(xi-1,yi-1,dx)
r1,g1,b1 = get_rgb_cubic_row(xi-1,yi, dx)
r2,g2,b2 = get_rgb_cubic_row(xi-1,yi+1,dx)
r3,g3,b3 = get_rgb_cubic_row(xi-1,yi+2,dx)
return cubic(dy,r0,r1,r2,r3),
cubic(dy,g0,g1,g2,g3),
cubic(dy,b0,b1,b2,b3)
end
function scale(ratio)
for y=0, height-1 do
for x=0, width-1 do
-- calculate the source coordinates (u,v)
u = x * (1.0/ratio)
v = y * (1.0/ratio)
r,g,b=get_rgb_bicubic(u,v)
set_rgb(x,y,r,g,b)
end
progress (y/height)
end
flush()
end
function cubic(offset,v0,v1,v2,v3)
-- offset is the offset of the sampled value between v1 and v2
return (((( -7 * v0 + 21 * v1 - 21 * v2 + 7 * v3 ) * offset +
( 15 * v0 - 36 * v1 + 27 * v2 - 6 * v3 ) ) * offset +
( -9 * v0 + 9 * v2 ) ) * offset + (v0 + 16 * v1 + v2) ) / 18.0;
end
scale(3)