%D \module %D [ file=meta-imp-bitmaps, %D version=2021.08.03, %D title=\METAPOST\ Graphics, %D subtitle=Bitmap Manipulations, %D author=Hans Hagen, %D date=\currentdate, %D copyright={PRAGMA ADE \& \CONTEXT\ Development Team}] %C %C This module is part of the \CONTEXT\ macro||package and is %C therefore copyrighted by \PRAGMA. See mreadme.pdf for %C details. \registerctxluafile{libs-imp-imagemagick}{autosuffix} \registerctxluafile{libs-imp-graphicsmagick}{autosuffix} % todo: load png directly \startluacode local char = string.char local concat = table.concat local unpack = unpack graphics.bitmaps.magick = "imagemagick" function graphics.bitmaps.load(name) local inputname = name local outputname = file.replacesuffix("m_k_i_v_mp_" .. name,"pnm") if file.suffix(inputname) == "pnm" then -- no need to convert else local whattodo = table.setmetatableindex( { inputname = inputname, outputname = outputname, }, specification) utilities[graphics.bitmaps.magick].convert(whattodo) end -- local files = utilities.files local f = files.open(outputname) local function read(f) while true do local s = files.readcline(f) if not s then return "" elseif string.find(s,"^#") then -- again else return s end end end local pnm = read(f) local xy = string.split(read(f)," ") local xsize = tonumber(xy[1]) local ysize = tonumber(xy[2]) local bsize = tonumber(read(f)) local bitmap, colorspace if xsize and ysize and bsize then local read = files.readbytetable local data = { } if pnm == "P6" then colorspace = 2 -- rgb for i=1,ysize do local tt = { } for i=1,xsize do tt[i] = read(f,3) end data[i] = tt end elseif pnm == "P5" then colorspace = 1 -- gray for i=1,ysize do data[i] = read(f,xsize) end elseif pnm == "P4" then colorspace = 1 -- todo end bitmap = { xsize = xsize, ysize = ysize, bsize = bsize, inputname = inputname, outputname = outputname, colorspace = colorspace, data = data, } end files.close(f) return bitmap end function graphics.bitmaps.save(b) local xsize = b.xsize local ysize = b.ysize local bsize = b.bsize local colorspace = b.colorspace if xsize and ysize and bsize then local data = b.data local pnm = nil if colorspace == 2 then pnm = "P6" for i=1,ysize do local t = data[i] for i=1,xsize do t[i] = char(unpack(t[i])) end data[i] = concat(t) end elseif colorspace == 1 then pnm = "P5" if xsize > 1024 then local t = data[i] for i=1,xsize do t[i] = char(t[i]) end else for i=1,ysize do data[i] = char(unpack(data[i])) end end else return end local result = concat { pnm .. "\r", xsize .. " " .. ysize .. "\r", bsize .. "\r", concat(data) } local outputname = file.replacesuffix(b.outputname,file.suffix(b.inputname)) local inputname = b.outputname io.savedata(inputname,result) -- local whattodo = table.setmetatableindex( { inputname = inputname, outputname = outputname, }, specification) utilities[graphics.bitmaps.magick].convert(whattodo) b.finalname = outputname end end graphics.bitmaps.manipulators = { } function graphics.bitmaps.manipulators.invert(b) local xsize = b.xsize local ysize = b.ysize local data = b.data local colorspace = b.colorspace if colorspace == 1 then for r=1,ysize do local row = data[r] for c=1,xsize do row[c] = 255 - row[c] end end elseif colorspace == 2 then for r=1,ysize do local row = data[r] for c=1,xsize do local column = row[c] column[1] = 255 - column[1] column[2] = 255 - column[2] column[4] = 255 - column[3] end end end end \stopluacode \continueifinputfile{meta-imp-bitmaps.mkxl} \starttext \startluacode local random = math.random function graphics.bitmaps.manipulators.myframe(b,f) local xsize = b.xsize local ysize = b.ysize local data = b.data local colorspace = b.colorspace if colorspace == 1 then local f = f or 20 local fx = xsize - f + 1 local fy = ysize - f + 1 for c=1,xsize do for r=1,random(f-5,f+5) do data[r][c] = random(0,255) end for r=ysize,random(fy-5,fy+5),-1 do data[r][c] = random(0,255) end end for r=1,ysize do local row = data[r] for c=1,random(f-5,f+5) do row[c] = random(0,255) end for c=xsize,random(fx-5,fx+5),-1 do row[c] = random(0,255) end end elseif colorspace == 2 then local f = f or 20 local fx = xsize - f + 1 local fy = ysize - f + 1 for c=1,xsize do for r=1,random(f-5,f+5) do local v = random(0,255) data[r][c] = { v, v, v } end for r=ysize,random(fy-5,fy+5),-1 do local v = random(0,255) data[r][c] = { v, v, v } end end for r=1,ysize do local row = data[r] for c=1,random(f-5,f+5) do local v = random(0,255) row[c] = { v, v, v } end for c=xsize,random(fx-5,fx+5),-1 do local v = random(0,255) row[c] = { v, v, v } end end end end function graphics.bitmaps.manipulators.colorize(b,m) local xsize = b.xsize local ysize = b.ysize local data = b.data local colorspace = b.colorspace if colorspace == 1 then for r=1,ysize do local row = data[r] for c=1,xsize do local v = row[c] row[c] = m[v] or { v, v, v } end end b.colorspace = 2 end end function graphics.bitmaps.manipulators.evening(b,m) local xsize = b.xsize local ysize = b.ysize local data = b.data local colorspace = b.colorspace if colorspace == 1 then for r=1,ysize do local row = data[r] for c=1,xsize do row[c] = row[c] // 2 end end end end context.startTEXpage() local b = graphics.bitmaps.load("hacker.jpg") graphics.bitmaps.manipulators.myframe(b,20) graphics.bitmaps.save(b) context.externalfigure { b.finalname } context.stopTEXpage() context.startTEXpage() local b = graphics.bitmaps.load("mill.png") graphics.bitmaps.manipulators.invert(b) graphics.bitmaps.manipulators.myframe(b,20) graphics.bitmaps.tocontext(b,50*65536,nil) context.stopTEXpage() do local m = table.setmetatableindex(function(t,k) local v = { k, k, k } t[k] = v return v end) -- local c = { 255, 0, 0 } for i=0x00,0x1F do m[i] = c end -- local c = { 0, 255, 0 } for i=0x20,0x3F do m[i] = c end -- local c = { 0, 0, 255 } for i=0x40,0x5F do m[i] = c end -- local c = { 255, 255, 0 } for i=0x60,0x7F do m[i] = c end -- local c = { 255, 0, 255 } for i=0x80,0x9F do m[i] = c end -- local c = { 0, 255, 255 } for i=0xA0,0xBF do m[i] = c end -- local c = { 255, 255, 255 } for i=0xC0,0xDF do m[i] = c end -- local c = { 0, 0, 0 } for i=0xE0,0xFF do m[i] = c end local c = { 0, 0, 255 } for i=0x40,0x5F do m[i] = c end local c = { 0, 255, 0 } for i=0x80,0x9F do m[i] = c end local c = { 255, 0, 0 } for i=0xB0,0xCF do m[i] = c end context.startTEXpage() local b = graphics.bitmaps.load("mill.png") graphics.bitmaps.manipulators.colorize(b,m) graphics.bitmaps.tocontext(b,50*65536,nil) context.stopTEXpage() end context.startTEXpage() local b = graphics.bitmaps.load("mill.png") graphics.bitmaps.manipulators.evening(b) graphics.bitmaps.tocontext(b,50*65536,nil) context.stopTEXpage() \stopluacode \protected\def\MyImage#1{\ctxlua{ local b = graphics.bitmaps.load("#1") graphics.bitmaps.manipulators.invert(b) graphics.bitmaps.manipulators.myframe(b,20) graphics.bitmaps.tocontext(b,50*65536,nil) }} % This is inefficient because textext processes twice, so a "todo". \startMPpage picture p ; p := textext("\MyImage{mill.png}") ; draw p ; draw (boundingbox p) enlarged -.5mm withpen pensquare scaled 1mm withcolor "darkred" withtransparency (1,.5) ; \stopMPpage \stoptext