Allow encoding grayscale images as BW8

This commit is contained in:
Nils Dagsson Moskopp 2022-05-14 22:41:52 +02:00
parent 9af0719df8
commit 25b7b30945
No known key found for this signature in database
GPG key ID: A3BC671C35191080
2 changed files with 58 additions and 16 deletions

View file

@ -29,6 +29,18 @@ for x = 1,56,1 do
end end
tga_encoder.image(pixels):save("bitmap_large.tga") tga_encoder.image(pixels):save("bitmap_large.tga")
-- note that the uncompressed grayscale TGA file written in this
-- example is 80 bytes but an optimized PNG file is 81 bytes …
local pixels = {}
for x = 1,6,1 do -- left to right
for z = 1,6,1 do -- bottom to top
local color = { math.min(x * z * 4 - 1, 255) }
pixels[z] = pixels[z] or {}
pixels[z][x] = color
end
end
tga_encoder.image(pixels, {colors="BW", pixel_depth=8}):save("gradients_8bpp.tga")
local pixels = {} local pixels = {}
for x = 1,16,1 do -- left to right for x = 1,16,1 do -- left to right
for z = 1,16,1 do -- bottom to top for z = 1,16,1 do -- bottom to top
@ -46,5 +58,5 @@ for x = 1,16,1 do -- left to right
pixels[z][x] = color pixels[z][x] = color
end end
end end
tga_encoder.image(pixels, {pixel_depth=16}):save("gradients_16bpp.tga") tga_encoder.image(pixels, {colors="RGB", pixel_depth=16}):save("gradients_16bpp.tga")
tga_encoder.image(pixels, {pixel_depth=24}):save("gradients_24bpp.tga") tga_encoder.image(pixels, {colors="RGB", pixel_depth=24}):save("gradients_24bpp.tga")

View file

@ -10,14 +10,15 @@ local image = setmetatable({}, {
function image:constructor(pixels, properties) function image:constructor(pixels, properties)
local properties = properties or {} local properties = properties or {}
local pixel_depth = properties.pixel_depth or 16 properties.colors = properties.colors or "RGB"
properties.pixel_depth = properties.pixel_depth or 16
self.data = "" self.data = ""
self.pixels = pixels self.pixels = pixels
self.width = #pixels[1] self.width = #pixels[1]
self.height = #pixels self.height = #pixels
self:encode(pixel_depth) self:encode(properties)
end end
function image:encode_colormap_spec() function image:encode_colormap_spec()
@ -27,10 +28,13 @@ function image:encode_colormap_spec()
.. string.char(0) -- bits per pixel .. string.char(0) -- bits per pixel
end end
function image:encode_image_spec(pixel_depth) function image:encode_image_spec(properties)
local colors = properties.colors
local pixel_depth = properties.pixel_depth
assert( assert(
16 == pixel_depth or -- (A1R5G5B5 = 2 bytes = 16 bits) "BW" == colors and 8 == pixel_depth or -- (8 bit grayscale = 1 byte = 8 bits)
24 == pixel_depth -- (B8G8R8 = 3 bytes = 24 bits) "RGB" == colors and 16 == pixel_depth or -- (A1R5G5B5 = 2 bytes = 16 bits)
"RGB" == colors and 24 == pixel_depth -- (B8G8R8 = 3 bytes = 24 bits)
) )
self.data = self.data self.data = self.data
.. string.char(0, 0) -- X-origin .. string.char(0, 0) -- X-origin
@ -41,23 +45,49 @@ function image:encode_image_spec(pixel_depth)
.. string.char(0) -- image descriptor .. string.char(0) -- image descriptor
end end
function image:encode_header(pixel_depth) function image:encode_header(properties)
local colors = properties.colors
local pixel_depth = properties.pixel_depth
local image_type
if "BW" == colors and 8 == pixel_depth then
image_type = 3 -- grayscale
elseif (
"RGB" == colors and 16 == pixel_depth or
"RGB" == colors and 24 == pixel_depth
) then
image_type = 10 -- RLE RGB
end
self.data = self.data self.data = self.data
.. string.char(0) -- image id .. string.char(0) -- image id
.. string.char(0) -- color map type .. string.char(0) -- color map type
.. string.char(10) -- image type (RLE RGB = 10) .. string.char(image_type)
self:encode_colormap_spec() -- color map specification self:encode_colormap_spec() -- color map specification
self:encode_image_spec(pixel_depth) -- image specification self:encode_image_spec(properties) -- image specification
end end
function image:encode_data(pixel_depth) function image:encode_data(properties)
if 16 == pixel_depth then local colors = properties.colors
local pixel_depth = properties.pixel_depth
if "BW" == colors and 8 == pixel_depth then
self:encode_data_bw8()
elseif "RGB" == colors and 16 == pixel_depth then
self:encode_data_a1r5g5b5_rle() self:encode_data_a1r5g5b5_rle()
elseif 24 == pixel_depth then elseif "RGB" == colors and 24 == pixel_depth then
self:encode_data_r8g8b8_rle() self:encode_data_r8g8b8_rle()
end end
end end
function image:encode_data_bw8()
local raw_pixels = {}
for _, row in ipairs(self.pixels) do
for _, pixel in ipairs(row) do
local raw_pixel = string.char(pixel[1])
raw_pixels[#raw_pixels + 1] = raw_pixel
end
end
self.data = self.data .. table.concat(raw_pixels)
end
function image:encode_data_a1r5g5b5_rle() function image:encode_data_a1r5g5b5_rle()
local colorword = nil local colorword = nil
local previous_r = nil local previous_r = nil
@ -232,10 +262,10 @@ function image:encode_footer()
.. string.char(0) .. string.char(0)
end end
function image:encode(pixel_depth) function image:encode(properties)
self:encode_header(pixel_depth) -- header self:encode_header(properties) -- header
-- no color map and image id data -- no color map and image id data
self:encode_data(pixel_depth) -- encode data self:encode_data(properties) -- encode data
-- no extension or developer area -- no extension or developer area
self:encode_footer() -- footer self:encode_footer() -- footer
end end