I have a widget which looks like this:
Every cone is a "touchable element". Now I want to put a bitmap texture above each cone. However, bitmap images are all rectangular, so a bitmap texture above one cone would interfere with the bitmap texture above another cone.
I'm wondering what is the best solution to this approach. Should I just create an image which fits (as a rectangle) exactly above the cone and make the non used areas transparent?
A second question is, how do bitmap textures work with stretching? Because this whole circle draws itself to fit the whole screen size, while bitmap textures are pretty much one size.
Offhand I can't think of a better way to draw bitmaps over those cones than your own suggestion of using transparent zones.
However, I can help with your second question as stretching bitmaps is not hard. You've got a few options in the Canvas class. For example:
canvas.save();
canvas.scale(xRatio, yRatio);
canvas.drawBitmap(....);
canvas.restore();
You can also use a Matrix, using matrix.postScale(xRatio, yRatio), to then generate either a larger bitmap and draw it normally, or pass the matrix in to your canvas.drawBitmap(....) command to make it scale while it draws.
All of these methods assume you have access to the drawing canvas itself. If you are using a view, you can subclass it and override the onDraw(Canvas canvas) method to grab the canvas before it starts drawing it. If you're using a SurfaceHolder, then you should already know how to get the canvas.
Edit: I forgot the third method I was going to describe. You can use the canvas.drawBitmap(bitmap, srcRect, dstRect, paint) to also make the canvas scale the bitmap to fit the destination rectangle. In short, there are lots of methods to do this - pick the one that's easiest based on your application!
Related
So on my canvas I have few rectangular areas where I draw different bitmaps.
Sometimes bitmaps get outside of their respective areas. I want these bitmaps to be cut off, so only the portion of bitmap inside of it's area is drawn.
I sure can calculate it manually (srcRect and dstRect)...
But isn't there a simpler solution?
I found clipBounds, but it doesn't seem to restrict drawing area in any way.
What you want is Canvas.clipRect(). You will need to know the bounds of the clipping rectangle, of course, but you don't need to worry about calculating a custom srcRect.
To use, save() the Canvas, do a single drawBitmap(), then restore() it to get your original clipping state back:
canvas.save();
canvas.clipRect(...);
canvas.drawBitmap(...);
canvas.restore();
I need to save a number of formatted circles to a Bitmap whenever a button is pushed, and then draw those circles to the canvas. I was looking around, but had a great deal of trouble finding resources on how to save a shape I had created that was not an already created resource file. Any advice on how to go about this would be appreciated.
Say you are in your custom view, but it should work also with a OnTouchListener in any view.
Create a mutable bitmap with Bitmap.createBitmap() with the same width and height of your view
use your logic for getting information of the circles, for example you can use onTouchEvent() to get the coordinates of you finger(s)
with this information you can use Bitmap.setPixel() to save it to the bitmap
optional, onDraw() you can draw your bitmap with Canvas.drawBitmap()
In case you need to draw shapes to the bitmap you can create a new Canvas(bitmap) and draw on this canvas: the pixels will be set on the bitmap.
im working on an app, that displays large(around 2000x2000px) bitmap in imageview. This image has to be that large since user can pinch to zoom it in order to see some details. App has to be able to draw circles on that image, and also to display image alone, without circles on it. I was using 2 layers but the problem is memory since 2k x 2k px is around 16mb of memory, and creating another bitmap(another 16mb), just to draw a few circles, is pointless in my opinion. Is there any way, that you can draw simple primitives on image, and also be able to display it without primitives(circles in my case)?
Maybe somehow to store only modified pixels or sth?
Thanks!
You don't need to make another 2000x2000 Bitmap to draw those circles on. Just 'prerender' a circle, and then choose where you draw it.
I'm working under the assumption that you're drawing your 'big' image on a Canvas, since you have zooming features etc.
If you're not, you'll need to override your SurfaceView's onDraw(Canvas canvas) method so that you can access the SurfaceView Canvas. I won't go into depth about that part since again I'm assuming you have it, but if not the implementation of that function would look like this:
//Overriding SurfaceView onDraw(Canvas canvas)
#Override
protected void onDraw(Canvas surfaceCanvas) {
if(canvas == null) return; //No Canvas? No point in drawing then.
surfaceCanvas.drawColor(Color.BLACK);
//Draw your 'big' image on the SurfaceView Canvas
insertYourBigImageDrawingFunctionHere(surfaceCanvas);
//Now draw your circles at their correct positions...
insertCircleDrawingFunctionHere(surfaceCanvas);
}
Now that you have access to the SurfaceView Canvas, you can choose precisely how things are drawn on it. Like circles for example...
I want to draw your attention to the multiple Canvas' being used below (surfaceCanvas vs. circleCanvas). I once thought that Canvas was a kind-of 'one Canvas for the whole app/activity' implementation, but it isn't. You are free to create Canvas' as you please. It is merely an instance of a tool to draw onto Bitmaps. This was a HUGE revelation for me, and gave me much more robust control over how Bitmaps are composed.
public void myCircleDrawingFunction(Canvas surfaceCanvas){
//Make a new Bitmap for your circle
Bitmap.Config conf = Bitmap.Config.ARGB_4444;
tinyCircleBMP = Bitmap.createBitmap(10,10, conf);
//Make a new canvas using that Bitmap as the source...
Canvas circleCanvas = new Canvas(cacheBmp);
//Now, perform your drawing on the `Canvas`...
Paint p = new Paint();
circleCanvas.drawCircle(5, 5, 5, p);
//Now the `Bitmap` has a circle on it, draw the `Bitmap` on the `SufaceView Canvas`
surfaceCanvas.drawBitmap(tinyCircleBMP, 10, 10, p);
//Replace the '10's in the above function with relevant coordinates.
}
Now obviously, your circles will zoom/pan differently to your 'big' image, since they are no longer being drawn at the same size/position of the 'big' image. You will need to consider how to translate the positions of each circle taking into account the current scale and position of the 'big' image.
For example, if your image is zoomed in to 200%, and a circle is supposed to appear 100px from the left of the big image, then you should multiply the pixel values to take into account the zoom, like this
(PsuedoCode):
drawCircleAtX = Bitmap.left * BitmapZoomFactor
If you are using the canvas API (if not I would suggest to)? if so you are just draw your image on the canvas and then the primitive shapes on top of the same canvas before display. This way you just keep a reference of the circles position in some basic data types and scale them as the user moves around and zooms, so you know where to draw them each frame.
I would like to create a 'graph paper' look to the Bitmap I am drawing via a Canvas, and trying to figure out the best way to do this.
I can't pass a source Bitmap containing the graph paper background to the Canvas constructor, as I am getting the Canvas in a SurfaceView via the .lockCanvas() call.
Some solutions I've tried:
I've tried implementing this solution in my SurfaceView's Thread.run(), but the issue I believe is when the BitmapDrawable is converted to a Bitmap... it loses the tiling properties.
canvas = mSurfaceHolder.lockCanvas(null);
BitmapDrawable TileMe = new BitmapDrawable(BitmapFactory.decodeResource(getResources(), R.drawable.editor_graph));
TileMe.setTileModeX(Shader.TileMode.REPEAT);
TileMe.setTileModeY(Shader.TileMode.REPEAT);
Bitmap b = TileMe.getBitmap();
canvas.drawBitmap(b, 0, 0, null);
If I use the Canvas.drawBitmap method that takes a destination RectF as a parameter, it looks like the bitmap will be tiled to fill the RectF... but how do I declare a RectF reliably that fills the entire view area?
Setting the Activities background to the desired graph paper look also doesn't work, as the bitmap/canvas layout is opaque and blocks that from being seen.
Any ideas how to achieve this?
You have two easy solutions:
Either use a BitmapDrawable, but instead of extracting the Bitmap, just call BitmapDrawable.draw(Canvas). Don't forget to set the drawable's bounds to fill your drawing area.
Create a Paint with a BitmapShader and draw a rectangle with it (this is basically what BitmapDrawable does).
I'm sure there is a way to get a tiled effect using a SurfaceView. Unfortunately, it looks like you can't use the BitmapDrawable with a canvas. So you would probably have to implement you own custom tiling method by creating your own series of Rect's on the Canvas and drawing a scaled bitmap to each one.
It honestly wouldn't be that hard. Just get the width/height of the view, and create an array of Rect's based on this data that you will draw the Bitmap to.
Alternatively, if you don't need to make modifications to the actual tiled background on the fly, just draw it as a background and draw the SurfaceView on top of it. That post you linked provided multiple solutions to tiling a BitmapDrawable that you could implement.
I have several bitmaps (game sprites) which I'd like to draw into another bitmap, however each non-transparent pixel of the source bitmap should be drawn using a single color, ignoring the original pixel color of the source. Basically, I'm trying to use the sprite as a "stamp" of a single color to be drawn into the destination bitmap.
I believe I should be using canvas.drawBitmap (Bitmap bitmap, Matrix matrix, Paint paint), however I'm not exactly sure how I should initialize the paint object. Is this approach correct?
You don't need to perform as many steps as Romain Guy suggests, just initialize your paint with the desired color, and use Paint.setColorFilter() with PorterDuff.Mode.SRC_ATOP
myPaint.setColorFilter(new PorterDuffColorFilter(myColor, PorterDuff.Mode.SRC_ATOP));
If your destination bitmap is transparent, draw all your sprites inside that bitmap normally (you can use a null Paint.) Then, draw a filled rectangle that covers the entire bitmap, using the Porter-Duff xfermode called SrcIn (Source In.)