Add updated tga_encoder

This commit is contained in:
Elias Fleckenstein 2021-05-02 17:47:46 +02:00
parent 63d4e57a8d
commit 1eaf662833

View File

@ -1,7 +1,5 @@
tga_encoder = {} tga_encoder = {}
local LUA_ARGS_LIMIT = 1000
local image = setmetatable({}, { local image = setmetatable({}, {
__call = function(self, ...) __call = function(self, ...)
local t = setmetatable({}, {__index = self}) local t = setmetatable({}, {__index = self})
@ -11,8 +9,7 @@ local image = setmetatable({}, {
}) })
function image:constructor(pixels) function image:constructor(pixels)
self.bytes = {} self.data = ""
self.chunks = {self.bytes}
self.pixels = pixels self.pixels = pixels
self.width = #pixels[1] self.width = #pixels[1]
self.height = #pixels self.height = #pixels
@ -20,87 +17,59 @@ function image:constructor(pixels)
self:encode() self:encode()
end end
function image:insert(byte)
table.insert(self.bytes, byte)
if #self.bytes == LUA_ARGS_LIMIT then
self.bytes = {}
table.insert(self.chunks, self.bytes)
end
end
function image:littleendian(size, value)
for i = 1, size do
local byte = value % 256
value = value - byte
value = value / 256
self:insert(byte)
end
end
function image:encode_colormap_spec() function image:encode_colormap_spec()
-- first entry index self.data = self.data
self:littleendian(2, 0) .. string.char(0, 0) -- first entry index
-- number of entries .. string.char(0, 0) -- number of entries
self:littleendian(2, 0) .. string.char(0) -- bits per pixel
-- number of bits per pixel
self:insert(0)
end end
function image:encode_image_spec() function image:encode_image_spec()
-- X- and Y- origin self.data = self.data
self:littleendian(2, 0) .. string.char(0, 0) -- X-origin
self:littleendian(2, 0) .. string.char(0, 0) -- Y-origin
-- width and height .. string.char(self.width % 256, math.floor(self.width / 256)) -- width
self:littleendian(2, self.width) .. string.char(self.height % 256, math.floor(self.height / 256)) -- height
self:littleendian(2, self.height) .. string.char(24) -- pixel depth (RGB = 3 bytes = 24 bits)
-- pixel depth .. string.char(0) -- image descriptor
self:insert(24)
-- image descriptor
self:insert(0)
end end
function image:encode_header() function image:encode_header()
-- id length self.data = self.data
self:insert(0) -- no image id info .. string.char(0) -- image id
-- color map type .. string.char(0) -- color map type
self:insert(0) -- no color map .. string.char(2) -- image type (uncompressed true-color image = 2)
-- image type self:encode_colormap_spec() -- color map specification
self:insert(2) -- uncompressed true-color image self:encode_image_spec() -- image specification
-- color map specification
self:encode_colormap_spec()
-- image specification
self:encode_image_spec()
end end
function image:encode_data() function image:encode_data()
for _, row in ipairs(self.pixels) do for _, row in ipairs(self.pixels) do
for _, pixel in ipairs(row) do for _, pixel in ipairs(row) do
self:insert(pixel[3]) self.data = self.data
self:insert(pixel[2]) .. string.char(pixel[3], pixel[2], pixel[1])
self:insert(pixel[1])
end end
end end
end end
function image:encode_footer()
self.data = self.data
.. string.char(0, 0, 0, 0) -- extension area offset
.. string.char(0, 0, 0, 0) -- developer area offset
.. "TRUEVISION-XFILE"
.. "."
.. string.char(0)
end
function image:encode() function image:encode()
-- encode header self:encode_header() -- header
self:encode_header()
-- no color map and image id data -- no color map and image id data
-- encode data self:encode_data() -- encode data
self:encode_data() -- no extension or developer area
-- no extension area self:encode_footer() -- footer
end
function image:get_data()
local data = ""
for _, bytes in ipairs(self.chunks) do
data = data .. string.char(unpack(bytes))
end
return data .. string.char(0, 0, 0, 0) .. string.char(0, 0, 0, 0) .. "TRUEVISION-XFILE." .. string.char(0)
end end
function image:save(filename) function image:save(filename)
self.data = self.data or self:get_data()
local f = assert(io.open(filename, "w")) local f = assert(io.open(filename, "w"))
f:write(self.data) f:write(self.data)
f:close() f:close()