mirror of
https://github.com/appgurueu/modlib.git
synced 2024-11-29 10:43:43 +01:00
Add modlib.minetest.encode_png
This commit is contained in:
parent
e5a3f0c9d8
commit
578d504575
@ -6,7 +6,8 @@ for _, value in pairs{
|
||||
"raycast",
|
||||
"schematic",
|
||||
"colorspec",
|
||||
"media"
|
||||
"media",
|
||||
"encode_png",
|
||||
} do
|
||||
components[value] = value
|
||||
end
|
||||
|
118
minetest/encode_png.lua
Normal file
118
minetest/encode_png.lua
Normal file
@ -0,0 +1,118 @@
|
||||
if minetest.encode_png then
|
||||
return minetest.encode_png
|
||||
end
|
||||
|
||||
local assert, char, ipairs, insert, concat, floor = assert, string.char, ipairs, table.insert, table.concat, math.floor
|
||||
|
||||
-- TODO move to modlib.bit eventually
|
||||
local bit_xor = bit.xor or function(a, b)
|
||||
local res = 0
|
||||
local bit = 1
|
||||
for _ = 1, 32 do
|
||||
if a % 2 ~= b % 2 then
|
||||
res = res + bit
|
||||
end
|
||||
a = floor(a / 2)
|
||||
b = floor(b / 2)
|
||||
bit = bit * 2
|
||||
end
|
||||
return res
|
||||
end
|
||||
|
||||
local crc_table = {}
|
||||
for i = 0, 255 do
|
||||
local c = i
|
||||
for _ = 0, 7 do
|
||||
if c % 2 > 0 then
|
||||
c = bit_xor(0xEDB88320, floor(c / 2))
|
||||
else
|
||||
c = floor(c / 2)
|
||||
end
|
||||
end
|
||||
crc_table[i] = c
|
||||
end
|
||||
|
||||
local function encode_png(width, height, data, compression, raw_write)
|
||||
local write = raw_write
|
||||
local function byte(value)
|
||||
write(char(value))
|
||||
end
|
||||
local function _uint(value)
|
||||
local div = 0x1000000
|
||||
for _ = 1, 4 do
|
||||
byte(floor(value / div) % 0x100)
|
||||
div = div / 0x100
|
||||
end
|
||||
end
|
||||
local function uint(value)
|
||||
assert(value < 2^31)
|
||||
_uint(value)
|
||||
end
|
||||
local chunk_content
|
||||
local function chunk_write(text)
|
||||
insert(chunk_content, text)
|
||||
end
|
||||
local function chunk(type)
|
||||
chunk_content = {}
|
||||
write = chunk_write
|
||||
write(type)
|
||||
end
|
||||
local function end_chunk()
|
||||
write = raw_write
|
||||
local chunk_len = 0
|
||||
for i = 2, #chunk_content do
|
||||
chunk_len = chunk_len + #chunk_content[i]
|
||||
end
|
||||
uint(chunk_len)
|
||||
write(concat(chunk_content))
|
||||
local chunk_crc = 0xFFFFFFFF
|
||||
for _, text in ipairs(chunk_content) do
|
||||
for i = 1, #text do
|
||||
chunk_crc = bit_xor(crc_table[bit_xor(chunk_crc % 0x100, text:byte(i))], floor(chunk_crc / 0x100))
|
||||
end
|
||||
end
|
||||
_uint(bit_xor(chunk_crc, 0xFFFFFFFF))
|
||||
end
|
||||
-- Signature
|
||||
write"\137\80\78\71\13\10\26\10"
|
||||
chunk"IHDR"
|
||||
uint(width)
|
||||
uint(height)
|
||||
-- Always use bit depth 8
|
||||
byte(8)
|
||||
-- Always use color type "truecolor with alpha"
|
||||
byte(6)
|
||||
-- Compression method: deflate
|
||||
byte(0)
|
||||
-- Filter method: PNG filters
|
||||
byte(0)
|
||||
-- No interlace
|
||||
byte(0)
|
||||
end_chunk()
|
||||
chunk"IDAT"
|
||||
local data_bytestring = {}
|
||||
for y = 0, height - 1 do
|
||||
local base = y * width
|
||||
insert(data_bytestring, "\0")
|
||||
for x = 1, width do
|
||||
local color_int = data[base + x]
|
||||
local a = floor(color_int / 0x1000000) % 0x100
|
||||
local r = floor(color_int / 0x10000) % 0x100
|
||||
local g = floor(color_int / 0x100) % 0x100
|
||||
local b = color_int % 0x100
|
||||
insert(data_bytestring, char(r, g, b, a))
|
||||
end
|
||||
end
|
||||
write(minetest.compress(concat(data_bytestring), "deflate", compression))
|
||||
end_chunk()
|
||||
chunk"IEND"
|
||||
end_chunk()
|
||||
end
|
||||
|
||||
(...).encode_png = function(width, height, data, compression)
|
||||
local rope = {}
|
||||
encode_png(width, height, data, compression or 9, function(text)
|
||||
insert(rope, text)
|
||||
end)
|
||||
return concat(rope)
|
||||
end
|
Loading…
Reference in New Issue
Block a user