Howdy, Stranger!

It looks like you're new here. If you want to get involved, click one of these buttons!

image:copy, image:set, and setContext weirdness?

First off, I think the doc for image:copy is wrong. It says the x and y params are top left corner of the copy area. It’s in fact the bottom left. Or maybe it’s affected by xxxxMode()?

Second, there’s something funky here. Maybe it’s something I shouldn’t do and I don’t know about it.

setContext(img)
... -- call to several draw operations
copiedArea = img:copy(...)
sprite(copiedArea, ...)
... -- more drawing calls
setContext()

The img above is displayed correctly with the changes in all draw loop. But then as soon as I do img:set(...), right after that (e.g as part of reacting to touch), whatever changes I had made in the code above to img is strangely reverted like nothing had happened.

What did I not know about these combination of calls?

Comments

  • dave1707dave1707 Mod
    Posts: 7,553

    @tsukit I’m not sure the img:copy inside the setContext pair will work. I don’t think img is complete until the closing setContext.

  • dave1707dave1707 Mod
    Posts: 7,553

    @tsukit Can you give a brief description of what you’re trying to do. Maybe I can give you an example based on that. From what you show above, I’m not sure what’s going on.

  • SimeonSimeon Admin Mod
    Posts: 4,928

    @tsukit I don't think you can use raw pixel access during a setContext call on the image you are rendering to. Because when the image is put up in setContext it is used as an OpenGL buffer, in order to access the raw pixel data that buffer has to be flushed from the GPU memory copied back into main memory.

    The closest you could get would be to save the image from the previous frame and access that when needed for the current frame's image.

  • Posts: 19

    Thanks @Simeon and @dave1707. I think at this point I want to understand how it happens, not as much what caused it. Here’s a sample code that demonstrates the problem. After the first touch, you see the copied area shows up correctly. But then after the second touch, the copied area is gone

    function setup()
        fill(255,0,0)
        img = image(100,100)
        setContext(img)
        background(255, 255, 255, 255)
        ellipse(50,50,50)
        setContext()
        step = 0
    end
    
    function touched(touch)
        if touch.state == BEGAN then
            if step == 0 then
                setContext(img) -- if i move this line to after img:copy below, then no problem
                local copiedArea = img:copy(0, 0, 50, 50)
                spriteMode(CORNER)
                sprite(copiedArea, 0, 50)
                setContext()
                step = 1
            else
                img:set(1, 1, 0, 0, 0) -- this cause the content of the image to revert
            end
        end
    end
    
    function draw()
        background(40, 40, 50)
    
        noSmooth()
        spriteMode(CENTER)
        sprite(img, WIDTH/2, HEIGHT/2, HEIGHT/2, HEIGHT/2)
    end
    
  • dave1707dave1707 Mod
    Posts: 7,553

    @tsukit I think there’s a difference between the img that was originally created in setup() and the img used with setContext(img). If you put setContext(img) and setContext() around the img:set code and change the 1's in img:set to 10 so the black square shows farther into the image, then you’ll see the black square along with the correct image. But when using img:set without setContext, then I think its reverting to the original img created in setup. I’m still trying to figure out a way to prove this.

  • Posts: 19

    Thanks @dave1707 . If they are indeed different img, that would be very interesting.

  • dave1707dave1707 Mod
    Posts: 7,553

    @tsukit I don’t think they’re different in a way that you can use one or the other. In you’re code above, doing an img:set with and without the setContext statements around it showed different images. So depending on how img is used was giving a different result.

  • JohnJohn Admin Mod
    Posts: 572

    Just to be clear. Anything to do with manually copying or setting pixels within a setContext() call is undefined.

    We maintain a local copy of an image as an array of bytes, at certain points data is copied into and out of the GPU when required (like after setContext is used, or after set is used). Trying to access those bytes while also drawing to the image means that those two things are not in sync and so changes may be overwritten, ignored or discarded.

  • dave1707dave1707 Mod
    edited March 1 Posts: 7,553

    @John Thanks for the explanation. I think that’s what I was trying to explain but I wasn’t sure how things were working within the setContext pair.

  • Posts: 19

    @dave1707 and @John thanks for the explanation. I think that's something important to add into the reference doc so everyone is aware of it -- in addition to the correction on the description of x, y params of image:copy() as I mentioned in the original post.

Sign In or Register to comment.