faubiguy

CBM Library

Oct 16th, 2012
307
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Lua 5.52 KB | None | 0 0
  1. local tags = {"&f", "&6", "&f", "&b", "&e",  "&a", "&d", "&8", "&7", "&3", "&5", "&1", "&f", "&2", "&c", "&0"}
  2. local reverseTags = {}
  3. for k,v in pairs(tags) do
  4.     reverseTags[v] = k-1
  5. end
  6.  
  7. function loadCBM(sFile, useTags, noAnimation)
  8.     if (not fs.exists(sFile)) or fs.isDir(sFile)
  9.         then return nil, "Invalid file or directory"
  10.     else
  11.         local file = fs.open(sFile, "rb")
  12.         if not file then return nil, "Invalid file or directory 2" end
  13.         --[[local]] bytes = {}
  14.         byteCopy = {}
  15.         while true do
  16.             local byte = file.read()
  17.             if not byte then break end
  18.             table.insert(bytes, byte)
  19.             table.insert(byteCopy, byte)
  20.         end
  21.         file.close()
  22.         --[[local]] width, height = 0, 0
  23.         if #bytes < 12 then return nil, "Invalid image" end
  24.         for i=1,3 do
  25.             if table.remove(bytes,1) ~= string.byte("CBM", i) then return nil, "Not a CBM file" end
  26.         end
  27.         for byteNum=3,0,-1 do
  28.             height = height + (2^byteNum)*table.remove(bytes,1)
  29.         end
  30.         for byteNum=3,0,-1 do
  31.             width = width + (2^byteNum)*table.remove(bytes,1)
  32.         end
  33.         --[[local]] flags = table.remove(bytes, 1)
  34.         --[[local]] trans = bit.band(flags, 1) ~= 0; flags = bit.brshift(flags, 1)
  35.         --[[local]] animated = bit.band(flags, 1) ~= 0; flags = bit.brshift(flags, 1)
  36.         --[[local]] reps = table.remove(bytes, 1)
  37.         --[[local]] interval = table.remove(bytes, 1) + 1
  38.         --[[local]] imgBytes = math.ceil(width*height/2)
  39.         --[[local]] alphaBytes = trans and math.ceil(width*height/8) or 0
  40.         if #bytes%(imgBytes+alphaBytes)~=0 then return nil, "Invalid image 2" end
  41.         local frameNum = animated and #bytes/(imgBytes+alphaBytes) or 1
  42.         local frames = {}
  43.         for _=1,noAnimation and 1 or frameNum do
  44.             local pixels = {}
  45.             local pixelList = {}
  46.             local bitMask = {}
  47.             for i=1,imgBytes do
  48.                 local byte = table.remove(bytes, 1)
  49.                 table.insert(pixelList, 1, math.floor(byte/16))
  50.                 table.insert(pixelList, 1, byte%16)
  51.                 if useTags then
  52.                     for i=1,2 do
  53.                         pixelList[i] = tags[pixelList[i]+1]
  54.                     end
  55.                 end
  56.             end
  57.             if trans then
  58.                 for i=1,alphaBytes do
  59.                     local insertPoint = #bitMask + 1
  60.                     local byte = table.remove(bytes, 1)
  61.                     for j=1,8 do
  62.                         --[[if ((i-1)*8)+j<=width*height then]] table.insert(bitMask, insertPoint, bit.band(byte, 1)) --end
  63.                         bit.brshift(byte, 1)
  64.                     end
  65.                 end
  66.             end
  67.             if (width*height)%2 == 1 then pixelList[#pixelList] = nil end
  68.             for row=1,height do
  69.                 pixels[row] = {}
  70.                 for column=1,width do
  71.                     pixels[row][column] = table.remove(pixelList)
  72.                     if trans then
  73.                         if table.remove(bitMask, 1) == 1 then
  74.                             pixels[row][column] = -1
  75.                         end
  76.                     end
  77.                 end
  78.             end
  79.             table.insert(frames, pixels)
  80.         end
  81.         if not noAnimation then frames.interval = interval end
  82.         if not noAnimation then frames.repetitions = (reps == 0) and math.huge or reps end
  83.         return noAnimation and frames[1] or frames
  84.     end
  85. end
  86.  
  87. function saveCBM( sFile, frames, trans)
  88.     t = trans
  89.     function toBytes(number, byteCount)
  90.         local byteCount = byteCount or 4
  91.         local byteTable = {}
  92.         for _=1,byteCount do
  93.             table.insert(byteTable, 1, number%256)
  94.             number=(number-byteTable[1])/256
  95.         end
  96.         return byteTable
  97.     end
  98.     if not (frames and sFile) then return nil, "Invalid argument" end
  99.     local reps = frames.repetitions or 0
  100.     if reps == math.huge then reps = 0 end
  101.     if reps > 255 then reps = 255 end
  102.     local interval = frames.interval or 10
  103.     if interval > 255 then interval = 255 end
  104.     --[[local]] animated = type(frames[1][1]) == "table"
  105.     local bytes = {string.byte("CBM", 1, 3)}
  106.     local pixels = animated and frames[1] or frames
  107.     frames = animated and frames or {frames}
  108.     local height = #pixels
  109.     if height == 0 then return nil, "Empty image" end
  110.     local width = #pixels[1]
  111.     for i=2,height do
  112.         if #pixels[i] ~= width then return nil, "Invalid image" end
  113.     end
  114.     local widthBytes = toBytes(width)
  115.     local heightBytes = toBytes(height)
  116.     for i=1,4 do
  117.         table.insert(bytes, heightBytes[i])
  118.     end
  119.     for i=1,4 do
  120.         table.insert(bytes, widthBytes[i])
  121.     end
  122.     --[[local]] flags = 0
  123.     flags = flags + (animated and 1 or 0)
  124.     flags = bit.blshift(flags, 1); flags = flags + (trans and 1 or 0)
  125.     table.insert(bytes, flags)
  126.     table.insert(bytes, reps)
  127.     table.insert(bytes, interval)
  128.     for _,pixels in ipairs(frames) do
  129.         local bitMask = {}
  130.         for row = 1,height do
  131.             for column = 1,width,2 do
  132.                 pixels[row][2] = pixels[row][2] or 0
  133.                 for i=1,2 do
  134.                     if type(pixels[row][i]) ~= "number" then
  135.                         if string.sub(pixels[row][i],1,1) == "&" then
  136.                             pixels[row][i] = reverseTags[pixels[row][i]]
  137.                         else return nil, "Invalid pixel: "..row..", "..column+i-1
  138.                         end
  139.                     end
  140.                 end
  141.                 if pixels[row][1] > 15 or pixels[row][2]  > 15 or pixels[row][1] < -1 or pixels[row][2] < -1 then return nil, "Invalid pixel 2: "..row..", "..column end
  142.                 if pixels[row][1] == -1 then pixels[row][1] = 0 table.insert(bitMask, 1) else table.insert(bitMask, 0) end
  143.                 if pixels[row][2] == -1 then pixels[row][2] = 0 table.insert(bitMask, 1) else table.insert(bitMask, 0) end
  144.                 table.insert(bytes, table.remove(pixels[row],1)*16 + table.remove(pixels[row],1))
  145.             end
  146.         end
  147.         while #bitMask%8~=0 do table.insert(bitMask, 0) end
  148.         if trans then
  149.             for i=1,#bitMask,8 do
  150.                 local byte = 0
  151.                 for j=0,7 do
  152.                 byte = byte + 2^(7-j) * bitMask[i+j]
  153.             end
  154.                 table.insert(bytes, byte)
  155.             end
  156.         end
  157.     end
  158.     local yieldcount = 0
  159.     local file = fs.open(sFile, "wb")
  160.     for _,byte in ipairs(bytes) do
  161.         yieldcount = yieldcount + 1
  162.         if yieldcount >= 64 then os.queueEvent(".") os.pullEvent(".") yieldcount = 0 end
  163.         file.write(byte)
  164.     end
  165.     file.close()
  166.     return true
  167. end
Advertisement
Add Comment
Please, Sign In to add comment