1 #! /usr/bin/env lua
2 -- fileheader 14bytes
3 -- infoheader 40bytes
4 -- 数据用小端储存方式
5 -- local fileheader =
6 -- {
7 -- bfType = 2 byte,
8 -- bfSize = 4 byte,
9 -- bfReserved1 = 2 byte, must = 0,
10 -- bfReserved2 = 2 byte, must = 0,
11 -- bfOffBits = 4 byte,
12
13 -- }
14 -- local infoheader =
15 -- {
16 -- biSize = 4 byte, default = 40,
17 -- biWidth = 4 byte,
18 -- biHeight = 4 byte,
19 -- biPlanes = 2 byte, must =1,
20 -- biBitCount = 2 byte , 1/4/8/24/32
21 -- bitCompression = 4 byte
22 -- biSizeImage = 4 byte
23 -- biXPelsPerMeter = 4 byte
24 -- biYPelsPerMeter = 4 byte
25 -- biClrUsed = 4 byte
26 -- biClrImortant = 4 byte
27 -- }
28
29 local BMP = {}
30 function BMP:new( ... )
31 local biBitCount = 24 -- 24bit/像素,也就是3byte/像素
32 local biWidth = 256 -- 默认256像素宽
33 local biHeight = 256 -- 默认256像素高
34 local message = string.format("生成24位位图,大小为 %d * %d ...",biWidth,biHeight)
35 print(message)
36 -- 生成FHeader
37 self:createFHeader(biWidth,biHeight,biBitCount)
38 -- 生成IHeader
39 self:createIHeader(biWidth,biHeight,biBitCount)
40 local fname = "bmp_" .. os.date("%X"):gsub(":","") .. ".bmp"
41 local file = io.open(fname,"wb")
42 file:write(self.fheader)
43 file:write(self.iheader)
44 -- 生成图像数据的方法,都是生成self.data(256*256的矩阵)
45 local arg = { ... }
46 -- 空,随机生成各个像素点
47 if not next(arg) then
48 self:creatRandomData()
49 else
50 self:creatRandomMap()
51 end
52
53 if self.data then
54 file:write(self.data)
55 end
56 file:close()
57 os.execute("open " .. fname)
58
59 -- -- 调用图像数据生成函数
60 -- local bmp_data = self:creatSingleton()
61 -- local function testBMP()
62 -- local file = io.open("bmp.bmp","wb")
63 -- file:write(self.fheader)
64 -- file:write(self.iheader)
65 -- file:write(bmp_data)
66 -- file:close()
67 -- end
68 -- return testBMP
69 end
70
71 function BMP:createFHeader(biWidth,biHeight,biBitCount)
72 self.bfType = 0x4D42
73 self.bfSize = biWidth * biHeight * biBitCount/8 + 54 --写死54字节的header
74 self.bfReserved1 = 0
75 self.bfReserved2 = 0
76 self.bfOffBits = 54 -- 32位位图不要调色板,所以偏移54位后就是图像数据
77 self.bfpackfmt = "<I2I4I2I2I4"
78 print(string.format("文件大小为: %d ,文件头大小为: %d ",self.bfSize,string.packsize(self.bfpackfmt)))
79 self.fheader = string.pack(self.bfpackfmt,self.bfType,self.bfSize,self.bfReserved1,self.bfReserved2,self.bfOffBits)
80 end
81
82
83 function BMP:createIHeader(biWidth,biHeight,biBitCount)
84 self.biSize = 40 -- infoheader头默认大小
85 self.biWidth = biWidth
86 self.biHeight = biHeight
87 self.biPlanes = 1
88 self.biBitCount = biBitCount
89 self.bitCompression = 0
90 self.biSizeImage = 0
91 self.biXPelsPerMeter = 0
92 self.biYPelsPerMeter = 0
93 self.biClrUsed = 0
94 self.biClrImortant = 0
95 self.bipackfmt = "<I4I4i4I2I2I4I4I4I4I4I4"
96 print(string.format("位图头大小为: %d ",string.packsize(self.bipackfmt)))
97 self.iheader = string.pack(self.bipackfmt,self.biSize,self.biWidth,self.biHeight,self.biPlanes,self.biBitCount,self.bitCompression,self.biSizeImage,self.biXPelsPerMeter,self.biYPelsPerMeter,self.biClrUsed,self.biClrImortant)
98 end
99
100 function BMP:creatRandomData()
101 local singlefmt = "<I1I1I1"
102 local tab_plex = {}
103 math.randomseed(os.time())
104 local b,g,r = math.random(256)-1,math.random(256)-1,math.random(256)-1
105 local randomspeed = 12800
106 for i = 1, self.biWidth*self.biHeight,1 do
107 if i%randomspeed == 0 then
108 b,g,r = math.random(256)-1,math.random(256)-1,math.random(256)-1
109 end
110 table.insert(tab_plex,string.pack(singlefmt,b,g,r))
111 end
112 self.data = table.concat(tab_plex)
113 end
114
115 function BMP:creatSingleData (b,g,r)
116 local b = tonumber(b) or 0
117 local g = tonumber(g) or 255
118 local r = tonumber(r) or 0
119 local singlefmt = "<I1I1I1"
120 local tab_plex = {}
121 for i = 1, self.biWidth* self.biHeight,1 do
122 table.insert(tab_plex,string.pack(singlefmt,b,g,r))
123 end
124 self.data = table.concat(tab_plex)
125 end
126
127 function BMP:creatFuncData (tab_arg)
128
129 end
130
131 function BMP:creatRandomMap(diffcult)
132 -- 一个点具有实际表示 4*4的像素
133 local plex_per_cell = 8
134 local clr_open = {255,255,255}
135 local clr_close = {0,0,0}
136 -- 要生成的是64*64的0/1矩阵,如果false就是堵住的点,如果是true是开服的点
137 local row,column = self.biWidth/plex_per_cell,self.biHeight/plex_per_cell
138 local map = {}
139 local singlefmt = "<I1I1I1"
140 local tab_plex = {}
141 local diffcult = diffcult or 5
142 math.randomseed(os.time())
143 for i = 1,row do
144 for j =1,column do
145 local var = math.random(10)
146 if var>diffcult then
147 map[row*(i-1)+j] = true
148 else
149 map[row*(i-1)+j] = false
150 end
151 end
152 end
153 print()
154 -- 开始生成self.data 表,通过map表坐标映射生成self.data
155 for i,isopen in ipairs(map) do
156 local map_column = i%(column)
157 if map_column ==0 then map_column = column end
158 local map_row = (i - map_column)//row +1
159 --print(map_row,map_column)
160 -- map_row,map_column 都乘以4映射一个数组出来,再根据数据算出在self.data中的索引
161 local map_t ={}
162 for k = (map_row-1)*plex_per_cell,map_row*plex_per_cell do
163 for j = (map_column-1)*plex_per_cell,map_column*plex_per_cell do
164 -- print(map_row,map_column, "=> ",k,j )
165 table.insert(map_t,{k,j})
166 end
167 end
168
169 for _,pos in ipairs(map_t) do
170 local k,j = table.unpack(pos)
171 --print(k,j)
172 if isopen then
173 tab_plex[(k-1)*self.biWidth + j] = string.pack(singlefmt,clr_open[1],clr_open[2],clr_open[3])
174 else
175 tab_plex[(k-1)*self.biWidth + j] = string.pack(singlefmt,clr_close[1],clr_close[2],clr_close[3])
176 end
177 end
178 end
179 self.data = table.concat(tab_plex)
180 end
181
182
183 BMP:new("123")
最后一个是按照块大小生成数组,再通过数组的值映射成图像的块,最后会生成这样的图片: