summaryrefslogtreecommitdiff
path: root/img/load_pnm.lua
diff options
context:
space:
mode:
authorubq323 <ubq323@ubq323.website>2022-08-04 22:23:48 +0100
committerubq323 <ubq323@ubq323.website>2022-08-04 22:23:48 +0100
commit80f58af6970bc8ed7079de2d6c1f6d66bb139332 (patch)
treee5b2ea44c367dcfc3061e717d72d9a31911ab898 /img/load_pnm.lua
parent96959afaa17c48741fd76bfb8188c4f3f395d774 (diff)
load_pnm
Diffstat (limited to 'img/load_pnm.lua')
-rw-r--r--img/load_pnm.lua127
1 files changed, 107 insertions, 20 deletions
diff --git a/img/load_pnm.lua b/img/load_pnm.lua
index 60cac8a..1cd228c 100644
--- a/img/load_pnm.lua
+++ b/img/load_pnm.lua
@@ -1,34 +1,121 @@
-local perr = require("util").perr
+-- only going to support binary ones
+-- because the textual ones are annoying
-local function load_p1(fname)
+-- types:
+-- P1 ascii pbm
+-- P2 ascii pgm
+-- P3 ascii ppm
+-- P4 binary pbm
+-- P5 binary pgm
+-- P6 binary ppm
- local file,err = fs.open(fname,"r")
- perr(err,"fs.open")
- local imgf = file.readAll()
- --print(img)
- assert(imgf:sub(1,2) == "P1","only P1 images are supported at the moment")
- local width,height, cur = imgf:match("%s*(%d+)%s*(%d+)%s*()",3)
- assert(width,"couldn't find image header")
- local img=setmetatable({},{__index=function(t,k)
+-- function nextpixel(imgf,cur,depth) -> pixel, ncur
+-- where pixel is {r,g,b}, with r,g,b in [0,1]
+
+local function np_p1(imgf,cur,depth)
+ local val,ncur = imgf:match("[01]%s*()",cur)
+ val = tonumber(val)
+ assert(val,"bad image format at "..cur)
+ local p = (1-v) -- 1 is black (0), 0 is white (1)
+ local pixel = {p,p,p}
+ return pixel,ncur
+end
+local function np_p2(imgf,cur,depth)
+ local val,ncur = imgf:match("(%d+)%s+()",cur)
+ val = tonumber(val)
+ assert(val,"bad image format at "..cur)
+ assert(0<=val and val<=depth, "image value out of range at "..cur)
+ local p = val/depth
+ local pixel = {p,p,p}
+ return pixel,ncur
+end
+local function np_p3(imgf,cur,depth)
+ local tr,tg,tb,ncur = imgf:match("(%d+)%s+(%d+)%s+(%d+)%s+()",cur)
+ local vr,vg,vb = tonumber(tr),tonumber(tg),tonumber(tb)
+ assert(vr,"bad image format at "..cur)
+ for _,v in ipairs{vr,vg,vb} do
+ assert(0<=v and v<=depth,"image value out of range at "..cur)
+ end
+ local pr,pg,pb = vr/depth,vg/depth,vb/depth
+ local pixel = {pr,pg,pb}
+ return pixel,ncur
+end
+-- i will figure this one out later
+local function np_p4() error("p4 isn't supported yet") end
+local function np_p5(imgf,cur,depth)
+ local val = imgf:byte(cur)
+ assert(val<=depth,"image value out of range at "..cur)
+ local p = val/depth
+ local pixel = {p,p,p}
+ return pixel,cur+1
+end
+local function np_p6(imgf,cur,depth)
+ local vr,vg,vb = img:byte(cur,cur+3)
+ for _,v in ipairs{vr,vg,vb} do
+ assert(0<=v and v<=depth, "image value out of range at "..cur)
+ end
+ local pr,pg,pb = vr/depth,vg/depth,vb/depth
+ local pixel = {pr,pg,pb}
+ return pixel,cur+3
+end
+
+local nextpixel_fns = {
+ [1]=np_p1,
+ [2]=np_p2,
+ [3]=np_p3,
+ [4]=np_p4,
+ [5]=np_p5,
+ [6]=np_p6,
+}
+
+
+local function parse(imgf)
+ assert(imgf:sub(1,1) == "P","invalid header")
+ local typech = tonumber(imgf:sub(2,2))
+ assert(typech and 1<=typech and typech<=6,"invalid header type")
+
+ local has_depth = not(typech == 1 or typech == 4)
+
+ local width,height,cur = imgf:match("%s*(%d+)%s*(%d+)%s*()",3)
+ assert(width,"couldn't find image dimensions")
+
+ -- by 'depth' i mean 'maximum value'
+ local depth = 1
+ if has_depth then
+ local ndepth,ncur = imgf:match("(%d+)%s*()")
+ assert(ndepth,"couldn't find image depth (max pixel value), in a format that needs it")
+ depth=ndepth
+ cur=ncur
+ end
+ assert(depth<=255,"depth too high (shouldn't be above 255)")
+
+ -- img[y][x]; 1,1 is top left
+ local img = setmetatable({},{__index=function(t,k)
if type(k) ~= "number" then return nil end
local r = {}
rawset(t,k,r)
return r
end})
- -- img[y][x]. 1,1 is top left
- for row=1,height do
- for col =1,width do
- local val,ncur = imgf:match("(%d+)%s*()",cur)
- cur = ncur
- img[row][col] = tonumber(val)
+ local x,y=1,1
+ local nextpixel = nextpixel_fns[typech]
+
+ while cur <= #imgf do
+ local npixel,ncur = nextpixel(imgf,cur,depth)
+ img[y][x] = npixel
+ cur = ncur
+ if y > width then
+ y = 1
+ x = x + 1
+ end
+ if x > height then
+ break
end
end
-
- img.width=width
- img.height=height
+
+ img.width = width
+ img.height = height
return img
end
-return load_p1