Making a more compact/pixelated 2D array

I’m trying to figure out how to turn an array like this:
Bigger

Into an array like this:
Simplified

I basically want it to become more pixelated. Can someone please explain to me how I would do something like this?

1 Like

To compact an array into a smaller one in Lua, you can use a loop or the table.pack function to create a new array that only includes non-empty or non-nil elements.

local originalArray = {1, 2, 3, "", nil, 5}
local compactArray = {}

for i, element in ipairs(originalArray) do
  if element then
    compactArray[#compactArray + 1] = element
  end
end

print(unpack(compactArray))  -- Output: 1    2    3    5
--Here is an example with a loop

However, you can also use the table.pack() function, which would look like this

local originalArray = {1, 2, 3, "", nil, 5}
local compactArray = table.pack(unpack(originalArray, 1, #originalArray))

print(unpack(compactArray))  -- Output: 1    2    3    5

In both examples, the compactArray variable will contain a new array with only the non-empty or non-nil elements from the originalArray.

Btw, no idea is roblox is past LUA 5.2, if it is then this would work.

Since you’re scaling down by an integer (2 in this case), it’s fairly simple. Each sample in the scaled down version is made from the corresponding 2x2 square of samples in the original. There’s a few ways you can turn a 2x2 square into a single value, e.g. taking the average, min or max. It looks like you want the max, so any 2x2 square with at least one 1 turns into a 1 in the scaled down version.

Hmm, I ended up some code that does what you asked, here it is:

function image_dimensions(image)
    --Personally I'd set image.w and image.h in image_new instead of counting every time
    return #image[1], #image
end

function image_get(image, x, y)
    local w, h = image_dimensions(image)
    if x <= w and y <= h then
        return image[y][x], true
    end
    return nil, false
end

function image_set(image, x, y, value)
    local w, h = image_dimensions(image)
    if x <= w and y <= h then
        image[y][x] = value
        return true
    end
    return false
end

function image_new(w, h, default)
    local image = table.create(h)
    --image.w=w; image.h=h; -- How I'd do it, see image_dimensions
    for y = 1, h do
        image[y] = table.create(w, default)
    end
    return image
end

function image_iter(image)
    local w, h = image_dimensions(image)
    local y, x = 1, 0
    return function()
        x = x + 1
        if x > w then
            y = y + 1
            x = 1
        end
        if x <= w and y <= h then
            return x, y
        end
    end
end

function image_max(image)
    local result
    for ix, iy in image_iter(image) do
        local sample = image_get(image, ix, iy)
        if sample then
        if result then
            result = math.max(result, sample)
        else
            result = sample
        end
    end
    end
    return result
end

function image_scale_down(image, factor, f_kernel_to_sample)
    local wo, ho = image_dimensions(image) --Old dimensions
    local wn, hn = math.ceil(wo/factor), math.ceil(ho/factor) --New dimensions
    local result = image_new(wn, hn, -1) -- -1 indicates invalid value
    
    local kernel = image_new(factor, factor, -1) -- -1 indicates invalid value
    --Foreach sample in new, scaled down image
    for xn, yn in image_iter(result) do
        --Upper left corner of (factor*factor)- square of samples in old image
        local yo = ((yn - 1) * factor) + 1
        local xo = ((xn - 1) * factor) + 1
        
        --Foreach sample in said square of samples in old image
        --print("XN", xn, "YN", yn)
        for xk, yk in image_iter(kernel) do
            --Store image sample in the kernel, to be processed 
            local yi, xi = yo+yk-1, xo+xk-1
            local sample, in_bounds = image_get(image, xi, yi)
            if not in_bounds then sample = nil end
            image_set(kernel, yk, xk, sample)
            --print("S", sample, "xk,yk", xk, yk, "i", xi, yi)
        end
        
        image_set(result, xn, yn, f_kernel_to_sample(kernel))
    end

    return result
end

local some_image = { --7x4 
    {1, 1, 0, 0, 0, 0, 1},
    {1, 1, 0, 0, 0, 0, 1},
    {1, 1, 0, 0, 0, 0, 1},
    {1, 1, 0, 0, 0, 0, 1},
}

local scaled = image_scale_down(some_image, 2, image_max) --4x2
print(image_dimensions(scaled))
for x, y in image_iter(scaled) do
    local s = image_get(scaled, x, y)
    print(s)
end
2 Likes

This topic was automatically closed 14 days after the last reply. New replies are no longer allowed.