local colors_list = { colors.white, colors.orange, colors.magenta, colors.lightBlue, colors.yellow, colors.lime, colors.pink, colors.gray, colors.lightGray, colors.cyan, colors.purple, colors.blue, colors.brown, colors.green, colors.red, colors.black } local function load(path) local image = { w = 0, h = 0, scale = 1.0, palette = {}, lines = {} } local fp, err = io.open(path, "rb") if not fp then return nil, err end local magic = fp:read(4) if magic ~= "CCPI" then return nil, "Invalid header: expected CCPI got " .. magic end image.w, image.h = string.byte(fp:read(1)), string.byte(fp:read(1)) image.scale = 0.5 + string.byte(fp:read(1)) * 5 / 255 for i = 1, 16 do image.palette[i] = bit32.lshift(string.byte(fp:read(1)), 16) image.palette[i] = bit32.bor(image.palette[i], bit32.lshift(string.byte(fp:read(1)), 8)) image.palette[i] = bit32.bor(image.palette[i], string.byte(fp:read(1))) end for y = 1, image.h do local line = { s = "", bg = "", fg = "" } for x = 1, image.w do line.s = line.s .. fp:read(1) local color = string.byte(fp:read(1)) line.bg = line.bg .. string.format("%x", bit32.band(0xF, color)) line.fg = line.fg .. string.format("%x", bit32.band(0xF, bit32.rshift(color, 4))) end table.insert(image.lines, line) end fp:close() return image end local function draw(img, ox, oy, monitor) local t = monitor or term.current() ox = ox or 1 oy = oy or 1 for i = 1, 16 do t.setPaletteColor(colors_list[i], img.palette[i]) end t.setTextScale(img.scale) for y = 1, img.h do t.setCursorPos(ox, oy + y - 1) t.blit(img.lines[y].s, img.lines[y].fg, img.lines[y].bg) end end return { load = load, draw = draw }