--[[ auto_pic.lua - 自动适配图片至显示器 用法: auto_pic <模式> <图片直链> 模式: fill (拉伸填充) 或 fit (适应屏幕,保持比例) 例如: auto_pic fill https://example.com/pic.png ]] local args = {...} if #args < 2 then print("用法: auto_pic <图片直链>") return end local mode = args[1] local url = args[2] -- 1. 查找显示器 local mon = peripheral.find("monitor") if not mon then print("错误: 未找到显示器") return end -- 2. 获取显示器网格尺寸 local cols, rows = mon.getSize() print("显示器: " .. cols .. " x " .. rows) -- 3. 下载图片 (使用 imgon-cc 生成 .bimg 格式,尺寸设为 400x400 以获取足够数据) -- 注意: 我们要求服务生成一个较大尺寸的图片,然后缩放绘制。 local bimgFile = "/tmp/pic.bimg" local tmpScript = "/tmp/dl.lua" local dlCmd = "wget https://imgon.cyberbit.dev/400x400:bimg/" .. url .. " " .. bimgFile print("下载图片中...") shell.run(dlCmd) if not fs.exists(bimgFile) then print("下载失败,请检查链接有效性。") return end -- 4. 解析 .bimg 格式 (简单解析) local function parseBimg(filename) local f = fs.open(filename, "rb") if not f then return nil end -- .bimg 格式: 前4字节为宽度 (int32 LE), 接着4字节为高度 (int32 LE) 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 -- 剩余数据为像素: 每个像素1字节 (颜色索引 0-15) local data = f.readAll() f.close() if #data < w * h then print("警告: 图片数据不完整") return nil end return {width = w, height = h, pixels = data} end local img = parseBimg(bimgFile) if not img then print("解析图片失败") return end print("原始图片: " .. img.width .. " x " .. img.height) -- 5. 计算缩放参数 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 offsetX = math.floor((screenW - outW) / 2) + 1 local offsetY = math.floor((screenH - outH) / 2) + 1 return scale, scale, offsetX, offsetY 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("缩放比例: " .. sx .. ", " .. sy) print("偏移: " .. offX .. ", " .. offY) -- 6. 绘制到显示器 (最近邻采样) mon.setTextScale(0.5) -- 可根据需要调整,但不影响网格尺寸 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) -- color 是 0-15 的索引 mon.setCursorPos(x + 1, y + 1) mon.blit(" ", string.char(color + 32), " ") end end end end drawScaled() fs.delete(bimgFile) print("显示完成")