2
\$\begingroup\$

I'm learning Lua. I decided to make a simple plain PPM decoder/encoder without error checks to familiarize myself with the language. I would appreciate any feedback on how could I make the following code simpler, shorter, more elegant and readable.

-- Load/save plain PPMs without error checking; img[img.w][img.h].r=img.maxVal
-- sets the red channel of pixel at the top-right corner to the reddest value

local p3 = {}

function p3.load(path)
    local file = io.open(path)
    local data = file:read('a')
    file:close()
    data = data:gsub('#[^\n]*', ' ') -- remove comments
    local w, h, maxVal = data:match('P3'..('%s*(%d+)'):rep(3))
    w, h, maxVal = tonumber(w), tonumber(h), tonumber(maxVal)
    data = data:sub(#data:match('P3'..('%s*%d+'):rep(3)) + 1) -- remove header
    local img = { w = w, h = h, maxVal = maxVal }
    for x = 1, w do
        img[x] = {}
        for y = 1, h do
            img[x][y] = {}
        end
    end
    local channels = { 'r', 'g', 'b' }
    local startIndex, endIndex = 1, 1
    for y = h, 1, -1 do
        for x = 1, w do
            for _, ch in ipairs(channels) do
                startIndex, endIndex = data:find('%d+', startIndex)
                img[x][y][ch] = tonumber(data:sub(startIndex, endIndex))
                startIndex = endIndex + 1
            end
        end
    end
    return img
end

function p3.save(img, path)
    local file = io.open(path, 'w')
    file:write('P3\n', img.w, ' ', img.h, '\n', img.maxVal, '\n')
    for y = img.h, 1, -1 do
        for x = 1, img.w do
            file:write(img[x][y].r, ' ', img[x][y].g, ' ', img[x][y].b, '\n')
        end
    end
    file:close()
end

return p3
\$\endgroup\$
0
\$\begingroup\$

Seems readable enough for me. When you're working with a standardized data there is no room for ingenuity, just a mechanical work that needs to be done correctly.

Maybe it is only this snippet 'P3'..('%s*(%d+)'):rep(3), that makes you thin for a while, whether there will be three 'P3's in result.

\$\endgroup\$
  • \$\begingroup\$ You're right! 'P3%s*(%d+)%s*(%d+)%s*(%d+)' is clearer than 'P3'..('%s*(%d+)'):rep(3). I should also change 'P3'..('%s*%d+'):rep(3) to 'P3%s*%d+%s*%d+%s*%d+' for consistency. Thank you for your feedback! \$\endgroup\$ – Rusty Bludgeon May 14 '17 at 3:50

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.