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.
Related
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.
I have one image image 1 and one is coming from server that is image 2 i am trying to draw second one just at the center of the first. as result i want single image like in pic .
This should do what you're looking for:
The backgroundBitmap variable would be your image1 and the bitmapToDrawInTheCenter would be your image2.
public void centerImageInOtherImage()
{
Bitmap backgroundBitmap = BitmapFactory.decodeResource(getResources(), R.drawable.ic_launcher);
Bitmap bitmapToDrawInTheCenter = BitmapFactory.decodeResource(getResources(), R.drawable.ic_action_search);
Bitmap resultingBitmap = Bitmap.createBitmap(backgroundBitmap.getWidth(), backgroundBitmap.getHeight(), backgroundBitmap.getConfig());
Canvas canvas = new Canvas(resultingBitmap);
canvas.drawBitmap(backgroundBitmap, new Matrix(), null);
canvas.drawBitmap(bitmapToDrawInTheCenter, (backgroundBitmap.getWidth() - bitmapToDrawInTheCenter.getWidth()) / 2, (backgroundBitmap.getHeight() - bitmapToDrawInTheCenter.getHeight()) / 2, new Paint());
ImageView image = (ImageView)findViewById(R.id.myImage);
image.setImageBitmap(resultingBitmap);
}
Courtesy : Draw text/Image on another Image in Android
Drawing images over each other is fairly simple with Canvas. Canvas basically acts as the drawing board to draw text/Image. You just need to construct a canvas with the first Image and then draw the second Image at the center as shown below
/* This ImageOne will be used as the canvas to draw an another image over it. Hence we make it mutable using the copy API
as shown below
*/
Bitmap imageOne = BitmapFactory.decodeResource(getResources(), R.drawable.imageOne).copy(Bitmap.Config.ARGB_8888,true);
// Decoding the image two resource into a Bitmap
Bitmap imageTwo= BitmapFactory.decodeResource(getResources(), R.drawable.imageTwo);
// Here we construct the canvas with the specified bitmap to draw onto
Canvas canvas=new Canvas(imageOne);
/*Here we draw the image two on the canvas using the drawBitmap API.
drawBitmap takes in four parameters
1 . The Bitmap to draw
2. X co-ordinate to draw from
3. Y co ordinate to draw from
4. Paint object to define style
*/
canvas.drawBitmap(imageTwo,(imageOne.getWidth())/2,(imageOne.getHeight())/2,new Paint());
imageView.setImageBitmap(imageOne);
I want to XOR two images in android as iam working on image encryption app iam bringing images from SD card and loading them in image view now as i have loaded two images i want to XOR both of them
Another alternative would be to draw on a Canvas both of your bitmaps. One bitmap does not specify any settings, but the other should specify a PorterDuffXfermode to Mode.XOR, in his Paint object.
Ex:
ImageView compositeImageView = (ImageView) findViewById(R.id.imageView);
Bitmap bitmap1=BitmapFactory.decodeResource(getResources(), R.drawable.batman_ad);
Bitmap bitmap2=BitmapFactory.decodeResource(getResources(), R.drawable.logo);
Bitmap resultingImage=Bitmap.createBitmap(bitmap1.getWidth(), bitmap1.getHeight(), bitmap1.getConfig());
Canvas canvas = new Canvas(resultingImage);
// Drawing first image on Canvas
Paint paint = new Paint();
canvas.drawBitmap(bitmap1, 0, 0, paint);
// Drawing second image on the Canvas, with Xfermode set to XOR
paint.setXfermode(new PorterDuffXfermode(Mode.XOR));
canvas.drawBitmap(bitmap2, 0, 0, paint);
compositeImageView.setImageBitmap(resultingImage);
It depends what you want to xor, the pixels or data itself.
any way an easy way to do it is to convert the to images to array of all the pixels, XOR them together and then convert it back to a bitmap. NOTE that this example will only work to bitmap with identical resolutions.
//convert the first bitmap to array of ints
int[] buffer1 = new int[bmp1.getWidth()*bmp1.getHeight()];
bmp1.getPixels(buffer1,0,bmp1.getWidth(),0,0,bmp1.getWidth(),bmp1.getHeight() );
//convert the seconds bitmap to array of ints
int[] buffer2 = new int[bmp2.getWidth()*bmp2.getHeight()];
bmp2.getPixels(buffer2,0,bmp2.getWidth(),0,0,bmp2.getWidth(),bmp2.getHeight() );
//XOR all the elements
for( int i = 0 ; i < bmp1.getWidth()*bmp1.getHeight() ; i++ )
buffer1[i] = buffer1[i] ^ buffer2[i];
//convert it back to a bitmap, you could also create a new bitmap in case you need them
//for some thing else
bmp1.setPixels(buffer1,0,bmp1.getWidth(),0,0,bmp2.getWidth(),bmp2.getHeight() );
see:
http://developer.android.com/reference/android/graphics/Bitmap.html
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 );
}
I'm building a game using Android 2.2. The main game Activity uses a custom SurfaceView:
class GameView extends SurfaceView
From what I understand, the onDraw() method requires its own Thread to be executed. That in mind, I am planning to add a background image in onDraw():
canvas.drawBitmap(wallpaper, 0, 0, paint);
paint = new Paint();
But when I execute the game, it becomes very slow. If I comment out the new Paint() line, the game speeds up.
Is there something I am doing wrong, or is there a solution to my problem? For example, is there a way to reduce the number of calls to onDraw()? Or add an XML attribute to my custom SurfaceView class?
Here's the code how I load the drawable images.
public Bitmap loadBitmap(String image) {
Bitmap bitmap = null;
try {
int id = R.drawable.class.getField(image).getInt(new Integer(0));
bitmap = BitmapFactory.decodeResource(context.getResources(), id);
// bitmap = Bitmap.createBitmap(bitmap.getWidth(), bitmap.getHeight(), Bitmap.Config.RGB_565);
} catch(Exception ex) {
Log.e("loadBitmap", ex.getMessage());
}
return bitmap;
}
Here's the code of the onDraw method.
Unfortunately, I can't post everything.
paint.setColor(Color.BLACK);
canvas.drawRect(0, 0, getWidth(), getHeight(), paint);
canvas.drawBitmap(gameLevel.getBitmap(), 0, 0, paint);
// draw object(1) 320x25
// draw object(5) 50x50 each
// draw object(n) 15x15 each, estimate
// draw object(n) 50x50 each
// collision check, draw hit tile on the image sheet
// draw game information using canvas.drawText()
timeLine++;
Thanks in advance!
If the problem is only the "paint = new Paint();" line, why don't you create the Paint object only once? When the class is first created and make it a Class variable. Then just use the object everytime you want.
You could try to load the background as RGB_565 instead of ARGB_8888 in case you haven't already. Otherwise there is not much you can do except switching to OpenGL
EDIT:
Options options = new Options();
options.inDither = false;
options.inJustDecodeBounds = false;
options.inSampleSize = 1;
options.mCancel = false;
options.inPreferredConfig = Config.RGB_565;
bitmap = BitmapFactory.decodeResource(context.getResources(), id, options);
If that doesn't help other reasons may be:
You drawing code is wrong
You scale the background when you draw it
You run it on an emulator