Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- local function readBMP(filename)
- local file = fs.open(filename, "rb")
- if not file then
- return nil, "Failed to open file"
- end
- local header = file.read(54)
- local width = string.byte(header, 19) + string.byte(header, 20) * 256
- local height = string.byte(header, 23) + string.byte(header, 24) * 256
- local pixels = {}
- for y = height, 1, -1 do
- pixels[y] = {}
- for x = 1, width do
- local b = file.read(1)
- local g = file.read(1)
- local r = file.read(1)
- pixels[y][x] = {r = string.byte(r), g = string.byte(g), b = string.byte(b)}
- end
- if y % 10 == 0 then
- os.queueEvent("yield")
- os.pullEvent("yield")
- end
- end
- file.close()
- return {width = width, height = height, pixels = pixels}
- end
- local function resizeImage(image, newWidth, newHeight)
- local resized = {width = newWidth, height = newHeight, pixels = {}}
- for y = 1, newHeight do
- resized.pixels[y] = {}
- for x = 1, newWidth do
- local srcX = math.floor(x * image.width / newWidth)
- local srcY = math.floor(y * image.height / newHeight)
- resized.pixels[y][x] = image.pixels[srcY][srcX]
- end
- if y % 10 == 0 then
- os.queueEvent("yield")
- os.pullEvent("yield")
- end
- end
- return resized
- end
- local function rgbToComputerCraftColor(r, g, b)
- local colors = {
- [0x1] = {240, 240, 240}, [0x2] = {242, 178, 51}, [0x4] = {229, 127, 216},
- [0x8] = {153, 178, 242}, [0x10] = {222, 222, 108}, [0x20] = {127, 204, 25},
- [0x40] = {242, 178, 204}, [0x80] = {76, 76, 76}, [0x100] = {153, 153, 153},
- [0x200] = {76, 153, 178}, [0x400] = {178, 102, 229}, [0x800] = {51, 102, 204},
- [0x1000] = {127, 102, 76}, [0x2000] = {87, 166, 78}, [0x4000] = {204, 76, 76},
- [0x8000] = {17, 17, 17}
- }
- local closestColor = 0x1
- local minDifference = math.huge
- for code, rgb in pairs(colors) do
- local difference = math.sqrt((r - rgb[1])^2 + (g - rgb[2])^2 + (b - rgb[3])^2)
- if difference < minDifference then
- minDifference = difference
- closestColor = code
- end
- end
- return closestColor
- end
- local function displayBMP(image, output)
- local width, height = output.getSize()
- local resizedImage = resizeImage(image, width, height)
- for y = 1, height do
- for x = 1, width do
- local pixel = resizedImage.pixels[y][x]
- local color = rgbToComputerCraftColor(pixel.r, pixel.g, pixel.b)
- output.setCursorPos(x, y)
- output.setBackgroundColor(color)
- output.write(" ")
- end
- if y % 5 == 0 then
- os.queueEvent("yield")
- os.pullEvent("yield")
- end
- end
- end
- local function displayBMPMode2(image, output)
- local width, height = output.getSize()
- local resizedImage = resizeImage(image, width * 2, height * 2)
- local charSet = {" ", "\131", "\132", "\133", "\135", "\136", "\137", "\138", "\139", "\140"}
- local colors = {
- [0x1] = {240, 240, 240}, [0x2] = {242, 178, 51}, [0x4] = {229, 127, 216},
- [0x8] = {153, 178, 242}, [0x10] = {222, 222, 108}, [0x20] = {127, 204, 25},
- [0x40] = {242, 178, 204}, [0x80] = {76, 76, 76}, [0x100] = {153, 153, 153},
- [0x200] = {76, 153, 178}, [0x400] = {178, 102, 229}, [0x800] = {51, 102, 204},
- [0x1000] = {127, 102, 76}, [0x2000] = {87, 166, 78}, [0x4000] = {204, 76, 76},
- [0x8000] = {17, 17, 17}
- }
- local function getNearestColor(r, g, b)
- local closestColor = 0x1
- local minDifference = math.huge
- for code, rgb in pairs(colors) do
- local difference = math.abs(r - rgb[1]) + math.abs(g - rgb[2]) + math.abs(b - rgb[3])
- if difference < minDifference then
- minDifference = difference
- closestColor = code
- end
- end
- return closestColor
- end
- local function blendColors(c1, c2)
- return {
- r = (c1.r + c2.r) / 2,
- g = (c1.g + c2.g) / 2,
- b = (c1.b + c2.b) / 2
- }
- end
- for y = 1, height do
- for x = 1, width do
- local tl = resizedImage.pixels[y*2-1][x*2-1]
- local tr = resizedImage.pixels[y*2-1][x*2]
- local bl = resizedImage.pixels[y*2][x*2-1]
- local br = resizedImage.pixels[y*2][x*2]
- local avgColor = blendColors(blendColors(tl, tr), blendColors(bl, br))
- local intensity = (avgColor.r + avgColor.g + avgColor.b) / 3
- local pattern = math.floor(intensity / 28.4) + 1
- local bgColor = getNearestColor(tl.r, tl.g, tl.b)
- local fgColor = getNearestColor(br.r, br.g, br.b)
- if bgColor == fgColor then
- if pattern > 5 then
- fgColor = getNearestColor(math.min(br.r + 30, 255), math.min(br.g + 30, 255), math.min(br.b + 30, 255))
- else
- bgColor = getNearestColor(math.max(tl.r - 30, 0), math.max(tl.g - 30, 0), math.max(tl.b - 30, 0))
- end
- end
- output.setCursorPos(x, y)
- output.setBackgroundColor(bgColor)
- output.setTextColor(fgColor)
- output.write(charSet[pattern])
- end
- if y % 5 == 0 then
- os.queueEvent("yield")
- os.pullEvent("yield")
- end
- end
- end
- local function displayBMPCraftOSPC(image, output, colorMode)
- local screenWidth, screenHeight = output.getSize()
- local imageWidth, imageHeight = image.width, image.height
- -- Store the original palette and graphics mode
- local originalPalette = {}
- for i = 0, 255 do
- originalPalette[i] = {term.getPaletteColor(i)}
- end
- local originalGraphicsMode = term.getGraphicsMode()
- -- Store the original text colors
- local originalBackgroundColor = term.getBackgroundColor()
- local originalTextColor = term.getTextColor()
- term.setGraphicsMode(colorMode)
- if colorMode == 2 then
- -- Preserve first 16 colors, set up custom palette for the rest
- -- Define a color cube palette with more distinct colors
- local cubeSize = 5 -- Number of steps for each color component (R, G, B)
- for i = 16, 255 do
- local index = i - 16
- local rIndex = math.floor(index / (cubeSize * cubeSize))
- local gIndex = math.floor((index % (cubeSize * cubeSize)) / cubeSize)
- local bIndex = index % cubeSize
- local r = math.floor(rIndex * 255 / (cubeSize - 1))
- local g = math.floor(gIndex * 255 / (cubeSize - 1))
- local b = math.floor(bIndex * 255 / (cubeSize - 1))
- term.setPaletteColor(i, r / 255, g / 255, b / 255)
- end
- end
- local function adjustBrightness(value)
- return math.min(255, math.max(0, math.floor(value * 1.2))) -- Increase brightness by 20%
- end
- local function mapColor(r, g, b)
- r, g, b = adjustBrightness(r), adjustBrightness(g), adjustBrightness(b)
- if colorMode == 2 then
- -- Map to the custom color cube palette
- local cubeSize = 5
- local rIndex = math.floor(r / (255 / (cubeSize - 1)))
- local gIndex = math.floor(g / (255 / (cubeSize - 1)))
- local bIndex = math.floor(b / (255 / (cubeSize - 1)))
- return 16 + rIndex * cubeSize * cubeSize + gIndex * cubeSize + bIndex
- else
- return rgbToComputerCraftColor(r, g, b)
- end
- end
- for y = 0, screenHeight * 9 - 1 do
- for x = 0, screenWidth * 6 - 1 do
- local sourceX = math.floor(x * imageWidth / (screenWidth * 6))
- local sourceY = math.floor(y * imageHeight / (screenHeight * 9))
- local pixel = image.pixels[sourceY + 1][sourceX + 1]
- local color = mapColor(pixel.r, pixel.g, pixel.b)
- output.setPixel(x, y, color)
- end
- if y % 10 == 0 then
- os.queueEvent("yield")
- os.pullEvent("yield")
- end
- end
- print("Image displayed. Press any key to exit.")
- os.pullEvent("key")
- -- Restore the original palette and graphics mode
- term.setGraphicsMode(originalGraphicsMode)
- for i = 0, 255 do
- term.setPaletteColor(i, table.unpack(originalPalette[i]))
- end
- -- Restore the original text colors
- term.setBackgroundColor(originalBackgroundColor)
- term.setTextColor(originalTextColor)
- -- Clear the screen and reset cursor position
- term.setBackgroundColor(colors.black)
- term.setTextColor(colors.white)
- term.clear()
- term.setCursorPos(1, 1)
- end
- local function downloadBMP(url, filename)
- if not http then
- error("HTTP API is not enabled. Enable it in ComputerCraft.cfg")
- end
- print("Downloading " .. url .. "...")
- local response = http.get(url, nil, true)
- if not response then
- error("Failed to download file")
- end
- local file = fs.open(filename, "wb")
- local content = response.readAll()
- for i = 1, #content, 8192 do
- file.write(content:sub(i, i + 8191))
- os.queueEvent("yield")
- os.pullEvent("yield")
- end
- file.close()
- response.close()
- print("Downloaded as " .. filename)
- end
- print("CC-BMP : An Enhanced BMP Image Viewer For ComputerCraft Coded By nonogamer9!")
- print("Enter a local filename or URL:")
- local input = read()
- local filename = input
- if string.sub(input, 1, 4) == "http" then
- filename = "downloaded.bmp"
- downloadBMP(input, filename)
- end
- local image, err = readBMP(filename)
- if not image then
- print("Error reading BMP file:", err)
- return
- end
- print("Select display mode:")
- print("1. Basic ComputerCraft screen")
- print("2. Enhanced Mode (pseudo-resolution and colors)")
- print("3. CraftOS-PC 16-color Graphics Mode")
- print("4. CraftOS-PC 256-color Graphics Mode")
- print("5. Monitor")
- local mode = tonumber(read())
- local output
- if mode == 5 then
- output = peripheral.find("monitor")
- if not output then
- print("No monitor found")
- return
- end
- else
- output = term
- end
- if mode == 1 then
- displayBMP(image, output)
- elseif mode == 2 then
- displayBMPMode2(image, output)
- elseif mode == 3 then
- if term.setGraphicsMode then
- displayBMPCraftOSPC(image, output, 1) -- 16-color mode
- else
- print("CraftOS-PC Graphics Mode not supported")
- end
- elseif mode == 4 then
- if term.setGraphicsMode then
- displayBMPCraftOSPC(image, output, 2) -- 256-color mode
- else
- print("CraftOS-PC Graphics Mode not supported")
- end
- elseif mode == 5 then
- displayBMP(image, output)
- else
- print("Invalid mode selected")
- end
- print("Image displayed")
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement