Allow to specify color format

This commit is contained in:
Nils Dagsson Moskopp 2022-05-16 02:48:51 +02:00
parent fa23775bf9
commit 7b94fc026d
No known key found for this signature in database
GPG Key ID: A3BC671C35191080
2 changed files with 60 additions and 45 deletions

@ -39,7 +39,7 @@ for x = 1,6,1 do -- left to right
pixels[z][x] = color pixels[z][x] = color
end end
end end
tga_encoder.image(pixels):save("gradient_8bpp_raw.tga", {colors="BW", compression="RAW", pixel_depth=8}) tga_encoder.image(pixels):save("gradient_8bpp_raw.tga", {color_format="Y8", compression="RAW"})
local pixels = {} local pixels = {}
for x = 1,16,1 do -- left to right for x = 1,16,1 do -- left to right
@ -59,11 +59,11 @@ for x = 1,16,1 do -- left to right
end end
end end
local gradients = tga_encoder.image(pixels) local gradients = tga_encoder.image(pixels)
gradients:save("gradients_8bpp_raw.tga", {colors="BW", compression="RAW", pixel_depth=8}) gradients:save("gradients_8bpp_raw.tga", {color_format="Y8", compression="RAW"})
gradients:save("gradients_16bpp_raw.tga", {colors="RGB", compression="RAW", pixel_depth=16}) gradients:save("gradients_16bpp_raw.tga", {color_format="A1R5G5B5", compression="RAW"})
gradients:save("gradients_16bpp_rle.tga", {colors="RGB", compression="RLE", pixel_depth=16}) gradients:save("gradients_16bpp_rle.tga", {color_format="A1R5G5B5", compression="RLE"})
gradients:save("gradients_24bpp_raw.tga", {colors="RGB", compression="RAW", pixel_depth=24}) gradients:save("gradients_24bpp_raw.tga", {color_format="B8G8R8", compression="RAW"})
gradients:save("gradients_24bpp_rle.tga", {colors="RGB", compression="RLE", pixel_depth=24}) gradients:save("gradients_24bpp_rle.tga", {color_format="B8G8R8", compression="RLE"})
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
@ -72,7 +72,7 @@ for x = 1,16,1 do -- left to right
pixels[z][x] = color pixels[z][x] = color
end end
end end
gradients:save("gradients_32bpp_raw.tga", {colors="RGBA", compression="RAW", pixel_depth=32}) gradients:save("gradients_32bpp_raw.tga", {color_format="B8G8R8A8", compression="RAW"})
local pixels = {} local pixels = {}
for x = 1,512,1 do -- left to right for x = 1,512,1 do -- left to right
@ -94,6 +94,6 @@ for x = 1,512,1 do -- left to right
pixels[z][x] = color pixels[z][x] = color
end end
end end
tga_encoder.image(pixels):save("fractal_8bpp.tga", {colors="BW", pixel_depth=8}) tga_encoder.image(pixels):save("fractal_8bpp.tga", {color_format="Y8"})
tga_encoder.image(pixels):save("fractal_16bpp.tga", {colors="RGB", pixel_depth=16}) tga_encoder.image(pixels):save("fractal_16bpp.tga", {color_format="A1R5G5B5"})
tga_encoder.image(pixels):save("fractal_24bpp.tga", {colors="RGB", pixel_depth=24}) tga_encoder.image(pixels):save("fractal_24bpp.tga", {color_format="B8G8R8"})

@ -22,14 +22,21 @@ function image:encode_colormap_spec()
end end
function image:encode_image_spec(properties) function image:encode_image_spec(properties)
local colors = properties.colors local color_format = properties.color_format
local pixel_depth = properties.pixel_depth
assert( assert(
"BW" == colors and 8 == pixel_depth or -- (8 bit grayscale = 1 byte = 8 bits) "Y8" == color_format or -- (8 bit grayscale = 1 byte = 8 bits)
"RGB" == colors and 16 == pixel_depth or -- (A1R5G5B5 = 2 bytes = 16 bits) "A1R5G5B5" == color_format or -- (A1R5G5B5 = 2 bytes = 16 bits)
"RGB" == colors and 24 == pixel_depth or -- (B8G8R8 = 3 bytes = 24 bits) "B8G8R8" == color_format or -- (B8G8R8 = 3 bytes = 24 bits)
"RGBA" == colors and 32 == pixel_depth -- (B8G8R8A8 = 4 bytes = 32 bits) "B8G8R8A8" == color_format -- (B8G8R8A8 = 4 bytes = 32 bits)
) )
pixel_depth_by_color_format = {
["Y8"] = 8,
["A1R5G5B5"] = 16,
["B8G8R8"] = 24,
["B8G8R8A8"] = 32,
}
local pixel_depth = pixel_depth_by_color_format[color_format]
assert( nil ~= pixel_depth)
self.data = self.data self.data = self.data
.. string.char(0, 0) -- X-origin .. string.char(0, 0) -- X-origin
.. string.char(0, 0) -- Y-origin .. string.char(0, 0) -- Y-origin
@ -40,16 +47,15 @@ function image:encode_image_spec(properties)
end end
function image:encode_header(properties) function image:encode_header(properties)
local colors = properties.colors local color_format = properties.color_format
local compression = properties.compression local compression = properties.compression
local pixel_depth = properties.pixel_depth
local image_type local image_type
if "BW" == colors and "RAW" == compression and 8 == pixel_depth then if "Y8" == color_format and "RAW" == compression then
image_type = 3 -- grayscale image_type = 3 -- grayscale
elseif ( elseif (
"RGB" == colors and 16 == pixel_depth or "A1R5G5B5" == color_format or
"RGB" == colors and 24 == pixel_depth or "B8G8R8" == color_format or
"RGBA" == colors and 32 == pixel_depth "B8G8R8A8" == color_format
) then ) then
if "RAW" == compression then if "RAW" == compression then
image_type = 2 -- RAW RGB(A) image_type = 2 -- RAW RGB(A)
@ -57,6 +63,7 @@ function image:encode_header(properties)
image_type = 10 -- RLE RGB image_type = 10 -- RLE RGB
end end
end end
assert( nil ~= image_type )
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
@ -66,37 +73,35 @@ function image:encode_header(properties)
end end
function image:encode_data(properties) function image:encode_data(properties)
local colors = properties.colors local color_format = properties.color_format
local compression = properties.compression local compression = properties.compression
local pixel_depth = properties.pixel_depth
self.pixel_depth = #self.pixels[1][1] * 8
if "BW" == colors and "RAW" == compression and 8 == pixel_depth then if "Y8" == color_format and "RAW" == compression then
if 8 == self.pixel_depth then if 8 == self.pixel_depth then
self:encode_data_bw8_to_bw8_raw() self:encode_data_Y8_as_Y8_raw()
elseif 24 == self.pixel_depth then elseif 24 == self.pixel_depth then
self:encode_data_r8g8b8_to_bw8_raw() self:encode_data_R8G8B8_as_Y8_raw()
end end
elseif "RGB" == colors and 16 == pixel_depth then elseif "A1R5G5B5" == color_format then
if "RAW" == compression then if "RAW" == compression then
self:encode_data_a1r5g5b5_raw() self:encode_data_R8G8B8_as_A1R5G5B5_raw()
elseif "RLE" == compression then elseif "RLE" == compression then
self:encode_data_a1r5g5b5_rle() self:encode_data_R8G8B8_as_A1R5G5B5_rle()
end end
elseif "RGB" == colors and 24 == pixel_depth then elseif "B8G8R8" == color_format then
if "RAW" == compression then if "RAW" == compression then
self:encode_data_r8g8b8_raw() self:encode_data_R8G8B8_as_B8G8R8_raw()
elseif "RLE" == compression then elseif "RLE" == compression then
self:encode_data_r8g8b8_rle() self:encode_data_R8G8B8_as_B8G8R8_rle()
end end
elseif "RGBA" == colors and 32 == pixel_depth then elseif "B8G8R8A8" == color_format then
if "RAW" == compression then if "RAW" == compression then
self:encode_data_r8g8b8a8_raw() self:encode_data_R8G8B8A8_as_B8G8R8A8_raw()
end end
end end
end end
function image:encode_data_bw8_to_bw8_raw() function image:encode_data_Y8_as_Y8_raw()
assert(8 == self.pixel_depth) assert(8 == self.pixel_depth)
local raw_pixels = {} local raw_pixels = {}
for _, row in ipairs(self.pixels) do for _, row in ipairs(self.pixels) do
@ -108,7 +113,7 @@ function image:encode_data_bw8_to_bw8_raw()
self.data = self.data .. table.concat(raw_pixels) self.data = self.data .. table.concat(raw_pixels)
end end
function image:encode_data_r8g8b8_to_bw8_raw() function image:encode_data_R8G8B8_as_Y8_raw()
assert(24 == self.pixel_depth) assert(24 == self.pixel_depth)
local raw_pixels = {} local raw_pixels = {}
for _, row in ipairs(self.pixels) do for _, row in ipairs(self.pixels) do
@ -130,7 +135,7 @@ function image:encode_data_r8g8b8_to_bw8_raw()
self.data = self.data .. table.concat(raw_pixels) self.data = self.data .. table.concat(raw_pixels)
end end
function image:encode_data_a1r5g5b5_raw() function image:encode_data_R8G8B8_as_A1R5G5B5_raw()
assert(24 == self.pixel_depth) assert(24 == self.pixel_depth)
local raw_pixels = {} local raw_pixels = {}
-- Sample depth rescaling is done according to the algorithm presented in: -- Sample depth rescaling is done according to the algorithm presented in:
@ -150,7 +155,7 @@ function image:encode_data_a1r5g5b5_raw()
self.data = self.data .. table.concat(raw_pixels) self.data = self.data .. table.concat(raw_pixels)
end end
function image:encode_data_a1r5g5b5_rle() function image:encode_data_R8G8B8_as_A1R5G5B5_rle()
assert(24 == self.pixel_depth) assert(24 == self.pixel_depth)
local colorword = nil local colorword = nil
local previous_r = nil local previous_r = nil
@ -240,7 +245,7 @@ function image:encode_data_a1r5g5b5_rle()
self.data = self.data .. table.concat(packets) self.data = self.data .. table.concat(packets)
end end
function image:encode_data_r8g8b8_raw() function image:encode_data_R8G8B8_as_B8G8R8_raw()
assert(24 == self.pixel_depth) assert(24 == self.pixel_depth)
local raw_pixels = {} local raw_pixels = {}
for _, row in ipairs(self.pixels) do for _, row in ipairs(self.pixels) do
@ -252,7 +257,7 @@ function image:encode_data_r8g8b8_raw()
self.data = self.data .. table.concat(raw_pixels) self.data = self.data .. table.concat(raw_pixels)
end end
function image:encode_data_r8g8b8_rle() function image:encode_data_R8G8B8_as_B8G8R8_rle()
assert(24 == self.pixel_depth) assert(24 == self.pixel_depth)
local previous_r = nil local previous_r = nil
local previous_g = nil local previous_g = nil
@ -329,7 +334,7 @@ function image:encode_data_r8g8b8_rle()
self.data = self.data .. table.concat(packets) self.data = self.data .. table.concat(packets)
end end
function image:encode_data_r8g8b8a8_raw() function image:encode_data_R8G8B8A8_as_B8G8R8A8_raw()
assert(32 == self.pixel_depth) assert(32 == self.pixel_depth)
local raw_pixels = {} local raw_pixels = {}
for _, row in ipairs(self.pixels) do for _, row in ipairs(self.pixels) do
@ -361,9 +366,19 @@ end
function image:save(filename, properties) function image:save(filename, properties)
local properties = properties or {} local properties = properties or {}
properties.colors = properties.colors or "RGB"
properties.compression = properties.compression or "RAW" properties.compression = properties.compression or "RAW"
properties.pixel_depth = properties.pixel_depth or 24
self.pixel_depth = #self.pixels[1][1] * 8
if nil == properties.color_format then
if 8 == self.pixel_depth then
properties.color_format = "Y8"
elseif 24 == self.pixel_depth then
properties.color_format = "B8G8R8"
elseif 32 == self.pixel_depth then
properties.color_format = "B8G8R8A8"
end
end
assert( nil ~= properties.color_format )
self:encode(properties) self:encode(properties)