Upscaling pixel art

Okay so this might be a little bit complicated to explain but I will try my best. I am making a pixel art game where everyone starts with a 128x128 canvas. The resolutions we’ll support are 16x16, 32x32, 64x64 and lastly 128x128. Now, instead of using multiple canvas at different resolutions such as having to delete the 128x128 canvas with 16k pixels to load a 64x64 with 4k pixels over and over again which is VERY performance consuming, instead what I’ll do is just upscale the resolution. So basically 1 pixel of 64x64 is equal to 4 pixels of 128x128 and this will be done in real time. So lets say the player clicked on the 1, 2 coordinate of the 128x128 drawing. The pixel board will convert this 128x128 coordinate to a 64x64 coordinate. 1, 2 of 128x128 = 1, 1 in 64x64. I made a function for this:

function calcres(res, pixels)
	local converted = {math.ceil(pixels[1]/128 * res), math.ceil(pixels[2]/128 * res)}
	return converted

print(unpack(calcres(64, {128, 127})))
--// 64, 64

Now what I am looking for is a function that can convert the coordinate of the smaller resolutions to a table of 128x128 pixels. So for example, the 1,1 coordinate of 64x64 should give me a table as such:
{1,1}, {1,2}, {2,1} {2,2} and then these pixels will be colored by my code and this should be equal to 1,1 in 64 just rendered in 128x128.

lets not confuse screenpixels (the amount of pixels on your screen) with canvaspixels (for what the drawing is for
the way i see this is that the canvaspixels dont change.
all the pixels in the bigger picture have a coordinate on the smaller picture
just the pixels itself become bigger

scaling down in pixels (like old windows paint would do it) they used an algorithm to remove sertain rows of pixels

(the image is someone doing manual rescaling on a photo)

1 Like

I don’t really get what you mean and that video got me a little bit confused. Basically the canvaspixels won’t change. They will be staying at 128x128 just when u start drawing imagine as if it will grid to 64x64. Now lets say the player wants to color a pixel in the canvas and his mouse hovers over the 128x127 pixel. This will be converted to the resolution he is painting at. Lets say he is painting 64x64 as it is the easiest example. The code will then convert this 128x127 to a 64x64 resolution which in this case is 64x64 pixel. Now, to “upscale” this to display on the 128x128 canvas, the 64x64 pixel will give a table correlating in 128x128 dimensions that have to be filled. It should return exactly 4 pixels as 1 pixel of 128x128 = 4 pixels of 64x64. The table should return the following:

{{127, 127}, {127, 128}, {128, 127}, {128, 128}}

Then these pixels will be colored and what we did here is the equivalent to painting 1 pixel on a 64x64 board. Hope this was clearer.


here is one I just made,
it’s quite simplistic, and might not be the best way as there’s a second degree loop (performance wise), but it seems to work correctly.

function ResUp(pixel)
  local coordinates = {}; 
  for x = pixel[1], pixel[1]+1 do
    for y = pixel[2], pixel[2]+1 do
      table.insert(coordinates, {x,y}); 
  return coordinates; 

I’m not 100% sure I’ve understood your request, so my answer might not be accurate but hopefully I helped a bit :slight_smile:

I believe this is right.

This function returns the corners of the rectangle you need to fill, inclusive.

local function UpRes(x, y, fromRes, toRes)
    local minX = toRes * (x-1) / fromRes + 1
    local maxX = toRes * x / fromRes
    local minY = toRes * (y-1) / fromRes + 1
    local maxY = toRes * y / fromRes

    return minX, minY, maxX, maxY

print(UpRes(1,1,32,128)) -- 1 1 4 4
print(UpRes(2,3,16,128)) -- 9 17 16 24
print(UpRes(63,64,64,128)) -- 125 127 126 128

Just have a nested loop with those numbers as your bounds if you want to iterate over the pixels:

local minX, minY, maxX, maxY = UpRes(…)

for x = minX, maxX do
  for y = minY, maxY do
    print("should fill pixel at", x, y)
1 Like

Thank you so much for your response, it appears to be working :slight_smile: