mirror of
https://github.com/appgurueu/modlib.git
synced 2024-11-22 15:23:48 +01:00
PNG decoder: Fix transparency handling
This commit is contained in:
parent
7e57c55caf
commit
8e42d027a0
@ -167,6 +167,7 @@ local adam7_passes = {
|
|||||||
end
|
end
|
||||||
elseif chunk_type == "tRNS" then
|
elseif chunk_type == "tRNS" then
|
||||||
assert(not color_type.alpha, "unexpected tRNS chunk")
|
assert(not color_type.alpha, "unexpected tRNS chunk")
|
||||||
|
color_type.transparency = true
|
||||||
assert(idat_allowed, "tRNS after IDAT chunks")
|
assert(idat_allowed, "tRNS after IDAT chunks")
|
||||||
if color_type.color == "palette" then
|
if color_type.color == "palette" then
|
||||||
assert(palette, "PLTE chunk expected")
|
assert(palette, "PLTE chunk expected")
|
||||||
@ -180,7 +181,11 @@ local adam7_passes = {
|
|||||||
else
|
else
|
||||||
assert(color_type.color == "truecolor")
|
assert(color_type.color == "truecolor")
|
||||||
assert(chunk_length == 6)
|
assert(chunk_length == 6)
|
||||||
alpha = ((((byte() * 0x100 + byte()) * 0x100 + byte()) * 0x100 + byte()) * 0x100 + byte()) * 0x100 + byte() -- 16-bit RGB
|
alpha = 0
|
||||||
|
-- Read 16-bit RGB (6 bytes)
|
||||||
|
for _ = 1, 6 do
|
||||||
|
alpha = alpha * 0x100 + byte()
|
||||||
|
end
|
||||||
end
|
end
|
||||||
elseif chunk_type == "gAMA" then
|
elseif chunk_type == "gAMA" then
|
||||||
assert(not palette, "gAMA after PLTE chunk")
|
assert(not palette, "gAMA after PLTE chunk")
|
||||||
@ -211,7 +216,10 @@ local adam7_passes = {
|
|||||||
(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 = color_type.color == "truecolor" and bit_depth == 16 and {} or nil
|
local alpha_data
|
||||||
|
if color_type.color == "truecolor" and bit_depth == 16 and (color_type.alpha or color_type.transparency) then
|
||||||
|
alpha_data = {}
|
||||||
|
end
|
||||||
if adam7 then
|
if adam7 then
|
||||||
-- Allocate space in list part in order to not fill the hash part later
|
-- Allocate space in list part in order to not fill the hash part later
|
||||||
for i = 1, width * height do
|
for i = 1, width * height do
|
||||||
@ -312,7 +320,9 @@ local adam7_passes = {
|
|||||||
-- Pack only RGB in data, alpha goes in a different table
|
-- Pack only RGB in data, alpha goes in a different table
|
||||||
-- 3 * 16 = 48 bytes can still be held accurately by the double mantissa
|
-- 3 * 16 = 48 bytes can still be held accurately by the double mantissa
|
||||||
data[data_index] = rgb16
|
data[data_index] = rgb16
|
||||||
alpha_data[data_index] = a
|
if alpha_data then
|
||||||
|
alpha_data[data_index] = a
|
||||||
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
@ -347,15 +357,15 @@ local adam7_passes = {
|
|||||||
}
|
}
|
||||||
end
|
end
|
||||||
|
|
||||||
local function rescale_depth(sample, source, target)
|
local function rescale_depth(sample, source_depth, target_depth)
|
||||||
if source == target then
|
if source_depth == target_depth then
|
||||||
return sample
|
return sample
|
||||||
end
|
end
|
||||||
return floor((sample / (2^source - 1) * (2^target - 1)) + 0.5)
|
return floor((sample * (2^target_depth - 1) / (2^source_depth - 1)) + 0.5)
|
||||||
end
|
end
|
||||||
-- In-place lossy (if bit depth = 16) conversion to ARGB8
|
-- In-place lossy (if bit depth = 16) conversion to ARGB8
|
||||||
(...).convert_png_to_argb8 = function(png)
|
(...).convert_png_to_argb8 = function(png)
|
||||||
local color, alpha, depth = png.color_type.color, png.color_type.alpha, png.color_type.depth
|
local color, transparency, depth = png.color_type.color, png.color_type.alpha or png.color_type.transparency, png.color_type.depth
|
||||||
if color == "palette" or (color == "truecolor" and depth == 8) then
|
if color == "palette" or (color == "truecolor" and depth == 8) then
|
||||||
return
|
return
|
||||||
end
|
end
|
||||||
@ -369,7 +379,7 @@ end
|
|||||||
local g = rescale_depth(floor(value / 0x10000) % 0x10000, depth, 8)
|
local g = rescale_depth(floor(value / 0x10000) % 0x10000, depth, 8)
|
||||||
local b = rescale_depth(value % 0x10000, depth, 8)
|
local b = rescale_depth(value % 0x10000, depth, 8)
|
||||||
local a = 0xFF
|
local a = 0xFF
|
||||||
if alpha then
|
if transparency then
|
||||||
a = rescale_depth(png.alpha_data[index], depth, 8)
|
a = rescale_depth(png.alpha_data[index], depth, 8)
|
||||||
end
|
end
|
||||||
png.data[index] = a * 0x1000000 + r * 0x10000 + g * 0x100 + b
|
png.data[index] = a * 0x1000000 + r * 0x10000 + g * 0x100 + b
|
||||||
|
Loading…
Reference in New Issue
Block a user