Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- local function _W(f) local e=setmetatable({}, {__index = _ENV or getfenv()}) if setfenv then setfenv(f, e) end return f(e) or e end
- local Class=_W(function(_ENV, ...)
- local Object = { __name = "Object" }
- function Object:init(...) end
- function Object:super(class)
- local obj = self
- return setmetatable({ }, { __index = function(t, k)
- return function(...)
- while class do
- local method = class[k]
- if method then
- return method(obj, ...)
- end
- class = class.__super
- end
- end
- end })
- end
- function Object:createTable()
- local obj = self
- local class = obj:getClass()
- return setmetatable({ }, { __index = function(t, k)
- return function(...)
- local method = class[k]
- return method(obj, ...)
- end
- end })
- end
- function Object:getSuper()
- return rawget(self:getClass(), "__super")
- end
- function Object:getClass()
- return rawget(self, "__class")
- end
- function Object:instanceof(targetType)
- local objectType = self:getClass()
- while objectType do
- if targetType == objectType then
- return true
- end
- objectType = objectType:getSuper()
- end
- return false
- end
- function Object:toString()
- return self:getClass():getName().." ("..tostring(self):sub(8, -1)..")"
- end
- function Object:extend(obj)
- self.__index = self -- This is a metatable
- local obj = obj or {}
- obj.__super = self
- local obj = setmetatable(obj, self)
- return obj
- end
- local Class = Object:extend({__name = "Class"})
- function Class:new(...)
- local instance = { __class = self }
- self:extend(instance)
- instance:init(...)
- return instance
- end
- function Class:getName(name)
- return self.__name
- end
- function Class:subClass(name)
- local instance = { }
- instance.__name = name
- return self:extend(instance)
- end
- return Class
- end)
- Colors=_W(function(_ENV, ...)
- local pairs = pairs
- local colors = colors or setmetatable({}, {__index = function() return 1 end})
- local termSets = {
- [colors.white] = {240, 240, 240},
- [colors.orange] = {242, 178, 51},
- [colors.magenta] = {229, 127, 216},
- [colors.lightBlue] = {153, 178, 242},
- [colors.yellow] = {222, 222, 108},
- [colors.lime] = {127, 204, 25},
- [colors.pink] = {242, 178, 204},
- [colors.gray] = {76, 76, 76},
- [colors.lightGray] = {153, 153, 153},
- [colors.cyan] = {76, 153, 178},
- [colors.purple] = {178, 102, 229},
- [colors.blue] = {37, 49, 146},
- [colors.brown] = {127, 102, 76},
- [colors.green] = {5, 122, 100},
- [colors.red] = {204, 76, 76},
- [colors.black] = {0, 0, 0},
- }
- local strSets = {
- ["0"] = {240, 240, 240},
- ["1"] = {242, 178, 51},
- ["2"] = {229, 127, 216},
- ["3"] = {153, 178, 242},
- ["4"] = {222, 222, 108},
- ["5"] = {127, 204, 25},
- ["6"] = {242, 178, 204},
- ["7"] = {76, 76, 76},
- ["8"] = {153, 153, 153},
- ["9"] = {76, 153, 178},
- ["a"] = {178, 102, 229},
- ["b"] = {37, 49, 146},
- ["c"] = {127, 102, 76},
- ["d"] = {5, 122, 100},
- ["e"] = {204, 76, 76},
- ["f"] = {0, 0, 0},
- }
- local function findClosestColor(colors, r, g, b)
- local smallestDifference = nil
- local smallestColor = nil
- for id, rgb in pairs(colors) do
- local diff = (r - rgb[1])^2 + (g - rgb[2])^2 + (b - rgb[3])^2
- if not smallestDifference or diff < smallestDifference then
- smallestColor = id
- smallestDifference = diff
- end
- end
- return smallestColor
- end
- local closestCache = {}
- --- Find the closest colour using a cache to store the results.
- -- This is because findClosestColor is not the fastest code.
- -- However, this could grow to be 256 ^ 3 bytes large (over 14MiB) which isn't great.
- local function findClosestCached(colors, r, g, b)
- local cache = closestCache[colors]
- if not cache then
- cache = {}
- closestCache[colors] = cache
- end
- local index = r * 65536 + g * 256 + b
- local result = cache[index]
- if not result then
- result = findClosestColor(colors, r, g, b)
- cache[index] = result
- end
- return result
- end
- return {
- findClosestColor = findClosestColor,
- findClosestCached = findClosestCached,
- termSets = termSets,
- strSets = strSets,
- }
- end)
- BitmapPixels=_W(function(_ENV, ...)
- local BitmapPixels = Class:subClass("BitmapPixels")
- function BitmapPixels:init(parser)
- self.parser = parser
- self.pixels = parser.pixels
- self.file = parser.file
- self.width = parser.width
- self.height = parser.height
- end
- function BitmapPixels:parse()
- local width = self.width
- for Y = self.height, 1, -1 do
- local row = {}
- self.pixels[Y] = row
- local startOffset = self.file.offset
- for X = 1, width, 1 do
- row[X] = self:parsePixel()
- end
- self:finaliseRow()
- local pixelsRemaning = (self.file.offset - startOffset) % 4
- if pixelsRemaning > 0 then
- self.file:discardBytes(4 - pixelsRemaning)
- end
- end
- self.file:close()
- end
- function BitmapPixels:parsePixel() return 1 end
- function BitmapPixels:finaliseRow() end
- return BitmapPixels
- end)
- BinaryFile=_W(function(_ENV, ...)
- local BinaryFile = Class:subClass("BinaryFile")
- function BinaryFile:init(path)
- self.path = path
- self.offset = 0
- self.file = fs.open(path, "rb")
- end
- function BinaryFile:close()
- self.file.close()
- self.file = nil
- end
- function BinaryFile:readByte()
- self.offset = self.offset + 1
- return self.file.read()
- end
- function BinaryFile:readBytes(length)
- local bytes = 0
- for i = 0, length - 1, 1 do
- bytes = bytes + (self:readByte() * (256 ^ i))
- end
- return bytes
- end
- function BinaryFile:discardBytes(length)
- for i = 1, length, 1 do
- self:readByte()
- end
- end
- return BinaryFile
- end)
- BitmapDepths=_W(function(_ENV, ...)
- local black, white = {0, 0, 0}, {255, 255, 255}
- --Monochrome bitmap
- local BitmapMono = BitmapPixels:subClass("BitmapMono")
- function BitmapMono:init(parser)
- self:super(BitmapPixels).init(parser)
- self.byte = nil
- self.bitPosition = 0
- self.file:discardBytes(parser.Starts - self.file.Offset)
- end
- function BitmapMono:parsePixel()
- if self.byte == nil then
- local byte = self.file:readByte()
- local byteT = {}
- local counter = 1
- while (counter <= 8) do
- local last = byte % 2
- if(last == 1) then
- byteT[counter] = black
- else
- byteT[counter] = white
- end
- byte = (byte-last)/2
- counter = counter + 1
- end
- self.byte = byteT
- self.bitPosition = 9
- end
- self.bitPosition = self.bitPosition - 1
- return self.byte[self.bitPosition]
- end
- function BitmapMono:finaliseRow()
- self.byte = nil
- self.bitPosition = 0
- end
- --4 Bit Bitmap
- local BitmapFour = BitmapPixels:subClass("Bitmap4")
- function BitmapFour:init(parser)
- self:super(BitmapPixels).init(parser)
- self.colors = {}
- for I = 0, 15, 1 do
- local b = self.file:readByte()
- local g = self.file:readByte()
- local r = self.file:readByte()
- self.file:readByte() -- Should be 0
- self.colors[I] = {r, g, b}
- end
- self.byte = nil
- end
- function BitmapFour:parsePixel()
- local thisColour = nil
- if self.byte == nil then
- local byte = self.file:readByte()
- thisColour = math.floor(byte / 16)
- self.byte = byte % 16
- else
- thisColour = self.byte
- self.byte = nil
- end
- return self.colors[thisColour]
- end
- function BitmapFour:finaliseRow()
- self.byte = nil
- end
- --Eight bit bitmap
- local BitmapEight = BitmapPixels:subClass("Bitmap8")
- function BitmapEight:init(parser)
- self:super(BitmapPixels).init(parser)
- self.colors = {}
- for I = 0, 255, 1 do
- local b = self.file:readByte()
- local g = self.file:readByte()
- local r = self.file:readByte()
- self.file:readByte() -- Should be 0
- self.colors[I] = {r, g, b}
- end
- end
- function BitmapEight:parsePixel()
- return self.colors[self.file:readByte()]
- end
- --24 bit bitmap
- local BitmapTwentyFour = BitmapPixels:subClass("Bitmap24")
- function BitmapTwentyFour:init(parser)
- self:super(BitmapPixels).init(parser)
- self.file:discardBytes(parser.starts - self.file.offset)
- end
- function BitmapTwentyFour:parsePixel()
- local b = self.file:readByte()
- local g = self.file:readByte()
- local r = self.file:readByte()
- return {r, g, b}
- end
- return {
- [1] = BitmapMono,
- [4] = BitmapFour,
- [8] = BitmapEight,
- [24] = BitmapTwentyFour,
- }
- end)
- BitmapParser=_W(function(_ENV, ...)
- local floor, log, sub, pairs = math.floor, math.log, string.sub, pairs
- local BitmapParser = Class:subClass("BitmapParser")
- function BitmapParser:init(file)
- self.file = file
- --==================================
- --Bitmap file header
- --==================================
- self.headerField = string.char(file:readByte()) .. string.char(file:readByte())
- self.size = file:readBytes(4)
- --Useless bytes (not useless but kinda are)
- file:discardBytes(4)
- self.starts = file:readBytes(4)
- --==================================
- -- BITMAPINFOHEADER (DBI Header)
- --==================================
- self.headerSize = file:readBytes(4)
- self.width = file:readBytes(4)
- self.height = file:readBytes(4)
- self.colourPlanes = file:readBytes(2)
- self.colourDepth = file:readBytes(2)
- self.compression = file:readBytes(4)
- --More junky stuff
- file:discardBytes(4) --the image size. This is the size of the raw bitmap data; a dummy 0 can be given for BI_RGB bitmaps.
- file:discardBytes(4) --the horizontal resolution of the image. (pixel per meter, signed integer)
- file:discardBytes(4) --the vertical resolution of the image. (pixel per meter, signed integer)
- file:discardBytes(4) --the number of colors in the color palette, or 0 to default to 2^n
- file:discardBytes(4) --the number of important colors used, or 0 when every color is important; generally ignored
- --Should have an offset of 55
- self.pixels = {}
- local pixelParser = BitmapDepths[self.colourDepth]
- if not pixelParser then
- error("Can't find a parser for depth "..tostring(self.colourDepth))
- end
- pixelParser:new(self):parse()
- end
- local closest, strSets = Colors.findClosestColor, Colors.strSets
- function BitmapParser:save(handle, save)
- if type(handle) == "string" then
- handle = fs.open(handle, "w")
- save = true
- end
- for y, values in pairs(self.pixels) do
- local Line = ""
- for x, col in pairs(values) do
- line = line .. findClosestColor(strSets, unpack(col))
- end
- handle.writeLine(Line)
- end
- if save then
- handle.close()
- end
- end
- return BitmapParser
- end)
- ImageHelpers=_W(function(_ENV, ...)
- local pairs, unpack = pairs, unpack
- function parseFile(path)
- local BinFile = BinaryFile:new(path)
- return BitmapParser:new(BinFile)
- end
- local closest, termSets = Colors.findClosestColor, Colors.termSets
- function createTermPixel(redirect)
- redirect = redirect or term
- return function(x, y, color)
- redirect.setCursorPos(x, y)
- redirect.setBackgroundColour(closest(termSets, unpack(color)))
- redirect.write(" ")
- end
- end
- termPixel = createTermPixel()
- function drawImage(parser, pixel)
- pixel = pixel or termPixel
- for y, row in pairs(parser.pixels) do
- -- print(y)
- for x, color in pairs(row) do
- -- print(string.format(" %s, {%s, %s, %s}", x, color[1], color[2], color[3]))
- pixel(x, y, color)
- end
- end
- end
- end)
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement