Pixel coloring problem

It’s like 20 lines of code to implement the memory bitmap and see it works as expected, also it’s for sure multiple orders of magnitudes more efficient (not only in code executed on average but also wrt to resources used) and it’s also much much simpler code than to try to manually optimize/handle offscreen pixels etc.

And no, memory bitmap does not create rectangles - all it does is, it makes the bitmap used for a texture available for modifications and update/reupload/reswizzle on demand (by the invalidate method) it’s contents as required for the GPU.

Below’s a simple sample with 250.000 pixels, drawing 500 random pixels during touches which runs pretty smooth on my 4 year old 50€ Android tablet.

Now if you want to change 5000 pixels smoothly each frame it’s going to be slow on lowspec devices using Corona as it’s not a natively compiled language - a memory bitmap will still be the only valid/best available choice (besides creating a native c++ extension).

[lua]


– main.lua


local memoryBitmap = require( “plugin.memoryBitmap” )

local tex = memoryBitmap.newTexture(

    {

        width = 500,

        height = 500,

        – format = “rgba”  – (default)

        – format = “rgb”

        – format = “mask”

    })

– Create image using the bitmap texture

local bitmap = display.newImageRect( tex.filename, tex.baseDir, 500, 500 )

bitmap.x = display.contentCenterX

bitmap.y = display.contentCenterY

– place some random pixels

for i = 1, 1000 do

    tex:setPixel( math.random(0, 1000), math.random(0,1000), 1, 0, 0, 1 )  – Set pixel at (10,10) to be red

end

– Submit texture to be updated

tex:invalidate()

local r, g, b = 1, 1, 1

function touchHandler( event )

    if event.phase == “began” then

        r, g, b = math.random(), math.random(), math.random()

    end

    local bmp = event.target

    local x, y = bmp:contentToLocal( event.x, event.y )

    x = (x + bmp.width/2)

    y = (y + bmp.height/2)

    for i = 1, 500 do

        local xx, yy = math.random(x-50, x+50), math.random(y-50, y+50)

        tex:setPixel( xx, yy, r, g, b, 1 )

    end

    tex:invalidate()

end

bitmap:addEventListener( “touch”, touchHandler )

[/lua]

True, it is simpler code than handling ‘offscreen’ pixels, but really even then it’s not really very complex, and something you should easily be able to code in an evening or two (or a full day).

Sure, but if there’s a better solution available that takes 5 minutes …

I’ve spent more time writing the postings in this thread than to implement it using the mechanism that’s made to solve these kinds of problems.

I undertand initially memory bitmap were an unknown and so display objects are a valid workaround but once you know better, there’s no reason to justify or even think about a worse solution.

You wouldn’t drive a 10 mile detour on a track across the fields once you know there’s a 1 mile route on a motorway with no traffic issues if you goal is to reach a target rather than waste time and resources and kill the springs of your car :slight_smile:

Hi Michael,

Sure thing, agreed on all points. I just wanted to let the OP know that even though the MemoryBitmap method is relatively much simpler, in absolute terms we’re not talking about a huge time investment for the ‘difficult’ method either.

This is important to know, because there could be very valid reasons to choose for the ‘difficult’ method. What if you want to use tiny rounded rectangles for your pixels, for example? Or add another style effect like a light glow in the center? Or maybe a cute transition where the pixels slide, rotate or zoom into place? Or overlapping squares, with some blendMode on them? All either impossible or very difficult with the memoryBitmap function, and a piece of cake with the ‘difficult’ method.

So in my book, it’s not about justifying a worse solution. And thinking about the possibilities for all the cool effects I described above definitely justifies thinking about different approaches.

Sure … well … YAGNI.

Also not solving the original stated problem (90k modifiable pixels, not slowing down the machine to a crawl or be forced to zoom in so far you only see a small part of the image).

Wow, you really seem to have a hard time dealing with the fact that people present alternate methods - each with their own benefits and drawbacks.

Personally, I think it’s best if people have informed options, and then decide for themselves wether or not they need certain functionality or not.

Another solution would be to use a canvas texture and draw to that.  You can workout which “pixel” was tapped, redraw that area and invalidate the canvas.

This way only a single texture is actually being drawn by GPU.  So performance should be very fast.

This app would be easy to do with Corona - but there are already hundreds of similar apps already.

You can pixelate an image to say 50x50 and have 2,500 rects that you simply fill with a colour.

I have to correct you right there. Creating 90,000 rects is nothing.

For example,

local newRect = display.newRect local pixel = {} local pixelSize = 2 local startX, startY = 20, 20 for i = 1, 300 do for j = 1, 300 do pixel[#pixel+1] = newRect( startX+i\*pixelSize, startY+j\*pixelSize, pixelSize, pixelSize ) pixel[#pixel]:setFillColor(1) end end

Adding zoom or something else on top of that isn’t that hard either.
 

90000 squares on the screen at the same time plant FPS to 8-10. This is very bad. To move such a group with pixels is impossible, terribly slow.

I want all these squares to move left and right, as they will be scaled, and not all of them will be visible on the screen.

in this case the detailing will suffer. 50x50 image is processed by the engine normally. but 300x300 gives FPS drawdown to 8-10.

Hardware is fast these days but you really don’t want to replace each pixel on a bitmap/texture with a full display object :slight_smile:

This is what you need/want

https://marketplace.coronalabs.com/corona-plugins/memory-bitmap

https://docs.coronalabs.com/plugin/memoryBitmap/index.html

Hi,

You only need to create the amount of rectangles that are visible on the screen, much like a tiled game.

When you slide your image to the left, the column of pixels / rectangles that falls outside of the screen area is moved to the right side off the screen and updated to the right colors for these pixels (by reading the color values from an array that holds all pixel colors).

Same for the other screen bounds.

By the way, replacing each pixel with a full display object is okay, as long as you keep the number of pixels visible on the screen under 2000, tested on a 3 year old iPhone SE and 5 year old iPad.

At the moment, these are the plugins that I use. Alas, despite the good harware, the engine can not cope with a large number of objects on the screen. For example, the Corona SDK cannot cope with drawing 3,500 objects, even if these objects are bitmaps. It will slow down and sink the FPS from each player’s action.

Thank you very much. Apparently this is the only working option.

https://marketplace.coronalabs.com/corona-plugins/memory-bitmap

This plugin creates squares and passes them by pixels, so it does not solve the performance problem in any way.

First of all: wow! I didn’t know Corona has gotten getPixel/setPixel functionality! When did this happen??? :slight_smile:

Second: but then the problem is solved, no? If you use this plugin then you only display one single bitmap with 90000 pixels, and not 90000 image with a single color each.

Are you 100% sure about that? Because from what see and read in the docs, it behaves the other getPixel/setPixel methods I’ve used in other software for the past 20 years - designed specifically to not create displayObjects but instead paint pixels in an existing texture.

You create 1 memory bitmap based display object of the required dimensions and then just set/modify the pixels you want to change.