1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
|
tga_encoder = {}
local image = setmetatable({}, {
__call = function(self, ...)
local t = setmetatable({}, {__index = image})
t:constructor(...)
return t
end,
})
function image:constructor(pixels)
self.bytes = {}
self.pixels = pixels
self.width = #pixles[1]
self.height = #pixels
self:encode()
end
function image:write(size, value)
-- TGA uses little endian encoding
local l = #self.bytes
for i = 1, size do
local byte = value % 256
value = value - byte
value = value / 256
self.bytes[l + i] = byte
end
end
function image:encode_colormap_spec()
-- first entry index
self:write(2, 0)
-- number of entries
self:write(2, 0)
-- number of bits per pixel
self:write(1, 0)
end
function image:encode_image_spec()
-- X- and Y- origin
self:write(2, 0)
self:write(2, 0)
-- width and height
self:write(2, width)
self:write(2, height)
-- pixel depth
self:write(1, 24)
-- image descriptor
self:write(1, 0)
end
function image:encode_header()
-- id length
self:write(1, 0) -- no image id info
-- color map type
self:write(1, 0) -- no color map
-- image type
self:write(1, 2) -- uncompressed true-color image
-- color map specification
self:encode_colormap_spec()
-- image specification
self:encode_image_spec()
end
function image:encode_data()
for _, row in ipairs(self.pixels) do
for _, pixel in ipairs(row) do
self:write(1, row[3])
self:write(1, row[2])
self:write(1, row[1])
end
end
end
function image:encode()
-- encode header
self:encode_header()
-- no color map and image id data
-- encode data
self:encode_data()
-- no extension area or file footer
end
function image:save(filename)
self.data = self.data or string.char(unpack(self.bytes))
local f = assert(io.open(filename))
f:write(data)
f:close()
end
tga_encoder.image = image
|