I want to display continuous bitmaps efficiently. First I tried with SurfaceView with code like the following:
Canvas canvas = holder.lockCanvas();
canvas.drawBitmap(bmpNow, 0, 0, paint);
holder.unlockCanvasAndPost(canvas);
However, the performance is bad and can not meet my needs. Then I tried it another way. I directly use ImageView and imageView.setImageBitmap(bitmap), and this way performance was better than in the former case, but even so, it still can not meet my needs.
EDIT: continuous bitmaps are frames captured by a camera. They will display frame by frame with a UI widget like ImageView. I want this UI widget to display the frames fast and fluently, for example: display more than 15 or 20 frames per second. The problem is, I do not know which UI widget to choose, and how to use it efficiently.
For fast frame-by-frame animation, you should consider using OpenGL. I suggest using either libgdx or andengine libraries.
Using the normal API will be easier, but there will be a lot of performance and memory issues that you will need to handle.
Related
I'm making a simple 2d game in android. However, even with only a few images on screen, I'm running into problems with fps(its around 15-25 and quite stuttery).
Currently I use canvas, and simply set up an image each frame with everything I need to display on it.
Here's some of my render code:
public void render(Painter g) {
g.setColor(Color.rgb(208, 244, 247));
g.fillRect(0, 0, GameMainActivity.GAME_WIDTH, GameMainActivity.GAME_HEIGHT);
g.setColor(Color.rgb(139,69,19));
g.fillRect(0, 1400, GameMainActivity.GAME_WIDTH, GameMainActivity.GAME_HEIGHT - 1400);
g.drawImage(Assets.background3stone, currentBackground3X, 141);
g.drawImage(Assets.background3stone, currentBackground3X + 3459, 141);
g.drawImage(Assets.background2stone, currentBackground2X, 141);
g.drawImage(Assets.background2stone, currentBackground2X + 3459, 141);
g.drawImage(Assets.ground, currentBackground1X, 760);
g.drawImage(Assets.ground, currentBackground1X + 3000, 760);
renderNews(g);
renderButtons(g);
g.drawImage(Assets.leaderboard, 40, 180, 148, 148);
g.drawImage(Assets.achievements, 40, 354, 148, 148);
g.drawString("FPS: " + frameValue, 50, 200);
}
This code runs for every iteration of the game loop.
Does anyone know any ways to optimize my performance? Currently I redraw literally everything every frame, is there a way to not redraw static images? Would switching to openGl help a lot?
Thanks!
There's also a lot of good and efficient game engines available for Android (For example LibGDX). Game engines are usually well optimized for showing, moving and animating multiple images and they usually come with plenty other useful features.
However, if you prefer not to use game engines, I'd recommend using OpenGL to get some boost. You may also get some boost by optimizing your images. Try to reduce the sizes of images and don't use too large images. Also try to load images efficiently to the program.
Switching to openGL would always help a lot. But your problem is that you're drawing directly to the screen. Don't do that. Draw to a bitmap, then blit the bitmap to the screen in a single operation. The performance of that will be MUCH higher. It also would allow you to do your drawing on a 2nd thread and only draw to the screen on the main one.
Before switching to openGL you may want to try to not redraw the image itself, but just to move it. You just need to set new LayoutParams to your image. You may also want to look at TranslateAnimation in case you are moving stuff softly. Or you use a matrix transformation.
I am creating an Android App that produces random images based on complex mathematical expressions. The color of a pixel depends on its location and the expression chosen. (I have seen many iPhone apps that produce "random art" but relatively few Android apps.)
It takes 5 to 15 seconds for the image to be drawn on a Nexus S dev phone.
To keep the UI thread responsive this seems like the purpose of the SurfaceView class. Almost all the examples of SurfaceView deal with animation, not a single complex image. Once the image is done being drawn / rendered I won't change it until the user
So, is SurfaceView the right component to use? If so, can I get a callback from the SurfaceView or its internal thread when it is done drawing when it is done rendering the image? The callback is so I know it is okay to switch the low resolution and blocky version of the image art with the high resolution one?
Is there an alternative to SurfaceView that is better for complex rendering of single images. (Not animation.)
Cheers!
If all you want to do is render a single complex image on another thread to keep the UI responsive, then after it's done rendering actually draw it, you might consider just doing this in the standard keep-work-off-the-UI-thread way by using something like an AsyncTask. It's not like you're doing compositing or anything that really is GPU-specific (unless as others have suggested you can offload the actual rendering calculations to the GPU).
I would at least experiment with simply building an array representing your pixels in an AsyncTask then when you're done, create a bitmap with it using setPixels and set the source of an ImageView to that bitmap.
If on the other hand you want your image to appear pixel by pixel, then maybe SurfaceView might be a reasonable choice, in which case it'll basically be an animation so you can follow other tutorials. There's some other setup, but the main thing would be to override onDraw and then you'll probably have to use Canvas.drawPoint to draw each pixel.
I want to make brushes displayed in below image for drawing application. Which is a suitable method - Open GL or Canvas & How can we implement it?
I'd say Canvas, as you'll want to modify an image. OpenGLES is good for displaying images, but does not (as far as I know) have methods for modifying its textures (unless you render to a texture that then render to screen with some modifications, which is not always so effective).
Using the Canvas you will have the methods for drawing your brush-strokes onto the Bitmap you're painting on, in GLES you would have to modify a texture (by using a canvas) and then upload that to the GPU again, before it could be rendered, and the rendering would most likely just consist of drawing a square with your texture on it (as the fillrate for most mobile GPUs are quite bad, you don't want to draw the strokes separately).
What I'm trying to say is; The most convenient way to let the user draw on an openGLES surface would be by creating a texture by drawing on a Canvas.
But, there might still be some gain in using GL for drawing, as the Canvas-operations can be performed off-screen, and you can push this data to a gl-renderer to (possibly) speed up the on-screen drawing.
However; if you are developing for Android 3.x+ you should take a look at RenderScript, (which I personally have never had a chance to use), but seems like it would be a good solution in this case.
Your best solution is going to be using native code. That's how Sketchbook does it. You could probably figure out how by browsing through the GIMP source code http://www.gimp.org/source . Out of Canvas vs OpenGL, Canvas would be the way to go.
It depends. if you want to edit the image statically, go with canvas. But if you want after brushing the screen, to have the ability to edit, scale, rotate, it would be easier with opengl.
An example with opengl: Store the motion the user do with touchs. create a class that store a motion and have fields for size, rotation etc. to draw this class, just make a path of the brush image selected following the stored motion.
I have a drawing app where the user can draw lines with their finger, adjust the color, thickness, etc. As the user is drawing, I am converting the massed X/Y points from MotionEvent into SVG Paths, as well as creating Android Path's and then drawing the Android Path's to the screen via a Canvas, and committing the SVG Path's to the app's database.
I am following the model used in FingerPaint, in that the 'in progress' lines are drawn on the fly by repeated calls to invalidate() (and thus, onDraw()), and once the line is complete and a new line is started, the previous line(s) are drawn in onDraw() from the underlying Canvas Bitmap, with in progress lines again generating repeated re-draws.
This works fine in this application - until you start rotating the underlying Bitmap to compensate for device rotation, supporting the ability to 'zoom in' on the drawing surface and thus having to scale the underlying Bitmap, etc. So for example, with the device rotated and the drawing scaled in, when the user is drawing, we need to scale AND rotate our Bitmap in onDraw(), and this is absolutely crawling.
I've looked at a SurfaceView, but as this still uses the same Canvas mechanism, I'm not sure I'll see noticeable improvement... so my thoughts turn to OpenGL. I have read somewhere that OpenGL can do rotations and scaling essentially 'for free', and even seen rumors (third comment) that Canvas may be disappearing in future versions.
Essentially, I am a little stuck between the Canvas and OpenGL solutions... I have a 2D drawing app that seems to fit the Canvas model perfectly when in one state, as there are not constant re-draws going on like a game (for instance when the user is not drawing I don't need any re-drawing), but when the user IS drawing, I need the maximum performance necessary to do some increasingly complex things with the surface...
Would welcome any thoughts, pointers and suggestions.
OpenGL would be able to handle the rotations and scaling easily.
Honestly, you would probably need to learn a lot of OpenGL to do this, specifically related to the topics of:
Geometry
Lighting (or just disabling it)
Picking (selecting geometry to draw on it)
Pixel Maps
Texture Mapping
Mipmapping
Also, learning OpenGL for this might be overkill, and you would have to be pretty good at it to make it efficient.
Instead, I would recommend using the graphic components of a game library built on top of openGL, such as:
Cocos2d
libgdx
any of the engines listed here
Well, this question was asked 6 years ago. Maybe Android 4.0 has not come up?
Actually, after Android 4.0 the Canvas at android.view.View is a hardware accelerated canvas, which means it is implementd by OpenGL, so you do not need to use another way for performance.
You can see the https://github.com/ChillingVan/android-openGL-canvas/blob/master/canvasglsample/src/main/java/com/chillingvan/canvasglsample/comparePerformance/ComparePerformanceActivity.java to compare the performance of normal canvas in view with GLSurfaceView.
You are right that SurfaceView uses Canvas underneath the hood. The main difference is that SurfaceView uses another thread to do the actual drawing, which generally improves performance. It sounds like it would not help you a great deal, though.
You are correct that OpenGL can do rotations very quickly, so if you need more performance that is the way to go. You should probably use GLSurfaceView. The main drawback with using OpenGL is that it is a real pain to do text. Basically you have to (okay, don't have to, but seems to be the best option) render bitmaps of text.
I'm writing a game in Android/OpenGLES, and when I use traceview, I see that the time taken to draw my background image (using glDrawTexfOES) is quite huge.
I understand of course that as the background fills the screen, it should take longer than my other sprites, but is there a faster way to draw the background image. The background does not move or change during the game, so maybe there is a tip or trick to do it faster ?
In most cases, I believe it's faster to do what you want by drawing and texturing a quad(well, or a triangle strip) using a texture buffer. I don't have any solid benchmarks, but it made a pretty big difference for me. Mine was a lot of smaller images(font renderer) rather than one large one, but faster is faster in my experience.