I have this code in a class that extends surface view and implements runnable
I am able to use the class basically allows you to draw to the canvas using different colors and such. I'm trying to get a method that will allow me to save the image after it is drawn and this is the method. No matter what i do i just get a black image with nothing on it. Any ideas?
I have cache drawing enabled
Objective get a bitmap image from a custom SurfaceView I have exhausted options of looking at some other post on here and didn't find anything to work. Here is hoping that there is recently a new solution to this. Many thanks
public Bitmap getImage() {
Bitmap bitmap = Bitmap.createBitmap(this.getWidth(),
this.getHeight(), Bitmap.Config.ARGB_8888);
Canvas canvas = new Canvas(bitmap);
this.draw(canvas);
return bitmap;
}
Your question became clear only by your last comment. In the code that you posted above, you are returning with return bitmap. That will return the local variable bitmap. This local variable is totally blank. You may be drawing to your bitmap or associating an image to it, somewhere else in the code. But the instance of bitmap in your above code, is blank and only local to the function. You cannot expect it to return your updated, latest bitmap.
Now, after your comment I googled "getting a bitmap of current surfaceview" and it led me to this SO answer: Create Bitmap from SurfaceView
In that question, it was apparently solved by extending View instead of SurfaceView. Drawing cache only works for View.
Update: Follow the below tutorials. Based on the code pasted by you, it's not clear what the error is. There are a lot of things that need be done for drawing to SurfaceView, and I'm not sure if you have done those, and I cannot ask for every such missing item. I followed below tutorials for my basic graphics projects. You need to read them and see if you have missed anything.
Tutorials on Canvas drawing:
Playing with Graphics in android all parts.
Android 2D
Related
I am trying to develop an android application to display a zoom-able, pan-able map, (which is just a bitmap image), that also allows the user to click on certain points on the map.
I am struggling to find the most effective way of implementing such an app. After trying numerous other methods, (including Webviews, OpenLayers), the best way, (according to this site at least), seems to be using a SurfaceView with a Canvas. The code I have so far is pieced together from snippets I found all over the internet, so it just crashes. I have included it here anyway in the hope it gives some idea of what I am trying to achieve:
public class Main extends Activity {
private Bitmap bmp;
private SurfaceView surfaceView;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
surfaceView = (SurfaceView)findViewById(R.id.surface);
bmp = BitmapFactory.decodeResource(getResources(),
R.drawable.testmapbmp);
//decode the bitmap file
Canvas canvas = new Canvas(bmp);
//create a canvas from the bitmap, then display it in surfaceview
surfaceView.draw(canvas);
}
}
Is this the best way to achieve the functionality I want for my application? Or is there a better way, especially if I could run into problems later on, implementing the clickable sections of the map, for example.
I really need help from someone who has created something like this before, so I can get my train-of-thought on the problem, but I greatly appreciate any help/pointers/tips at all!
Thanks
Your piece of code is not really correct.
Usualy if you want to do this kind if things you need to create your own custom view (either by inheriting View or SurfaceView). In your View subclass you need to override method onDraw(Canvas) and draw your bitmap on canvas by using one of canvas methods.
To make it pannable and pinch-zoomable you need to use Scroller and ScaleGestureDetector classes. Usually panning or scaling is done by applying affine transformations to a canvas by using it's methods (rotate, scale, translate).
Difference between SurfaceView and View is that in SurfaceView you can draw directly from separate thread, which means you can organize sort of rendering loop there and draw from it. It is good for simple games and animation effects. I believe, for purpose of drawing a bitmap this is overkill and much simpler to subclass View.
I'd start with this and this, if I were you.
i try to paint an arrow png on canvas with a png bitmap behind it. so every time i rotate the arrow i have to reset the background bitmap of the canvas becouse otherwise i would see duplicates of the old arrows.
i reset the background with:
bMapLoad.eraseColor(0);
the problem is that sometimes it erases parts of the new arrow. sow that i sometimes only see a part of the arrow. i rotate it aber every 10-100 ms.
can someone help me?
i also tried:
bMapLoad=bMapcanvasBack.copy(bMapcanvasBack.getConfig(), true);
canvasLoad.setBitmap(bMapLoad);
this works fine but needs more memory. so is there a better way?
edit:
also
canvasLoad.drawColor(0, PorterDuff.Mode.CLEAR);
don't work
Try canvas.drawARGB(0,0,0,0) or, more concise canvas.drawColor(0) to clear it, then draw the bitmap again (canvas.drawBitmap(...))
The partial overdrawing may have a different reason though - synchronization between drawing and display. A common practice is to use double buffering. This means, you would draw on a offscreen canvas, and then exchange the underlying Bitmap with the visible canvas.
EDIT: some useful resources on double buffering with android:
An example here plus the book "beginning android games" also features a section on double buffering. The source code for the book can be downloaded here
I'm using cocos2d.
Now I've added some images in the layer, and played around a bit.
I'm trying to save the whole screen as image file.
How can I do this?
The only way to capture the content of a SurfaceView is if you are rendering into it using OpenGL. You can use glReadPixels() to grab the content of the surface. If you are drawing onto the SurfaceView using a Canvas, you can simply create a Bitmap, create a new Canvas for that Bitmap and execute your drawing code with the new Canvas.
It is my understanding that cocos2d-android also has a CCRenderTexture class with the saveBuffer method. In that case have a look at my CCRenderTexture demo program and blog post for cocos2d-iphone which gives you an example for how to create a screenshot using CCRenderTexture and saveBuffer. The same principle should be applicable to cocos2d-android.
When I want to draw a BitmapDrawable to a Canvas in Android, there are two possibilities that do the same and I don't know which one to prefer:
Using canvas.drawBitmap() and extract the Bitmap from the drawable using getBitmap()
Using drawable.draw(canvas), passing the canvas as an argument to the drawable.
I'm using the first option now, but it seems completely arbitrary as I can't see any difference.
Thanks for your answers
Never do option number 1 the way you do it. Instead of creating a bitmap out of a drawable every time you want to draw it, create a bitmap in the first place. That is, don't create a Drawable if you are going to draw a bitmap. Create a bitmap like this:
mBitmap = BitmapFactory.decodeResource(mContext.getResources(), R.drawable.myImage);
mBitmap = Bitmap.createScaledBitmap(mBitmap, width, height, true);
And this is something you do just once. After that, just draw like you do (canvas.drawbitmap()).
As for option number 2, you are doing it correctly.
Now, there are some differences.
Option 1 is faster to draw and usually good for background images. There is a significant change to FPS depending on if you draw a bitmap or drawable. Bitmaps are faster.
Option 2 is the way to go if you need to things like scaling, moving and other kinds of manipulations of the image. Not as fast but there's no other option if you want to do any of those things just mentioned.
Hope this helps!
I am trying to make a game for the android. I currently have all of my art assets loaded into the drawables folder, but my question is how do I actually reference a specific one to render it?
I know that the files each have a unique #id, and I probably have to implement in the #override of the onDraw(canvas) method. so the question is how do I actually display the image to the screen?
I have looked through a good half dozen books and all those talk about is getting an image off the web, or manually drawing it with the paint functionality, but I have the assets ready to go in .bmp, and they are complex enough that coding paint to draw them by hand will be a very great migrain.
I would prefer a direction to look in (specific book, tutorial, blog, open source code[assuming quality comments])I am still kinda learning java as my 2nd programming language and so I am not to the point of translating pseudocode directly to java yet.
[added in edit]
does drawing using Paint() every frame have a lower overhead then rendering a bitmap, and only changing the display when it changes?
for 2Dgames I would recommend you to use SurfaceView
load your image as a bitmap and let the canvas draw that bitmap.
to animate the images there are two possible way :
You could inflate the view
Create a looping thread to call the draw function
Here's some good starting tutorial about displaying image in Android, especially for games
You can use one of the drawBitmap variants of the Canvas class. A canvas object is passed in the onDraw method. You can use the BitmapFactory class to load a resourse.
You can read a nice tutorial here.