Fast set each pixel color on every frame

Put problem concerning Views, Layouts and other XML-Resources (like AndroidManifest) here.

Fast set each pixel color on every frame

Postby peaceoutside.org » Mon Nov 09, 2009 5:44 am

I'm currently trying to find the best way to update each pixel in a bitmap on every frame.

The following code is incredibly slow (like 1-2 fps):

Syntax: [ Download ] [ Hide ]
Using java Syntax Highlighting
  1.  
  2. public class Test extends Activity
  3.  
  4. {
  5.  
  6.  
  7.  
  8.         @Override
  9.  
  10.         public void onCreate(Bundle savedInstanceState)
  11.  
  12.         {
  13.  
  14.                 super.onCreate(savedInstanceState);
  15.  
  16.  
  17.  
  18.                 this.requestWindowFeature(Window.FEATURE_NO_TITLE);
  19.  
  20.  
  21.  
  22.                 Panel panel = new Panel(this);
  23.  
  24.                 this.setContentView(panel);
  25.  
  26.         }
  27.  
  28.  
  29.  
  30.         class Panel extends View
  31.  
  32.         {
  33.  
  34.  
  35.  
  36.                 private Bitmap bmp = null;
  37.  
  38.                 private Random r = new Random();
  39.  
  40.  
  41.  
  42.                 @Override
  43.  
  44.                 protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec)
  45.  
  46.                 {
  47.  
  48.                         super.onMeasure(widthMeasureSpec, heightMeasureSpec);
  49.  
  50.                         this.bmp = Bitmap.createBitmap(
  51.  
  52.                                 this.getMeasuredWidth(),
  53.  
  54.                                 this.getMeasuredHeight(),
  55.  
  56.                                 Config.ARGB_8888
  57.  
  58.                         );
  59.  
  60.                 }
  61.  
  62.  
  63.  
  64.                 @Override
  65.  
  66.                 public void onDraw(Canvas canvas)
  67.  
  68.                 {
  69.  
  70.                         super.onDraw(canvas);
  71.  
  72.                
  73.  
  74.                         for(int i = 0; i < this.bmp.getWidth(); ++i)
  75.  
  76.                         {
  77.  
  78.                                 for(int j = 0; j < this.bmp.getHeight(); ++j)
  79.  
  80.                                         this.bmp.setPixel(i, j, 0xFF000000 | this.r.nextInt(0xFFFFFF));
  81.  
  82.                         }
  83.  
  84.  
  85.  
  86.                         canvas.drawBitmap(this.bmp, 0, 0, null);
  87.  
  88.            
  89.  
  90.                         this.invalidate();
  91.  
  92.                 }
  93.  
  94.         }
  95.  
  96. }
  97.  
  98.  
Parsed in 0.035 seconds, using GeSHi 1.0.8.4


What's the proper way to do this?
peaceoutside.org
Freshman
Freshman
 
Posts: 3
Joined: Mon Nov 09, 2009 5:32 am
Location: Reno, NV

Top

Postby ExxKA » Mon Nov 09, 2009 12:34 pm

instead of asking for the measures of the canvas each time, you could save it in an instance variable.

You could also reuse parts of the canvas which has not changed. I don't know how much cutting / pasting / clipping support there on Android, but i have done a map application with java on a desktop, and doing buffering and saving states in instance variables I gained a lot of speed!
Student at the IT-University of Copenhagen
Visit my blog 1337h4x0r.com
ExxKA
Developer
Developer
 
Posts: 29
Joined: Tue Nov 03, 2009 7:16 pm
Location: Denmark

Postby Kyros » Mon Nov 09, 2009 1:59 pm

Probably doesn't help that its an inner class either, just a thought.
Kyros
Junior Developer
Junior Developer
 
Posts: 13
Joined: Wed Oct 21, 2009 11:49 am

Postby I_Artist » Mon Nov 09, 2009 3:58 pm

Hi,

I'm not sure about this one, but in other platforms it's not wise to call invallidate() from inside the draw() method. Are you sure this is what you want to do?

cheers!
The I_Artist

follow me on Twitter: @I_Artist
follow Android Development on Twitter: #androiddev

Show the world that you are an #androiddev, wear the badge http://www.twibbon.com/join/androiddev
User avatar
I_Artist
Developer
Developer
 
Posts: 33
Joined: Fri Oct 16, 2009 3:49 am
Location: St-Eustache, Quebec

Postby peaceoutside.org » Mon Nov 09, 2009 4:59 pm

I_Artist wrote:I'm not sure about this one, but in other platforms it's not wise to call invallidate() from inside the draw() method. Are you sure this is what you want to do?


No, not really sure if that's how it's supposed to be done. I've just started with the Android platform.

I'm still trying to figure out how to:
1. Put this in a different thread than the UI
2. Use a loop that's more efficient (doesn't seem like invalidate() in the onDraw() method is correct)
3. Find the fastest way to use setPixel() or equivalent to get hopefully at least 30fps on a 256x160 bitmap
peaceoutside.org
Freshman
Freshman
 
Posts: 3
Joined: Mon Nov 09, 2009 5:32 am
Location: Reno, NV

Postby Kyros » Mon Nov 09, 2009 5:44 pm

you really have to get shit like this out of there too

bmp.getWidth()
bmp.getHeight()

Why would you need to look this up every single loop, make it a constant!
You'll save 2 method calls per loop right there.
Kyros
Junior Developer
Junior Developer
 
Posts: 13
Joined: Wed Oct 21, 2009 11:49 am

Top

Postby mangaluve » Thu Nov 12, 2009 4:01 pm

Well Android is really slow for those kind of things. Perhaps it would be wise to write that part of the code in C, using the NDK? It will probably be at least 50 times faster (seriously).
mangaluve
Experienced Developer
Experienced Developer
 
Posts: 82
Joined: Mon Mar 23, 2009 8:59 pm

Postby I_Artist » Thu Nov 12, 2009 4:24 pm

Hi, yesterday I saw that this might just be the way that Android prefers doing fast redraws. Search for gaming on android, that should really help you with fast redraws...

Cheers!
The I_Artist

follow me on Twitter: @I_Artist
follow Android Development on Twitter: #androiddev

Show the world that you are an #androiddev, wear the badge http://www.twibbon.com/join/androiddev
User avatar
I_Artist
Developer
Developer
 
Posts: 33
Joined: Fri Oct 16, 2009 3:49 am
Location: St-Eustache, Quebec

Postby mangaluve » Thu Nov 12, 2009 4:30 pm

yups that's the way animations are handled by Android. Another alternative, which is basically the same thing, is to create a self-posting Runnable and post it to the UI-thread. Then, call invalidate() from that Runnable.
mangaluve
Experienced Developer
Experienced Developer
 
Posts: 82
Joined: Mon Mar 23, 2009 8:59 pm

Postby peaceoutside.org » Thu Nov 12, 2009 6:24 pm

Thanks for the replies.

Storing the Bitmap width and height is good to do, but it's certainly not the bottleneck.

Here's some things I found:

1. The emulator is apparently extremely slow in some cases compared to actual hardware. All my tests so far have only been on the emulator. Soon I will be doing additional tests on my actual phone.

2. Using Android's OpenGL classes might be the way to go.

Thanks for the tip about the NDK, I didn't even know that existed. It gives me a good reason to improve my C/C++ skills.

Does anyone have any links to examples or tutorials with OpenGL or the NDK with respect to my original question?
peaceoutside.org
Freshman
Freshman
 
Posts: 3
Joined: Mon Nov 09, 2009 5:32 am
Location: Reno, NV

Postby mangaluve » Fri Nov 13, 2009 7:52 pm

Yeah, sometimes the emulator performs better than the actual device, and in some cases it's being outperformed by the phone. But for your program, I doubt that you'll be satisfied with the fps on a phone. The things you do, for instance iterating over an array, is among the things that Android (or well, the dalvik VM) handles Really bad. I don't really see how OpenGL would result in better performance for this. The best way is probably to use the NDK. You'll pass the image as an integer array to a JNI-function, manipulate the data, and return it to use in your java code.

If you download the NDK, you'll find some samples of how to use it.
mangaluve
Experienced Developer
Experienced Developer
 
Posts: 82
Joined: Mon Mar 23, 2009 8:59 pm

Top

Return to View, Layout & Resource Problems

Who is online

Users browsing this forum: Exabot [Bot] and 5 guests