Help Debugging Screen Zoom Extension

I’ve made a simple extension that is supposed to zoom the screen. It works on 1x zoom, but for anything over that (or under that), it only does half the screen. I’d like somebody to help debug (preferably a member of the Makecode team, maybe @Richard) this code, becasue it seems that my math is right. I am trying to make it zoom into the center of the screen, so I calculate an offset, but when I do this, it only zooms half of the screen. If I make it calculate the offset to the right of the middle, it works, but it zooms into the right side of the screen. I think this may be a bug of Makecode.

Here's my code (IK it's a bit messy):

//% color="#f76820"
namespace Zoom {
//% block
//% block=“Zoom In Screen Image Using On Game Update By $size Times”
export function SetBlurFilter(size: number) {
let zLayer = 0
let savedx = 0
let buf = Buffer.create(120)
let precalc = [0]
let precalc2 = [0]
precalc = []
precalc2 = []
let variable = scene.createRenderable(zLayer, (image: Image, camera: scene.Camera) => {
for (let index = 0; index < 160; index++) {
precalc2.push(Math.ceil(index / size + (159 - 159 / size) / 2))
}
for (let index3 = 0; index3 < 120; index3++) {
precalc.push(Math.ceil(index3 / size + (119 - 119 / size) / 2))
}
for (let index5 = 0; index5 < 160; index5++) {
for (let index6 = 0; index6 < 120; index6++) {
buf[index6] = image.getPixel(precalc2[index5], precalc[index6])
}
image.setRows(index5, buf)
}
}
)
control.runInParallel(() => variable.destroy())
}
}

You can also download it with importing the url (kiwiphoenix364/pxt-zoom)
What the code does is it takes a bunch of x and y variables into the “precalc” and “precalc 2” variables (the ones that the new screen gets the color for). It makes a renderable then gets the colors for every pixel from the positions in the array. It draws the rows, then it destroys the renderable, ready for the next frame.
I appriciate any help!

The issue here is that you are trying to read and write to the same image at the same time. Eventually, your going to start reading the pixels that you just wrote. to fix it, you need to make a clone of the screen before you start overwriting it.

I’m not 100% sure I understand your precalc code either. One easier way to think about this is to first calculate the zoom rectangle:

const zoomWidth = Math.ceil(screen.width / size);
const zoomHeight = Math.ceil(screen.height / size);

const zoomLeft = Math.floor((screen.width / 2) - (zoomWidth / 2));
const zoomTop = Math.floor((screen.height / 2) - (zoomHeight / 2));

Once you have that, you can just map the current pixel to be the pixel in that rectangle:

            for (let x = 0; x < screen.width; x++) {
                for (let y = 0; y < screen.height; y++) {
                    screen.setPixel(x, y, screenClone.getPixel(Math.floor(zoomLeft + x / size), Math.floor(zoomTop + y / size)))
                }
            }

The precalc code gets the positions for all of the pixels, so all it has to do is pull from the array, with absolutely NO calculations needed for each pixel, as that makes it only have to calculate positions 160 + 120 (280) times instead of 160 x 120 (19,200) times. - But you DID give me an idea, I could calculate the top and left BEFORE the precalc runs, so I wouldn’t be calculating the top and left 280 times, only once! That optimizes it even more.

Thanks for the help @richard Richard, I forgot that I was reading pixels that I was just writing lol.

I’ve released the extension in kiwiphoenix364/pxt-zoom!

Cool. Can you make it possible to zoom out too?