Jump to content

[TOPIC: topicViewTemplate]
[GLOBAL: userSmallPhoto]
Photo

Pixel coloring problem
Started by bus_ter2011 Jun 18 2019 02:10 PM

26 replies to this topic
optimization coloring pixel
[TOPIC CONTROLS]
Page 1 of 2 1 2
[/TOPIC CONTROLS]
[modOptionsDropdown]
[/modOptionsDropdown]
[reputationFilter]
[TOPIC: post.html]
#1

bus_ter2011

[GLOBAL: userInfoPane.html]
bus_ter2011
  • Observer

  • 10 posts
  • Corona SDK

Hi, guys! I want to develop my pixel coloring on the Corona SDK.

 

I want to do something similar - https://play.google.com/store/apps/details?id=com.appcraft.unicorn

 

As pixels I think to use squares, when clicked, they will change color.

 

I need to use relatively large images, for example 300x300 pixels. I will have to create 90,000 squares, with which the engine will not cope.

 

In the future, I want to make a zoom for my image, consisting of pixels (squares).

 

Since the engine can not cope with so many squares on the screen, advise the best solution. I came up with just such an idea. Thank you in advance.

 

P.S. For example, i can enlarge the squares and draw only 50 squares on the screen. But then I lose the possibility of zoom with a pinch.



[TOPIC: post.html]
#2

SGS

[GLOBAL: userInfoPane.html]
SGS
  • Corona Geek

  • 2,106 posts
  • Corona SDK

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.



[TOPIC: post.html]
#3

XeduR @Spyric

[GLOBAL: userInfoPane.html]
XeduR @Spyric
  • Contributor

  • 762 posts
  • Corona SDK

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.
 



[TOPIC: post.html]
#4

bus_ter2011

[GLOBAL: userInfoPane.html]
bus_ter2011
  • Observer

  • 10 posts
  • Corona SDK

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.



[TOPIC: post.html]
#5

bus_ter2011

[GLOBAL: userInfoPane.html]
bus_ter2011
  • Observer

  • 10 posts
  • Corona SDK

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.

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



[TOPIC: post.html]
#6

Michael Flad

[GLOBAL: userInfoPane.html]
Michael Flad
  • Contributor

  • 231 posts
  • Corona SDK

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

 

This is what you need/want

 

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

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



[TOPIC: post.html]
#7

thomas6

[GLOBAL: userInfoPane.html]
thomas6
  • Contributor

  • 975 posts
  • Corona SDK

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.



[TOPIC: post.html]
#8

thomas6

[GLOBAL: userInfoPane.html]
thomas6
  • Contributor

  • 975 posts
  • Corona SDK

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.


  • bus_ter2011 likes this

[TOPIC: post.html]
#9

bus_ter2011

[GLOBAL: userInfoPane.html]
bus_ter2011
  • Observer

  • 10 posts
  • Corona SDK

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

 

This is what you need/want

 

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

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

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.


  • bus_ter2011 likes this

[TOPIC: post.html]
#10

bus_ter2011

[GLOBAL: userInfoPane.html]
bus_ter2011
  • Observer

  • 10 posts
  • Corona SDK

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.

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


  • bus_ter2011 likes this

[TOPIC: post.html]
#11

bus_ter2011

[GLOBAL: userInfoPane.html]
bus_ter2011
  • Observer

  • 10 posts
  • Corona SDK

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.


  • bus_ter2011 likes this

[TOPIC: post.html]
#12

thomas6

[GLOBAL: userInfoPane.html]
thomas6
  • Contributor

  • 975 posts
  • Corona SDK

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

 

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.


  • bus_ter2011 likes this

[TOPIC: post.html]
#13

thomas6

[GLOBAL: userInfoPane.html]
thomas6
  • Contributor

  • 975 posts
  • Corona SDK

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.

 

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.


  • bus_ter2011 likes this

[TOPIC: post.html]
#14

Michael Flad

[GLOBAL: userInfoPane.html]
Michael Flad
  • Contributor

  • 231 posts
  • Corona SDK

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.

 

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


  • bus_ter2011 likes this

[TOPIC: post.html]
#15

thomas6

[GLOBAL: userInfoPane.html]
thomas6
  • Contributor

  • 975 posts
  • Corona SDK

Yep, that's what I thought. That should be blazingly fast - unless the afterlying code is extremely poorly programmed.


  • bus_ter2011 likes this

[TOPIC: post.html]
#16

roaminggamer

[GLOBAL: userInfoPane.html]
roaminggamer
  • Corona Geek

  • 7,585 posts
  • Corona SDK

Quick chime in.  You can absolutely make an app like that with Corona and it will run fine.

 

Those apps very likely do not render off-screen selectable/paintable blocks.  Your game should not either.  Once you cull off-screen content there will be no issue with performance.

 

I think the real question here is, "What techniques should be applied to implement this?"  I'm seeing good responses above that all seem on track.

 

Best of luck on this.  Be sure to share in-progress  updates with us.

 

Also, if you get stuck, the best way to get help is to make a demo that shows the issue you're encountering, zip it up, and share it here.  Folks will be more included to run and examine it that dig into partial code posts or just provide their own example.  i.e. It is nicer to look at and help with existing samples as long as they are small and focused.


Edited by roaminggamer, 19 June 2019 - 05:39 PM.

  • bus_ter2011 likes this

[TOPIC: post.html]
#17

bus_ter2011

[GLOBAL: userInfoPane.html]
bus_ter2011
  • Observer

  • 10 posts
  • Corona SDK

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

 

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.

Memory Bitmap plugin does not solve the problem. Because if you make setPixel 5000 times for example, then performance will drop. Similar loss of FPS with 5000 squares on the screen and using setPixel.


  • bus_ter2011 likes this

[TOPIC: post.html]
#18

bus_ter2011

[GLOBAL: userInfoPane.html]
bus_ter2011
  • Observer

  • 10 posts
  • Corona SDK

Thank you all for the answers! The best option is to draw one picture in parts, 1500 squares on the screen.
 
The Memory Bitmap plugin will most likely work in the same way, using the principle of creating squares. Because of this, performance drops. So the setPixel method is not justified.


[TOPIC: post.html]
#19

thomas6

[GLOBAL: userInfoPane.html]
thomas6
  • Contributor

  • 975 posts
  • Corona SDK

Hi Buster,

 

Ah, it's a shame that the setPixel function is too slow then.

 

In that case I would go for only drawing the visible on-screen pixels and my wrap-around idea mentioned above. Let me know if you have any problems with that.



[TOPIC: post.html]
#20

Yoger Games

[GLOBAL: userInfoPane.html]
Yoger Games
  • Contributor

  • 109 posts
  • Corona SDK

We are doing a similar app (still a prototype). We create squares to represent the pixels and so far performance seems to be ok.

 

Short simple video
https://www.youtube.com/watch?v=3cwvQD6UmhM

 

The app also has zooming etc. but not visible in the video (recorded on simulator). 



[TOPIC: post.html]
#21

Michael Flad

[GLOBAL: userInfoPane.html]
Michael Flad
  • Contributor

  • 231 posts
  • Corona SDK

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).

 

-----------------------------------------------------------------------------------------
--
-- 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 )



[TOPIC: post.html]
#22

thomas6

[GLOBAL: userInfoPane.html]
thomas6
  • Contributor

  • 975 posts
  • Corona SDK

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).



[TOPIC: post.html]
#23

Michael Flad

[GLOBAL: userInfoPane.html]
Michael Flad
  • Contributor

  • 231 posts
  • Corona SDK

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 :)


  • SGS likes this

[TOPIC: post.html]
#24

thomas6

[GLOBAL: userInfoPane.html]
thomas6
  • Contributor

  • 975 posts
  • Corona SDK

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.



[TOPIC: post.html]
#25

Michael Flad

[GLOBAL: userInfoPane.html]
Michael Flad
  • Contributor

  • 231 posts
  • Corona SDK

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).



[topic_controls]
Page 1 of 2 1 2
 
[/topic_controls]

Also tagged with one or more of these keywords: optimization, coloring, pixel