Can someone explain what the rect does in: canvas.drawBitmap(bmp,scr ,dst ,null);
Because I have tried and tried to make any sense of this but I simply don't understand what the two rectangles does.
My goal is to display a portion the bitmap instead of the whole image.
//Simon
Rect src = new Rect(0, 0, 50, 50);
Rect dst = new Rect(50, 50, 200, 200);
canvas.drawBitmap(originalBitmap, src, dst, null);
This code specifies that you want to copy a rectangle with the dimensions 50 width / 50 height of the source starting at position 0x 0y, and draw into the destination bitmap starting at position 50x / 50y and occupy it until 200x 200y - therefore stretching a bit - because as the source is only 50 pixels long, to stretch to 200x and 200y the copy will end up with the size 150width / 150 height.
The Android documentation seems to explain this method quite well.
drawBitmap Documenation
From reading the documentation it appears you can do what you want by specifying a source Rect, which will be the rectangle(subset) from the original bitmap, and it will then be translated into the dest Rectangle.
Bitmap picture; //Assume this is a 1024x768 image and has been initialized.
#Override
public void onDraw(Canvas canvas){
//To Draw only the top left corner of the image
Rect src = new Rect(0,0,512,368);
Rect dest = new Rect(0,0,512,368);
canvas.drawBitmap(picture, src, dest, null);
}
Related
I need to increase the size of a bitmap in Android, like in this image:
Basically, the user save the Image1. Then, the user can open again Image1 but I need that the Image2 (that is just a white rectangle) is added to the top of the Image1. So, I need to create another image, that is the Image1 plus another image.
How can I do that?
However, I just need to "increase" the Image1 size, so if there's another way to do that please let me know.
Thanks a lot
Since you only need the rectangle on top you can do this, but replace drawRect by some drawBitmap if you want to draw another image on top.
Bitmap i1 = //load the one
int w = i1.getWidth(), h = i1.getHeight();
Bitmap i3 = Bitmap.createBitmap(i1.getConfig(), w, h + 200); //200 will be the white
Canvas surface = new Canvas(i3);
Paint white = new Paint();
white.setColor(Color.WHITE);
surface.drawRect(0, 0, 200, w, white);
surface.drawBitmap(i1, 0, 200, w, h, white);
About increasing height, you can do this with the BitmapConfig.Options, but that will streth the result to match your proportions.
I have bitmap that need to draw to canvas. The image is of a fixed size, but the canvas will change according to the user's screen size and density (bitmap coule be larger/smaller than the canvas).
I need to draw the bitmap to canvas scaling all the way into the canvas size (without distorting the image), I have done the code as below but the bitmap still filling only a portion of the screen.
Rect dest = new Rect(0, 0, drawCanvas.getWidth(), drawCanvas.getHeight());
Paint paint = new Paint();
paint.setFilterBitmap(true);
drawCanvas.drawBitmap(canvasBitmap, null, dest, paint);
May I know if anybody can shed light on a good solution? Thanks.
This example is in javascript but it should still help you out scale an image
jsFiddle : https://jsfiddle.net/CanvasCode/7oghuwe2/3/
javascript
var canvas1 = document.getElementById('canvas1');
var context1 = canvas1.getContext('2d')
var canvas2 = document.getElementById('canvas2');
var context2 = canvas2.getContext('2d');
var image1 = new Image();
image1.src = "http://media.giphy.com/media/iNk83OBPzlA8o/giphy.gif";
image1.onload = function () {
context1.fillStyle = "#F00";
context1.fillRect(0, 0, canvas1.width, canvas1.height);
context2.fillStyle = "#00F";
context2.fillRect(0, 0, canvas2.width, canvas2.height);
ratio(context1, canvas1, image1);
ratio(context2, canvas2, image1);
}
function ratio(context1, canvas1, image1) {
var imageRatio = image1.width / image1.height;
var newHeight = canvas1.width / imageRatio;
var newWidth = canvas1.height * imageRatio;
var heightDiff = newHeight - canvas1.height;
var widthDiff = newWidth - canvas1.width;
if (widthDiff >= heightDiff) {
context1.drawImage(image1, 0, 0, canvas1.width, canvas1.width / imageRatio);
} else {
context1.drawImage(image1, 0, 0, canvas1.height * imageRatio, canvas1.height);
}
}
Basically you need to calculate what the width would be if you scaled the image by the canvas height and what the height would be if you scale the image by the canvas width, and which ever is smaller, then you scale by that dimension.
The reason why it might not work for you might be because the function drawBitmap() ignores the density of the bitmap. The following is from the documentation.
public void drawBitmap (Bitmap bitmap, Rect src, Rect dst, Paint
paint)
This function ignores the density associated with the bitmap. This is
because the source and destination rectangle coordinate spaces are in
their respective densities, so must already have the appropriate
scaling factor applied.
What you could do is use public void drawBitmap (Bitmap bitmap, Matrix matrix, Paint paint) instead. First you need to map the source Matrix with the desination Matrix. You do this via Matrix.setRectToRect() or Matrix.setPolyToPoly(). This will give you an accurate mapping. Just make sure you map them correctly, otherwise things will be distorted.
For more info refer here: What code should I use with 'drawMatrix.setPolyToPoly' to manipulate and draw just a rectangular part of a bitmap, rather than the entire bitmap?
The mentioned class has got the following method:
protected void drawCompass(Canvas canvas, float bearing) {
int offset = Math.max(canvas.getHeight(), canvas.getWidth()) / 8;
Rect r = new Rect(0, 0, 2*offset, 2*offset);
canvas.drawBitmap(compassBase, null, r, paint);
canvas.rotate(-bearing, offset, offset);
canvas.drawBitmap(compassArrow, null, r, paint);
}
Link to the complete src: MyLocationOverlay
There they create a Rect r witch specifies where the both Bitmaps should be drawn on the canvas.
The java doc of drawBitmap says :"Draw the specified bitmap, scaling/translating automatically to fill the destination rectangle. If the source rectangle is not null, it specifies the subset of the bitmap to draw. "
Because both Bitmaps use the same Rect r and because they both are automatically scaled to fit the Rect, why is the result a perfect Compass when I activate the compass in the MapView.
To my mind the result should be crap, because the arrow of the compass is also scaled to fit the Rect.
So where is the error in reasoning?
They are scaled using the same proportion, not to absolute size. To answer your question, the canvas is drawn on using the bitmap as reference - think of it like a painter and a canvas painting one image on top of the other using two photo images as reference.
I'm doing my own pixel calculations for drawing on the screen, and have a sprite bitmap (4x2 images in one file). Each image is 100x100, and the overall file is 400x200. Using the following method my drawing is not pulling the right section of the bitmap, and the placement on the scren isn't quite right:
public void drawBitmap(Bitmap bitmap, Rect src, RectF dst, Paint paint)
Since: API Level 1
Draw the specified bitmap, scaling/translating automatically to fill
the destination rectangle. If the source rectangle is not null, it
specifies the subset of the bitmap to draw.
Note: if the paint contains a maskfilter that generates a mask which
extends beyond the bitmap's original width/height (e.g.
BlurMaskFilter), then the bitmap will be drawn as if it were in a
Shader with CLAMP mode. Thus the color outside of the original
width/height will be the edge color replicated.
This function ignores the density associated with the bitmap. This is
because the source and destination rectangle coordinate spaces are in
their respective densities, so must already have the appropriate
scaling factor applied.
Parameters
bitmap > The bitmap to be drawn
src > May be null. The subset of the bitmap to be drawn
dst > The rectangle that the bitmap will be scaled/translated to fit into
paint > May be null. The paint used to draw the bitmap
Rect source = new Rect();
source.left = (this.currentFrame % 4) * 100;
source.right = source.left + 100;
source.top = (this.currentFrame / 4) * 100;
source.bottom = source.top + 100;
Rect dest = new Rect();
dest.top = (int) top;
dest.left = (int) left;
dest.right = dest.left + 100;
dest.bottom = dest.top + 100;
// draw current frame onto canvas
//canvas.drawBitmap(pics[this.currentFrame], left, top, painter);
canvas.drawBitmap(pics[0], source, dest, painter);
The documentation explicity says densities are ignored, but why is my image being scaled?
As per Renard
How exactly are you loading pics[0]? Have you tried getResources().openRawResource(imageId)?
This solved my problem.
I am trying to build a Magnify tool in my Android app. For this, I have an ImageView, which I converted to Bitmap (with some zoom/scale factor).
imageView.setDrawingCacheEnabled(true);
Bitmap drawingCache = imageView.getDrawingCache(true);
Matrix matrix = new Matrix();
matrix.postScale(5, 5);
Bitmap viewCapture = Bitmap.createBitmap(drawingCache, 0, 0,
drawingCache.getWidth(),
drawingCache.getHeight(),
matrix, true);
imageView.setDrawingCacheEnabled(false);
Now, I am drawing this Bitmap image "viewCapture" to my canvas. Here, I want only portion of the image to be rendered on the canvas.
I tried using approaches: "setRectToRect() on Matrix", "canvas.drawBitmap(bitmap, src, dst, paint)". But, didn't work out appropriately.
Would using SurfaceViews be helpful? Has anyone come across this situation? Please post your thoughts/ideas.
Why not just use the following?
Canvas.drawBitmap(Bitmap bitmap, Rect src, RectF dst, Paint paint)
src corresponds to which region of the bitmap you want to draw and dst says where you want the bitmap drawn. You can read more about it here: http://developer.android.com/reference/android/graphics/Canvas.html
When I do that, I get a smaller image of the bitmap, instead of cropped image. Following is the snippet I have used.
Canvas c = holder.lockCanvas();
c.drawRGB(10, 10, 10);
Rect src = new Rect((int)x - _image.getWidth(), (int) y - _image.getHeight(), (int)x + _image.getWidth(), (int) y + _image.getHeight());
RectF dst = new RectF((int)x - 50, (int) y - 50, (int)x + 50, (int) y + 50);
c.drawBitmap(_image, src, dst, null);
holder.unlockCanvasAndPost(c);