android paint using bitmaps as a paint object - android

I am building a drawing app and would like to create custom brushes. I assumed there was a way to set your android.graphics.Paint object to use a bitmap along the path instead of a color, but this doesn't seem to be the case.. I suppose i could just save the path and draw bitmaps to it, but that seems excessive.. before i start trying to come up with a custom solution i was wondering if anyone has already tackled this. The idea is lets say i had a 'star' icon, id like to be able to draw a line of stars based on stroke width to the path the user has drawn..
Psuedo code:
drawPath = new Path();
drawPaint = new Paint();
//drawPaint.setColor(paintColor);
drawPaint.setBitmap(bitmap); /// <-- wouldn't that be sweet

Nevermind.. i found it.. i knew i could do this..
drawPaint.setShader(new BitmapShader(bm, Shader.TileMode.REPEAT, Shader.TileMode.REPEAT));

Related

How to make circle drawable in Android custom canvas?

I want to make in my app possibilty to draw circles by user. The drawing is quite simple - user just press on canvas somewhere and then predefined circle
The difficult part here is to draw it with some drawable (picture) as a fill. It is quite simple when it is about rectangle. Then you just need to write:
Drawable drawable = getResources().getDrawable(R.drawable.my_background_picture);
drawable.setBounds(myRectangle);
drawable.draw(myCanvas);
Everything is done on onDraw() method of my custom view.
Unfortunatelly there isn't such simple method to make it with circle. The one that I've found is slight modification from Vogella's tutorial:
InputStream resource = getResources().openRawResource(R.drawable.sand);
Bitmap bitmap = BitmapFactory.decodeStream(resource);
BitmapShader shader;
shader = new BitmapShader(bitmap, Shader.TileMode.CLAMP,Shader.TileMode.CLAMP);
paint = new Paint();
paint.setAntiAlias(true);
paint.setShader(shader);
myCanvas.drawRoundRect(myRectangle, 120, 120, paint);
At first sight it looks ok, but it's not. This commands make just something like frame on a picture below, so you move hollow circle on a picture and that's all. Not as with rectangle where you actually move rectangular bitmap.
So, my question is - Is there a way to make circle drawable that can be also moved/resized?
Why make a drawable? You can easily draw a circle via the canvas.drawCircle command. You can also easily make one via a Path object.
Edit:
If you need a drawable, try making a ShapeDrawable based off an OvalShape.

How to remove the drawing from a bitmap of a particular region in Android

I have a bitmap object.
I have a Region object that represents a small portion of the bitmap;
I want to remove drawing from the bitmap object of that particular region and make that portion transparent..
How to do it? any help....
I am using android api-level 8..
You can simply make a pixel transparent by using mBitmap.setPixel (100,100,Color.TRANSPARENT);, so basic idea is to iterate over all the pixel to make it transparent, but if you have to iterate over too many pixels, it might be slow.
OR
You can use PorterDuffXferMode to make a portion transparent,
For an example create a paint object as mentioned below and pass it to the canvas:
Paint mPaint = new Paint();
mPaint.setXferMode(new PorterDuffXferMode(PorterDuff.Mode.CLEAR));
You can pass it to the canvas as described below:
Canvas c = new Canvas(mBitmap);
c.drawCircle(cx, cy, radius, paint);
It is for the circle but hope you will get the hint to do it for the custom region as per your need.
If still it is not working then you might have to disable Hardware Acceleration for that particular View. For more information, refer this Google DOC.
Hope this will give you some hint.

Custom Image View

I have this image that comes back from an API, which represents the users avatar:
However, my graphics department has designed the app to mask the image to make it look like this at runtime (to match our existing design of sharp edges, etc):
Notice the small edge cutout on the bottom left?
I'd love to be able to create a custom ImageView that handled this for me. Unfortunately I'm not sure how to go about doing that. How can I create the bottom image in a custom ImageView. Is this possible? Do I mask it? If so, how?
Thanks!
Using Path and xfer modes to draw on canvas can do the trick. Check this answer how to draw pic to Closed curve area
I think the easiest way to do is to use 2 ImageViews, one with the photo and other above it with a mask for the photo, in your case it would be all transparent except the bottom left to create the cutout with the background color.
You may be able to use android.graphics.Path to draw the complex shape you want. I found this very helpful for a simple custom View, but it seems like you can do a lot with it:
http://developer.android.com/reference/android/graphics/Path.html
Simple code sample for a shaded rectangle:
private Path mRectanglePath;
...
// draw the path
mRectanglePath = new Path();
mRectanglePath.addRect(mLeft, mTop, mRight, mBottom, Path.Direction.CW);
// draw the fill
Paint paint = new Paint();
paint.setColor(Color.RED);
paint.setAlpha(64);
canvas.drawPath(mRectanglePath, paint);

Android DrawBitMap very slow when using ARGB_8888

I find that DrawBitMap is taking 50-60 ms for drawing just three bitmaps one is a rectangle occupying the full screen, one is a circle and another one is a Path. My bitmaps are created by using Canvas.drawPath, drawRect and drawCircle on a blank bitmap with the Bitmap.Config as ARGB_8888.
I am using ARGB_8888 to make the background visible to get a layering effect.
I was shocked to find the time taken as around 50ms as I thought drawBitmap would be a very simple operation. Can someone guide as to is there any fundamental mistake that I am making. Following is my code
Creating the Blank Bitmaps
Rectangle = Bitmap.createBitmap(320,480,Bitmap.Config.ARGB_8888);
Circle = Bitmap.createBitmap(70,70,Bitmap.Config.ARGB_8888);
Leaf1 = Bitmap.createBitmap(20,30,Bitmap.Config.ARGB_8888);
Drawing the Shapes on the appropriate BitMap
Canvas c = new Canvas(Rectangle);
Paint p = new Paint();
p.setAntiAlias(true);
p.setColor(0xff6e8b3e);
c.drawRect(0,0,320,480,p);
Canvas c = new Canvas(Circle);
Paint p = new Paint();
CirclePath = new Path();
p.setAntiAlias(true);
p.setColor(0xffcd661d);
System.out.println("x = "+x+" y = "+y);
CirclePath.addCircle(50,50,10,Path.Direction.CW);
c.drawPath(CirclePath,p);
Canvas c = new Canvas(Leaf1);
Paint paint = new Paint();
Path path = new Path();
paint.setAntiAlias(true);
path.moveTo((float)184.37,(float)219.15);
path.cubicTo((float)188.32,(float)219.15,(float)192.88,(float)220.44,(float)195.62,(float)223.54);
path.cubicTo((float)197.84,(float)226.05,(float)203.2,(float)229.84,(float)198.18,(float)245.98);
Drawing the BitMap in OnDraw
canvas.drawBitmap(Rectangle,0,0,p);
canvas.translate(x,y); // For animation effect
canvas.drawBitmap(Circle,0,0,p);
canvas.drawBitmap(Leaf1,0,0,p);
Now when I record the time taken for this three drawBitMap I find it is taking around 50ms
Is there something big time mistake in the code. Changing the Bitmap.Config to RGB_565 brings the time down to around 8ms but then the background is not visible and I am getting a black box around the path
Looks normal.
Canvas is very slow on transparency.
You can either try to switch to OpenGL ES or design your content with as little transparency as possible so you can use RGB_565 as often as possible.
You should always match the format of your screen. There was a very similar question recently, and Romain mentioned that blits essentially turn into memcpys if the format matches. And, of course, make sure that you're not using an esoteric blit mode.
Also, why are you using anti-aliasing if you're not scaling/rotating anything?
As for 565 not working - I'm just skimming over your code. Are you using the alpha channel? What exactly do your bitmaps look like?
One of the Android devs explains this here. To draw ARGB_8888 quickly you need to draw to a 32-bit window. See bottom of article for benchmarks.

moving a path with a repeating Bitmap image in android

I'm currently writing an android side-scrolling game and am having trouble filling a path with a repeating bitmap image. I'm creating a path from a number of coordinates to make up the "ground" area. I have a character who is fixed in the middle of the canvas and screen and am moving the path to represent the movement of the character. I've been able to fill the path with a repeating image using a BitmapShader. Also I can move the path shape from side to side on the screen. However, the Bitmapshader seems to be using a default origin of 0,0 which means the shader is always drawing the ground repeating image in the same place. This means that even though the path is moving the ground repeated image never appears to move. Does anyone have any idea how to change the origin of the shader or know of a better way to fill the path with a repeating image?
Alternatively, can anyone suggest a better solution for filling a drawable shape with an image?
Thanks
Andy
Thanks, had a look at those...Replica Island seems to use OpenGL quite a lot which is a bit beyond me at present and Snake didn't quite do what I was looking for...eventually got there..
//Shape pathShape = this.getPathShape();
Bitmap groundImage = ImageHandler.getmGroundImage();
int offset = groundImage.getWidth()-(xPosition%groundImage.getWidth());
Path path = new Path();
path.moveTo(coordinates.get(0).getmX(), coordinates.get(0).getmY());
for ( ShapeCoordinate coordinate : coordinates ) {
path.lineTo(coordinate.getmX(), coordinate.getmY());
}
path.lineTo(coordinates.get(coordinates.size()-1).getmX(), mYBase);
path.lineTo(coordinates.get(0).getmX(), mYBase);
path.lineTo(coordinates.get(0).getmX(), coordinates.get(0).getmY());
path.close();
PathShape shape = new PathShape(path,canvas.getWidth(),canvas.getHeight());
BitmapShader bs = new BitmapShader(groundImage, Shader.TileMode.REPEAT,Shader.TileMode.REPEAT);
Matrix matrix = new Matrix();
matrix.reset();
matrix.setScale(1,1);
matrix.preTranslate(offset, 0);
bs.setLocalMatrix(matrix);
ShapeDrawable sd = new ShapeDrawable(shape);
sd.setColorFilter(Color.argb(255, 50*(mLevel+1), 50*(mLevel+1), 50*(mLevel+1)), Mode.LIGHTEN);
sd.getPaint().setShader(bs);
sd.setBounds(0, 0, canvas.getWidth(), canvas.getHeight());
sd.draw(canvas);
Have you looked at the Snake example in the android sdk? Also Replica Island is another example of how to do a tile engine in android.

Categories

Resources