Microsoft MakeCode

Help with block field editors - large image grid picker?

Can anyone please help me work out how to define a function withinmy custom extension whic can replicate for me the LED image creator functionsuch as the images.createBigImage()? In Makecode blocks for the Microbit, this function appears as a grid of tick-boxes for the pixels in an image. This is twice the width of the standard 5x5 image as in images.createImag().

I want to reproduce this for a larger image or indeed for images of various sizes (for displaying on larger LED matrix displays) but I can’t work out the appropriate annotations and functions for the field editor. Has anyone got some in-depth knowledge here?

Michael

This is only supported in beta (https://makecode.microbit.com/beta). Use imageLiteralColumns and imageLiteralRows.

For legacy reasons, the parameter should be a string; but it is really an Image runtime object.

    /**
     * TODO: describe your function here
     */
    //% block="foo"
    //% imageLiteral=1
    //% imageLiteralColumns=12
    //% imageLiteralRows=3
    export function foo(i: string): void {
        // this is not pretty but basically, i is an Image
        let im = <Image><any>i;
        im.showImage(0)
    }

Open this in beta: https://makecode.microbit.org/beta#pub:_Fm582taEK8Ww

Thank you for helping but unfortunately that doesn’t seem to achieve what I want. The MakeCode block for “foo” appears to be constrained only to a multiple of a standard image, in other words always 5 rows and any multiple of 5 columns depending on the value of “imageLiterals” but irrespective of the “imageLiteralRows” or columns.

What I want to do is to work out how the image editor works in Blocks and create one that lets me input an image of say 17,7 pixels- for use with a particular LED matrix display that is can be attached to a Microbit - and returned as an image/string which can be assigned to a variable and then at some point delivered to an LED matrix display.

I tried looking through lots of the core code for the Microbit platform but couldn’t work out where the definition was for the block (the “grid picker” type element) was defined such that I could alter it for a custom size.

Do you need colors as well?

No, I just need something dead simple. On/Off for an array of 17x7 pixels. It would be nice to have a Block for it so I want an editor which is like the standard image.createImage() editor. But possibly a smaller rendition as 17x7 would take up a lot of space in the Makecode editor screen.

However, in relation to the extension for the Scroll:bit I’m using, there’s also the possibility that a simple monochrome pixel editor for a larger array would be useful to apply to the larger windowing system I’m trying to make for it. In which it would be of any size the user requested.

In the other thread you mentioned the Arcade pixel editor? I haven’t looked at any of that yet but I can see a whole forum category for it. Is there an editor I could adapt and simplify?

Indeed row is ignored, i’ll look into that.

Demo that does not work yet:

Ah, thanks.But that does work if you do the following:

//% block=“make image”
//% blockId=myscrollbit_make_image
//% imageLiteral=1
//% imageLiteralColumns=17
//% imageLiteralRows=7
export function makeImage(i: string): Image {
// this is not pretty but basically, i is an Image
let im = i;
console.logValue(“width”, im.width())
console.logValue(“height”, im.height())
im.scrollImage(1, 200)
return im
}

although I’d really like to know how to rebuild this in a different design and make the pixels more compact in the editor.

However, it works only in the beta makecode editor. Any idea why?

This PR needs to go in. https://github.com/microsoft/pxt-microbit/pull/2879

Also you need to set the shim on this function:

//% shim=images::createImage

Tested on browser/hw:

Ah, thank you very much. I have got the code successfully creating an image into a variable and then displaying it on the 17x7 display, so that’s brilliant.

I don’t quite understand all the ins and outs of shims yet. Here it maps the function “foo” to the creatImage() C++ function, yes? Why is im declared as a const here?

I see you’ve requested a pull on this and I’m looking at your comments. I’m pretty new to github so I’m still learning how everything fits together. Maybe following a trail from the code referred to in your PR will help me understand how the createImage() pixel editor is constructed. I’d happily copy the entire construction and play with it to see if I can edit its appearance for using with larger images if I can find all of the relevant code.

I also had a look at the sprite editor for Arcade. Very impressive and useful. However, there’s no way I can work out how to extract the editor from the rest of Arcade and make a dead simple monochrome version of it to create a pixel image of any give size. It would be handy, though.

The fix is now in the latest beta (v2.3.21 and up).

Here it maps the function “foo” to the creatImage() C++ function, yes?

The “shim” notation is telling our linker to use the C++ imagers::createImage function for C++ instead of the TypeScript. Docs at https://makecode.com/simshim

Why is im declared as a const here?

That’s just a typescript habit. It makes the variable reference readonly – eg you cannot assign into that variable again. It could have been let. as well.

The “image” feature in micro:bit is kind of a legacy feature - which explains why it’s using a string and not a string literal like in Arcade.

If you’re working on an extension, feel free to post it here on the forums so that we can give you feedback.

I certainly will do. In what form can it be posted on the forum?

Err, but if the Microbit pxt has just been updated after your PR, does that explain why my function below suddenly shows an error in the MakeCode editor? It is complaining about the if (im.pixel(x,y)==1) statement! it worked an hour or so ago. I’ve just changed it to if (im.pixel(x,y)) as a boolean, and now it works.

export function displayImage(im: Image): void {
        for(let y = 0; y < im.height(); ++y) {
            for(let x = 0; x < im.width(); ++x) {
                if (im.pixel(x, y) == 1) {
                    setPixel(x,y)
                }
            }
        }
    }

Let me investigate what changed…

Looks like pixel was always returning a boolean; not sure why it worked for you previously.

A new thread for that extension for do it.

Hey! You appear to have done something that causes a crash when this is called:

basic.showIcon(Icon.Sad)

Oops!

Oh, or maybe not. It’s broken if I use the stable version not the beta. I think I’ve got a memory leak somewhere. I must be abusing a buffer somewhere in my code (it’s a worm chasing game on the scrollbit and it worked a few hours ago).