-
Notifications
You must be signed in to change notification settings - Fork 22
/
bitmap_resize.lua
123 lines (86 loc) · 2.66 KB
/
bitmap_resize.lua
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
--bitmap resampling.
--Written by Cosmin Apreutesei. Public domain.
local bitmap = require'bitmap'
bitmap.resize = {}
local min, max, floor, ceil =
math.min, math.max, math.floor, math.ceil
local function clamp(x, t0, t1)
return min(max(x, t0), t1)
end
local function check_colortypes(src, dst)
local c1 = bitmap.colortype(src)
local c2 = bitmap.colortype(dst)
assert(c1 == c2, 'colortype mismatch')
return #c1.channels, c1.max
end
local function args(src, w, h)
local dst
if type(w) == 'number' then --src, w, h
dst = bitmap.new(w, h, src.format)
else --src, dst
dst = w
end
local channels, maxval = check_colortypes(src, dst)
local src_getpixel = bitmap.pixel_interface(src)
local _, dst_setpixel = bitmap.pixel_interface(dst)
return src, dst, src_getpixel, dst_setpixel, channels, maxval
end
function bitmap.resize.nearest(...)
local src, dst, src_getpixel, dst_setpixel = args(...)
local tx = (src.w-1) / dst.w
local ty = (src.h-1) / dst.h
for y1 = 0, dst.h-1 do
for x1 = 0, dst.w-1 do
local x = ceil(tx * x1)
local y = ceil(ty * y1)
dst_setpixel(x1, y1, src_getpixel(x, y))
end
end
return dst
end
function bitmap.resize.bilinear(...)
local src, dst, src_getpixel, dst_setpixel, channels, maxval = args(...)
local kernel = {}
kernel[2] = function(x, y, x1, y1, f1, f2, f3, f4)
local g1, a1 = src_getpixel(x, y )
local g2, a2 = src_getpixel(x+1, y )
local g3, a3 = src_getpixel(x, y+1)
local g4, a4 = src_getpixel(x+1, y+1)
dst_setpixel(x1, y1,
g1 * f1 + g2 * f2 + g3 * f3 + g4 * f4,
a1 * f1 + a2 * f2 + a3 * f3 + a4 * f4)
end
kernel[4] = function(x, y, x1, y1, f1, f2, f3, f4)
local r1, g1, b1, a1 = src_getpixel(x, y )
local r2, g2, b2, a2 = src_getpixel(x+1, y )
local r3, g3, b3, a3 = src_getpixel(x, y+1)
local r4, g4, b4, a4 = src_getpixel(x+1, y+1)
dst_setpixel(x1, y1,
clamp(r1 * f1 + r2 * f2 + r3 * f3 + r4 * f4, 0, maxval),
clamp(g1 * f1 + g2 * f2 + g3 * f3 + g4 * f4, 0, maxval),
clamp(b1 * f1 + b2 * f2 + b3 * f3 + b4 * f4, 0, maxval),
clamp(a1 * f1 + a2 * f2 + a3 * f3 + a4 * f4, 0, maxval))
end
local kernel = assert(kernel[channels], 'unsupported colortype')
local maxx = src.w-2
local maxy = src.h-2
local tx = src.w / dst.w
local ty = src.h / dst.h
for y1 = 0, dst.h-1 do
for x1 = 0, dst.w-1 do
local x = floor(tx * x1)
local y = floor(ty * y1)
x = clamp(x, 0, maxx)
y = clamp(y, 0, maxy)
local dx = tx * x1 - x
local dy = ty * y1 - y
local f1 = (1-dx)*(1-dy)
local f2 = dx*(1-dy)
local f3 = (1-dx)*dy
local f4 = dx*dy
kernel(x, y, x1, y1, f1, f2, f3, f4)
end
end
return dst
end
if not ... then require'bitmap_demo' end