mirror of
https://github.com/appgurueu/modlib.git
synced 2024-11-22 23:33:53 +01:00
decode_png: Implement Adam7 interlacing support
This commit is contained in:
parent
7d4aa0fec1
commit
6d40609f38
@ -72,6 +72,13 @@ local samples = {
|
|||||||
truecolor = 3
|
truecolor = 3
|
||||||
}
|
}
|
||||||
|
|
||||||
|
local adam7_passes = {
|
||||||
|
x_min = { 0, 4, 0, 2, 0, 1, 0 },
|
||||||
|
y_min = { 0, 0, 4, 0, 2, 0, 1 },
|
||||||
|
x_step = { 8, 8, 4, 4, 2, 2, 1 },
|
||||||
|
y_step = { 8, 8, 8, 4, 4, 2, 2 },
|
||||||
|
}
|
||||||
|
|
||||||
(...).decode_png = function(stream)
|
(...).decode_png = function(stream)
|
||||||
local chunk_crc
|
local chunk_crc
|
||||||
local function read(n)
|
local function read(n)
|
||||||
@ -125,7 +132,6 @@ local samples = {
|
|||||||
local interlace_method = byte()
|
local interlace_method = byte()
|
||||||
assert(interlace_method <= 1, "unsupported interlace method")
|
assert(interlace_method <= 1, "unsupported interlace method")
|
||||||
local adam7 = interlace_method == 1
|
local adam7 = interlace_method == 1
|
||||||
assert(not adam7, "adam7 interlacing not supported yet")
|
|
||||||
check_crc() -- IHDR CRC
|
check_crc() -- IHDR CRC
|
||||||
|
|
||||||
local palette
|
local palette
|
||||||
@ -205,13 +211,23 @@ local samples = {
|
|||||||
(64 bits required, packing non-mantissa bits isn't practical) => separate table with alpha values
|
(64 bits required, packing non-mantissa bits isn't practical) => separate table with alpha values
|
||||||
]]
|
]]
|
||||||
local data = {}
|
local data = {}
|
||||||
local alpha_data = {}
|
local alpha_data = color_type.color == "truecolor" and bit_depth == 16 and {} or nil
|
||||||
|
if adam7 then
|
||||||
|
-- Allocate space in list part in order to not fill the hash part later
|
||||||
|
for i = 1, width * height do
|
||||||
|
data[i] = false
|
||||||
|
if alpha_data then
|
||||||
|
alpha_data[i] = false
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
local bits_per_pixel = (samples[color_type.color] + (color_type.alpha and 1 or 0)) * bit_depth
|
local bits_per_pixel = (samples[color_type.color] + (color_type.alpha and 1 or 0)) * bit_depth
|
||||||
local bytes_per_pixel = math.ceil(bits_per_pixel / 8)
|
local bytes_per_pixel = math.ceil(bits_per_pixel / 8)
|
||||||
local scanline_bytecount = math.ceil(width * bits_per_pixel / 8)
|
|
||||||
local previous_scanline
|
local previous_scanline
|
||||||
for y = 0, height - 1 do
|
local idat_base_index = 1
|
||||||
local idat_base_index = y * (scanline_bytecount + 1) + 1
|
local function read_scanline(x_min, x_step, y)
|
||||||
|
local scanline_width = math.ceil((width - x_min) / x_step)
|
||||||
|
local scanline_bytecount = math.ceil(scanline_width * bits_per_pixel / 8)
|
||||||
local filtering = idat_content:byte(idat_base_index)
|
local filtering = idat_content:byte(idat_base_index)
|
||||||
local scanline = {}
|
local scanline = {}
|
||||||
for i = 1, scanline_bytecount do
|
for i = 1, scanline_bytecount do
|
||||||
@ -262,7 +278,7 @@ local samples = {
|
|||||||
local low = 2^(-bit % 8)
|
local low = 2^(-bit % 8)
|
||||||
return floor(byte / low) % (2^bit_depth)
|
return floor(byte / low) % (2^bit_depth)
|
||||||
end
|
end
|
||||||
for x = 0, width - 1 do
|
for x = x_min, width - 1, x_step do
|
||||||
local data_index = y * width + x + 1
|
local data_index = y * width + x + 1
|
||||||
if color_type.color == "palette" then
|
if color_type.color == "palette" then
|
||||||
local palette_index = sample()
|
local palette_index = sample()
|
||||||
@ -303,6 +319,23 @@ local samples = {
|
|||||||
-- Each byte of the scanline must have been read from
|
-- Each byte of the scanline must have been read from
|
||||||
assert(bit >= #scanline * 8 - 7)
|
assert(bit >= #scanline * 8 - 7)
|
||||||
previous_scanline = scanline
|
previous_scanline = scanline
|
||||||
|
idat_base_index = idat_base_index + scanline_bytecount + 1
|
||||||
|
end
|
||||||
|
if adam7 then
|
||||||
|
for pass = 1, 7 do
|
||||||
|
local x_min, y_min = adam7_passes.x_min[pass], adam7_passes.y_min[pass]
|
||||||
|
if x_min < width and y_min < height then -- Non-empty pass
|
||||||
|
local x_step, y_step = adam7_passes.x_step[pass], adam7_passes.y_step[pass]
|
||||||
|
previous_scanline = nil -- Filtering doesn't use scanlines of previous passes
|
||||||
|
for y = y_min, height - 1, y_step do
|
||||||
|
read_scanline(x_min, x_step, y)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
else
|
||||||
|
for y = 0, height - 1 do
|
||||||
|
read_scanline(0, 1, y)
|
||||||
|
end
|
||||||
end
|
end
|
||||||
return {
|
return {
|
||||||
width = width,
|
width = width,
|
||||||
@ -310,7 +343,7 @@ local samples = {
|
|||||||
color_type = color_type,
|
color_type = color_type,
|
||||||
source_gamma = source_gamma,
|
source_gamma = source_gamma,
|
||||||
data = data,
|
data = data,
|
||||||
alpha_data = next(alpha_data) and alpha_data
|
alpha_data = alpha_data
|
||||||
}
|
}
|
||||||
end
|
end
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user