-
Notifications
You must be signed in to change notification settings - Fork 2
/
Copy pathlibpng_demo.lua
214 lines (182 loc) · 5.86 KB
/
libpng_demo.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
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
local player = require'cplayer'
local libpng = require'libpng'
local glue = require'glue'
local ffi = require'ffi'
require'unit' --dir
local good_files = dir'media/png/good/*.png'
local bad_files = dir'media/png/bad/*.png'
local source_type = 'path'
local files = good_files
local bottom_up = false
local stride_aligned = false
local max_cut_size = 1024 * 6
local cut_size = max_cut_size
local pixel_format = 'rgb'
local interlaced_filter_values = {'interl', 'normal'}
local interlaced_filter = glue.index(interlaced_filter_values)
local paletted_filter_values = {'pal', 'bitmap'}
local paletted_filter = glue.index(paletted_filter_values)
local channels_filter_values = {'rgb', 'rgba', 'g', 'ga'}
local channels_filter = glue.index(channels_filter_values)
local bpc_filter_values = {'1b', '2b', '4b', '8b', '16b'}
local bpc_filter = glue.index(bpc_filter_values)
local passes_filter_values = {'single', 'multi'}
local passes_filter = glue.index(passes_filter_values)
local pass_only = 7
local sparkle = false
function player:on_render(cr)
self:checkerboard()
files = self:mbutton{id = 'files',
x = 10, y = 10, w = 180, h = 24,
values = {good_files, bad_files},
texts = {[good_files] = 'good files', [bad_files] = 'bad files'},
multiselect = false,
selected = files}
source_type = self:mbutton{id = 'source_type',
x = 200, y = 10, w = 490, h = 24,
values = {'path', 'stream', 'cdata', 'string',
'read cdata', 'read string'},
selected = source_type}
sparkle = self:togglebutton{id = 'sparkle',
x = 700, y = 10, w = 90, h = 24,
text = 'sparkle', selected = sparkle}
bottom_up = self:togglebutton{id = 'bottom_up',
x = 800, y = 10, w = 90, h = 24,
text = 'bottom_up', selected = bottom_up}
stride_aligned = self:togglebutton{id = 'stride_aligned',
x = 900, y = 10, w = 90, h = 24,
text = 'stride_aligned', selected = stride_aligned}
if source_type ~= 'path' and source_type ~= 'stream' then
cut_size = self:slider{id = 'cut_size',
x = 1000, y = 10, w = self.w - 1000 - 10, h = 24,
i0 = 0, i1 = max_cut_size, step = 1, i = cut_size,
text = 'file cut'}
end
pixel_format = self:mbutton{id = 'pixel',
x = 10, y = 40, w = 380, h = 24,
values = {'rgb', 'bgr', 'rgba', 'bgra',
'argb', 'abgr', 'g', 'ga', 'ag'},
selected = pixel_format}
interlaced_filter = self:mbutton{id = 'interlaced_filter',
x = 400, y = 40, w = 90, h = 24,
values = interlaced_filter_values,
selected = interlaced_filter}
paletted_filter = self:mbutton{id = 'paletted_filter',
x = 500, y = 40, w = 90, h = 24,
values = paletted_filter_values,
selected = paletted_filter}
channels_filter = self:mbutton{id = 'channels_filter',
x = 600, y = 40, w = 190, h = 24,
values = channels_filter_values,
selected = channels_filter}
bpc_filter = self:mbutton{id = 'bpc_filter',
x = 800, y = 40, w = 190, h = 24,
values = bpc_filter_values,
selected = bpc_filter}
passes_filter = self:mbutton{id = 'passes_filter',
x = 1000, y = 40, w = 90, h = 24,
values = passes_filter_values,
selected = passes_filter}
pass_only = self:slider{id = 'pass_only',
x = 1100, y = 40, w = 90, h = 24,
i0 = 1, i1 = 7, i = pass_only,
text = 'pass'}
local function allow_image(image)
if not interlaced_filter.interl and image.file.interlaced then return end
if not interlaced_filter.normal and not image.file.interlaced then return end
if not paletted_filter.pal and image.file.paletted then return end
if not paletted_filter.bitmap and not image.file.paletted then return end
if not bpc_filter[tostring(image.file.bpc)..'b'] then return end
if not channels_filter[image.file.channels] then return end
if not passes_filter.single and image.file.passes == 1 then return end
if not passes_filter.multi and image.file.passes == 7 then return end
return true
end
local cy = 80
local cx = 10
for i,filename in ipairs(files) do
local t = {}
if source_type == 'path' then
t.path = filename
elseif source_type == 'stream' then
t.stream = io.open(filename, 'rb')
else
local s = glue.readfile(filename)
s = s:sub(1, cut_size)
local cdata = ffi.new('uint8_t[?]', #s+1, s)
if source_type == 'cdata' then
t.cdata = cdata
t.size = #s
elseif source_type == 'string' then
t.string = s
elseif source_type:match'^read' then
local function one_shot_reader(buf, sz)
local done
return function()
if done then return end
done = true
return buf, sz
end
end
if source_type:find'string' then
t.read = one_shot_reader(s)
else
t.read = one_shot_reader(cdata, #s)
end
end
end
local w, h = 32, 32
--[[
t.accept = {
[pixel_format] = true,
bottom_up = bottom_up,
stride_aligned = stride_aligned}
]]
t.sparkle = sparkle
function t.render_scan(image, last_scan, scan_number, err)
if scan_number ~= pass_only
and not (pass_only > 1 and scan_number == 1 and last_scan)
then
return
end
if not image then
w = (w + 10) * 8 - 10
end
if cx + w + 10 > self.w then
cx = 10
cy = cy + h + 10 + 40
end
if image then
self:image{x = cx, y = cy, image = image}
self:textbox(cx, cy - 16, w, h,
string.format('%s', image.file.format),
8, 'normal_fg', 'center', 'top')
self:textbox(cx, cy + 16, w, h,
string.format('%s', image.format),
8, 'normal_fg', 'center', 'bottom')
else
self:rect(cx, cy, w, h, 'error_bg')
self:textbox(cx, cy, w, h,
string.format('%s', err:match('^(.-)\n'):match(': ([^:]-)$')),
14, 'normal_fg', 'center', 'center')
end
cx = cx + w + 10
end
local ok, err = xpcall(function()
local t0 = glue.merge({
header_only = true,
render_scan = false,
}, t)
local image = libpng.load(t0)
if not allow_image(image) then return end
libpng.load(t)
end, debug.traceback)
if not ok then
t.render_scan(nil, true, 1, err)
end
if t.stream then
t.stream:close()
end
end
end
player:play()