首页 > 代码库 > Lua生成位图—string.pack打包数据的应用

Lua生成位图—string.pack打包数据的应用

  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 = http://www.mamicode.com/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 = http://www.mamicode.com/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 = http://www.mamicode.com/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 = http://www.mamicode.com/table.concat(tab_plex)
180 end
181 
182 
183 BMP:new("123")
最后一个是按照块大小生成数组,再通过数组的值映射成图像的块,最后会生成这样的图片:
技术分享

 

Lua生成位图—string.pack打包数据的应用