--[[ auto_pic.lua - Auto-fit image to monitor Usage: auto_pic fill: stretch to fill entire screen (may distort) fit: keep aspect ratio, fill as much as possible, center ]] local args = {...} if #args < 2 then print("Usage: auto_pic ") return end local mode = args[1] local url = args[2] -- 1. Find monitor local mon = peripheral.find("monitor") if not mon then print("ERROR: No monitor found") return end -- 2. Get monitor grid size local cols, rows = mon.getSize() print("Monitor: " .. cols .. " x " .. rows) -- 3. Download image via imgon-cc as .bimg (400x400 to get enough data) local bimgFile = "/tmp/pic.bimg" local dlCmd = "wget https://imgon.cyberbit.dev/400x400:bimg/" .. url .. " " .. bimgFile print("Downloading image...") shell.run(dlCmd) if not fs.exists(bimgFile) then print("ERROR: Download failed, check URL") return end -- 4. Parse .bimg format local function parseBimg(filename) local f = fs.open(filename, "rb") if not f then return nil end -- .bimg: first 4 bytes width (little-endian), next 4 bytes height local wBytes = f.read(4) local hBytes = f.read(4) if not wBytes or #wBytes < 4 or not hBytes or #hBytes < 4 then f.close() return nil end local w = string.byte(wBytes, 1) + string.byte(wBytes, 2)*256 + string.byte(wBytes, 3)*65536 + string.byte(wBytes, 4)*16777216 local h = string.byte(hBytes, 1) + string.byte(hBytes, 2)*256 + string.byte(hBytes, 3)*65536 + string.byte(hBytes, 4)*16777216 local data = f.readAll() f.close() if #data < w * h then print("WARNING: Incomplete image data") return nil end return {width = w, height = h, pixels = data} end local img = parseBimg(bimgFile) if not img then print("ERROR: Failed to parse image") return end print("Original image: " .. img.width .. " x " .. img.height) -- 5. Calculate scaling local function calcScale(imgW, imgH, screenW, screenH, mode) local scaleX = screenW / imgW local scaleY = screenH / imgH if mode == "fill" then return scaleX, scaleY, 1, 1 else -- fit local scale = math.min(scaleX, scaleY) local outW = math.floor(imgW * scale) local outH = math.floor(imgH * scale) local offX = math.floor((screenW - outW) / 2) + 1 local offY = math.floor((screenH - outH) / 2) + 1 return scale, scale, offX, offY end end local sx, sy, offX, offY if mode == "fill" then sx, sy, offX, offY = calcScale(img.width, img.height, cols, rows, "fill") offX, offY = 1, 1 else sx, sy, offX, offY = calcScale(img.width, img.height, cols, rows, "fit") end print("Scale: " .. sx .. ", " .. sy) print("Offset: " .. offX .. ", " .. offY) -- 6. Draw to monitor (nearest neighbor) mon.clear() local function drawScaled() local pixels = img.pixels local imgW, imgH = img.width, img.height for y = 0, rows - 1 do for x = 0, cols - 1 do local srcX = math.floor((x - offX + 1) / sx) local srcY = math.floor((y - offY + 1) / sy) if srcX >= 0 and srcX < imgW and srcY >= 0 and srcY < imgH then local idx = srcY * imgW + srcX + 1 local color = string.byte(pixels, idx) -- 0-15 mon.setCursorPos(x + 1, y + 1) mon.blit(" ", string.char(color + 32), " ") end end end end drawScaled() fs.delete(bimgFile) print("Done")