This link: http://www.mediafire.com/view/?hr441qalu6b6d7s
points to an image that show that my drawing of Bitmaps is taking a long time and resulting in lag in my application. How can I optimize this so as not to cause so much lag. Currently I have this as my canvas method:
Canvas c = holder.lockCanvas();
Paint p = new Paint();
p.setTextSize(30);
p.setColor(Color.BLACK);
new handleStuff().execute("");
//Actions End
//Background
Bitmap scaledBackground = Bitmap.createScaledBitmap(background, this.getWidth(), this.getHeight(), true);
c.drawBitmap(scaledBackground, 0, 0, null);
//Background End
My initial thoughts are that the drawing of the background every single time is what is causing that lag, but I am not sure.
Put all object creation outside of the draw method (so only create the bmp/paint etc in your init/whatever) and then use them in the draw method.
This will speed up thing and reduce memory use and reduce garbage collection ... a lot.
Related
The helper function below draws a rectangle on top of input bitmap and returns a thumbnail bitmap. However, I run into java OutOfMemory Error when I call this helper around 1000 times from an activity to populate a list of thumbnails. I tried resizing the tempScaledBitmap to 375, 500 but the quality of the thumbnail image is poor.
Also, I was unable to directly draw on inputBitmap as it was immutable.
What is an efficient way to display a list of 1000 plus thumbnails in an activity?
private static Bitmap drawOnCanvas(Bitmap inputBitmap, FramePoint[] points, ColorCode colorCode){
Bitmap tempScaledBitmap = Bitmap.createScaledBitmap(inputBitmap, 750, 1000, false);
//draw path
Canvas canvas = new Canvas(tempScaledBitmap);
// Path
Paint paint = new Paint();
paint.setStyle(Paint.Style.STROKE);
paint.setColor(colorCode.equals(ColorCode.GREEN)?Color.GREEN:(colorCode.equals(ColorCode.RED)?Color.RED:Color.BLUE));
paint.setStrokeWidth(5);
Path p = new Path();
p.moveTo(points[0].getPointX(), points[0].getPointY());
p.lineTo(points[1].getPointX(), points[1].getPointY());
p.lineTo(points[2].getPointX(), points[2].getPointY());
p.lineTo(points[3].getPointX(), points[3].getPointY());
p.close();
canvas.drawPath(p, paint);
return tempScaledBitmap;
}
After each call to drawOnCanvas you should recycle your bitmaps:
inputBitmap.recycle();
Also recycle the tempScaledBitmap after they are assigned to ImageViews or wherever to prevent this OOM errors.
Also, you could consider using picasso or glide. For me, it's the best option of all.
I have an Activity in which the user touches the eye positions on a picture, and this is supposed to draw a little white circle over each. I have a working bit of code that, using the Android FaceDetector tools, finds the eye positions and facial midpoint and draws a rectangle. The drawing part of that code, for reference, is this:
private void drawRectangles(){
Canvas canvas = new Canvas(mBitmap);
Paint paint = new Paint();
paint.setStrokeWidth(2);
paint.setColor(Color.BLUE);
paint.setStyle(Style.STROKE);
for (int i=0; i < faceFrames.length; i++) {
RectF r = faceFrames[i];
if (r != null){
canvas.drawRect(r, paint);
Log.d(TAG, "Drew rectangle");
}
}
mImageView.setImageResource(0);
mImageView.setImageBitmap(mBitmap);
mImageView.draw(canvas);
}
That part's fine. I figured, as a method that is called from onTouchEvent, that I could use the following to draw a circle:
private void makeDrawableLayer(int x, int y, int touchCount){
if (touchCount == 1){
Bitmap eyeOneBmp = Bitmap.createBitmap(mBitmap);
Canvas c1 = new Canvas(eyeOneBmp);
c1.drawCircle(x, y, 5, eyePaint);
mImageView.setImageResource(0);
mImageView.setImageBitmap(eyeOneBmp);
mImageView.draw(c1);
}
}
Here are screen shots showing the result of each code snippet. The first picture is the rectangle drawn on the face. The second picture shows the very strange result I get when I attempt to draw using the second code snippet. Note, however, that I had specified x and y as 10, 10 for the circle's position when drawing the second output. It's the same thing when I give it the passed-in eye position coordinates, just with the pixelated circle coming from wherever the eye is.
Does anyone have any idea what the heck is going on with this behavior?
Thanks so much.
So I found that you can basically only draw one time to the canvas before needing to make a class that extends View to start calling methods from. What I ended up needing to do was: customView.prepareCircle(), customView.invalidate(), and then parentView.addView(customView). And actually, I could only prepare, invalidate, and re-add the modified custom view to the canvas once before having to make any subsequent calls from a Runnable on the UI thread. I am not under the impression this is an ideal way to do it (certainly doesn't feel elegant), but it is giving me the results I want:
I need to "compute" the resulting bitmap obtained from overlapping two different bitmaps that have an alpha value somewhere between 0 and 255. I need to do this in java code, not xml, because bitmaps are being loaded dinamically and not from resources.
Here is my first try (which always yields a black bitmap...):
private Drawable composeBitmaps(int alpha1, BitmapDrawable bm1,
int alpha2, BitmapDrawable bm2)
{
Canvas c = new Canvas();
Bitmap b1 = bm1.getBitmap();
BitmapDrawable draw1 = new BitmapDrawable(b1.copy(b1.getConfig(), true));
draw1.setAlpha(alpha1);
c.setBitmap(draw1.getBitmap());
Paint p = new Paint();
p.setAlpha(alpha2);
c.drawBitmap(bm2.getBitmap(), 0, 0, p);
return draw1;
}
...
View v = // whatever
v.setBackgroundDrawable(composeBitmaps(100, bdrawable1, 150, bdrawable2));
And the view goes black background. What am I doing wrong?
My code above is absolutely correct. The bug that made the bitmap go black was elsewhere. Found it, fixed it, now it works.
The only thing to note is that my code is slow as hell and it cannot be used to crossfade two fullscreen bitmaps at a reasonable fps rate.
I have an application which requires me to draw paths to a canvas. As the number of paths builds up, the cumulative drawing action takes longer, so I thought I would improve speed by using the drawing cache.
To do this I have an onDraw method looking a bit like this:
#Override
protected void onDraw(Canvas canvas) {
Path path;
Paint paint;
synchronized(mPaths) {
buildDrawingCache();
Bitmap bmp = getDrawingCache();
if(bmp!=null) canvas.drawBitmap(bmp,
new Rect(0, 0, bmp.getWidth(), bmp.getHeight()),
new Rect(getLeft(), getTop(), getRight(), getBottom()),
null);
for(int i=mLastCount; i<mPaths.size(); ++i) {
path = mPaths.get(i);
paint = mPaints.get(i);
canvas.drawPath(path, paint);
}
mLastCount = 0;
mDrawn = true;
destroyDrawingCache();
}
}
mPaths and mPaints are lists of Path and Paint objects and I have a method set up to work out how many are new so it only redraws the last one. I originally called setDrawingCacheEnabled(true) instead of buildDrawingCache() and destroyDrawingCache() but this didn't work (that may be significant).
Anyway, this code works—it produces a bitmap which I can write to the canvas, then I only draw the last path and everything is fine except that as I draw more and more paths, it still slows down, as though it were still redrawing all the paths during buildDrawingCache().
Is that what's happening? Ideally I would like the draw method to be blitting a bitmap, then placing a single path over it. If it's generating the bitmap from all the paths, every time, I might as well not bother (in fact I will probably write my own bitmap generation code if this is the case, but it seems a pain).
If it isn't what's happening, is there something else that could be causing the code to slow down?
Hi every am new to this android development.
Currently am developing drawing application with adding stamps/labels to drawn image.so i have done drawing part so now i have to implement adding stamps/labels to that drawn image.
So please help me out this..
Bitmap Rbitmap = Bitmap.createBitmap(bitmap).copy(Config.ARGB_4444, true);
Canvas canvas = new Canvas(Rbitmap);
canvas.drawBitmap(label, -9, Rbitmap.getHeight()-label.getHeight()-10, null);
canvas.save();
return Rbitmap;
Making your question little more specific will help you more.If I understood is correct this piece of code will help you out to draw a bitmap to a drawn canvas.
private Paint green = new Paint();
private int greenx , greeny;
green.setColor(Color.GREEN);
green.setAntiAlias(false);
canvas.drawCircle(greenx,greeny,20,green);
how to add image in this code replace drawcircle with image how ?
You could be a little more specific, i.e posting some code to show what you have to get more specific answers. Anyway, you can draw a bitmap on top of another bitmap by using something like this:
//You will have a Bitmap bottomBmp, a Bitmap topBmp and a Canvas canvas.
//If you are inside an onDraw() method the canvas will be provided to you, otherwise you will have to create it yourself, use a mutable bitmap of the same size as the bottomBmp.
canvas.drawBitmap(bottomBmp, 0, 0, null); //Draw the bottom bitmap in the upper left corner of the canvas without any special paint effects.
canvas.drawBitmap(topBmp, 0, 0, null); //Draw the top bitmap over the bottom bitmap, change the zeroes to offset this bitmap.
Try with this code:
private Bitmap background;
public birdClass(Context context) {
super(context);
background = BitmapFactory.decodeResource(getResources(),R.drawable.splash );
}