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
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
--[[
BASIC BITMAP LOADING SYSTEM
- - - - - - - - - - - - - -
	Special thanks to:
	------------------
	>Leegao - I used part of his struct.lua
	
	News
	----
	>PNG is now working
	
	-Flacko
	3/02/2010
]]
function ReadInt(file,endian)
	local b = {0,0,0,0}
	for i=1, 4 do
		local a = file:read(1)
		if a then
			b[i] = string.byte(a)
		end
	end
	if endian == "l" then --Little endian reading, for BMP format
		return b[1] + b[2]*256 + b[3]*256e2 + b[4]*256e3
	elseif endian == "b" then --big endian reading, for PNG format
		return b[1]*256e3 + b[2]*256e2 + b[3]*256 + b[4]
	else
		error("ReadInt: Wrong endian string (Arg. #2)")
	end
end
function ReadShort(file, endian)
	local b = {0,0}
	for i=1, 2 do
		local a = file:read(1)
		if a then
			b[i] = string.byte(a)
		end
	end
	if endian == "l" then --Little endian reading, for BMP format
		return b[1] + b[2]*256
	elseif endian == "b" then --big endian reading, for PNG format
		return b[1]*256 + b[2]
	else
		error("ReadShort: Wrong endian string (Arg. #2)")
	end
end
local function ReadPixel(file,bpp)
	if not bpp then
		bpp = 24
	end
	if bpp == 24 then
		return {
			b = string.byte(file:read(1)),
			g = string.byte(file:read(1)),
			r = string.byte(file:read(1))
		}
	elseif bpp==8 then
	--[[Only 24 and 8 bit color depth is supported
	8bit colormode only works for grayscale
	Not indexed color. No improvements planned]]
	
	local byte = string.byte(file:read(1))
	return {
		r = byte,
		g = byte,
		b = byte
	}
	end
end
local function ReadPadding(file,w)
	if w > 4 then
		return
	else
		file:read(w)
	end
end
function loadBitmap(dir)
	local BMP = assert(io.open(dir,"rb"),"loadBitmap: Image '"..dir.."' NOT FOUND!")
	
	local newbmp = {fsize,w,h,bpp,typ,dir = dir, map={}}
	
	local ReadInt = function(e) return ReadInt(BMP,e) end
	local ReadShort = function(e) return ReadShort(BMP,e) end
	
	local FILETYPE = BMP:read(2)
	
	if FILETYPE == "BM" then
		newbmp.typ = "bmp"
		newbmp.fsize = ReadInt("l")
		BMP:read(12)
		newbmp.w = ReadInt("l")
		newbmp.h = ReadInt("l")
		BMP:read(2)
		newbmp.bpp = ReadShort("l")
		for y=newbmp.h, 1, -1 do
			newbmp.map[y] = {}
			for x=1,newbmp.w do
				newbmp.map[y][x] = ReadPixel(BMP,newbmp.bpp)
			end
			ReadPadding(BMP,newbmp.w)--padding
		end
		BMP:close()
		return newbmp
	else
		FILETYPE = FILETYPE..BMP:read(2)
		
		if FILETYPE == "\137PNG" then
			BMP:read(8)
			if BMP:read(4) == "IHDR" then
				newbmp.typ = "png"
				newbmp.w = ReadInt("b")
				newbmp.h = ReadInt("b")
				BMP:close()
				return newbmp
			end
		end
		
	end
	error("loadBitmap: Unknown file header: "..dir)
end
--[[
USAGE
-----
The loadBitmap(dir) function will load an image file.
Regardless of it's extension, it will determine
the bitmap's format using it's headers.
Only windows bitmaps (.BMP) and portable networks graphics(.PNG)
are supported.
A successful call to the loadBitmap function will return a table
with the following keys:
typ | String, representing the format ie: "png"
w | Number, it is the width in pixels ie: 5
h | Number, it is the height in pixels ie: 300
Additionaly, the function will load additional data for bmp files:
fsize | Number, size of the file in bytes ie: 10035
bpp | Number, bits per pixel ie: 24
map | Table, this table contains more tables
describing each pixel's RGB values
map[y][x] | Table, (note that y axis goes first), this table
	 has three keys: r, g and b each one is a number
	 that represents the corresponding color value
	 for that pixel
]]