Canvas.DrawBitmap unexpected result(BUG or strange behaviour) Xamarin Android - android

So i have an problem with method of Canvas.DrawBitmap(), that draws unexpected result.
Lets see my example:
Source image
I have two cases(just for test):
I want to draw Red rectangle from 0,0 and give for him size 1/4 of image,also i want to draw this bitmap in same size(1/4) and put to Bottom.Right place.
Draw again Red rectangle with same conditions(starts from Top.Left(0,0) and size 1/4 of image) and draw part of bitmap and shows as Rectangle with 1/4 size(Bottom.Right).
Case #1
i'm doing this:
//source imageview
Source.SetImageResource(Resource.Drawable.lena30);
//bitmap
bt = ((BitmapDrawable)Source.Drawable).Bitmap.Copy(Bitmap.Config.Argb8888, true);
//second imageview, where i fill result
Draw.SetImageBitmap(bt);
can = new Canvas(bt);
Paint paint = new Paint();
paint.Color = Color.Red;
paint.SetStyle(Paint.Style.Fill);
//draw Red Rect with 1/4 size and locate Top.Left
can.DrawRect(0,0,bt.Width/2,bt.Height/2,paint);
//redraw new bitmap(all subset) and locate to Bottom.Right with 1/4 size
can.DrawBitmap(bt, null, new Rect(bt.Width/2, bt.Height / 2, bt.Width, bt.Height), null);
and the result is :
Case #2
same,but getting now part of bitmap(not full subset of bitmap):
//source imageview
Source.SetImageResource(Resource.Drawable.lena30);
//bitmap
bt = ((BitmapDrawable)Source.Drawable).Bitmap.Copy(Bitmap.Config.Argb8888, true);
//second imageview, where i fill result
Draw.SetImageBitmap(bt);
can = new Canvas(bt);
Paint paint = new Paint();
paint.Color = Color.Red;
paint.SetStyle(Paint.Style.Fill);
//draw Red Rect with 1/4 size and locate Top.Left
can.DrawRect(0,0,bt.Width/2,bt.Height/2,paint);
//redraw new bitmap(not full,only part of Source Rectangle) and locate to Bottom.Right with 1/4 size
can.DrawBitmap(bt, new Rect(bt.Width/2,0,bt.Width,bt.Height), new Rect(bt.Width/2, bt.Height / 2, bt.Width, bt.Height), null);
So i cant understand,why that happens?(Why image no scaling to fit size and duplicate Rectangles!?).
Any ideas? Thanks!

The issue is that you're drawing the bt Bitmap onto itself, which is causing it to recursively draw until it hits a minimum size limit. It'll take a little reworking of your code, but you'll need to create an intermediate Bitmap and Canvas on which to do your drawing, then set that Bitmap on the target ImageView.
Source.SetImageResource(Resource.Drawable.lena30);
bt = ((BitmapDrawable) Source.Drawable).Bitmap.Copy(Bitmap.Config.Argb8888, true);
Paint paint = new Paint();
paint.Color = Color.Red;
paint.SetStyle(Paint.Style.Fill);
Canvas canSource = new Canvas(bt);
canSource.DrawRect(0, 0, bt.Width / 2, bt.Height / 2, paint);
Bitmap btDraw = Bitmap.CreateBitmap(bt.Width, bt.Height, Bitmap.Config.Argb8888);
Canvas canDraw = new Canvas(btDraw);
canDraw.DrawBitmap(bt, null, new Rect(0, 0, bt.Width, bt.Height), null);
canDraw.DrawBitmap(bt, null, new Rect(bt.Width / 2, bt.Height / 2, bt.Width, bt.Height), null);
Draw.SetImageBitmap(btDraw);
NB: I've never used Xamarin, so please forgive any syntax errors in my attempted translation.

Related

Android Cover Flow with image shadow effect

I want to implement cover flow as below
I have tried Carousel, but its not the same thing. Did some google search was not able to find something even near to the cover flow implemented in given example.
Definitely have a look at this, FancyCoverFlow.
There is a demo app for it in the Play store as well that shows the reflection requirement you'd like.
have you tried this:
blog post
public Bitmap getRefelection(Bitmap image) {
// The gap we want between the reflection and the original image
final int reflectionGap = 0;
// Get you bit map from drawable folder
Bitmap originalImage = image;
int width = originalImage.getWidth();
int height = originalImage.getHeight();
// This will not scale but will flip on the Y axis
Matrix matrix = new Matrix();
matrix.preScale(1, -1);
// Create a Bitmap with the flip matix applied to it.
// We only want the bottom half of the image
/*if(bitmapWithReflection!=null && !bitmapWithReflection.isRecycled()){
bitmapWithReflection.recycle();
bitmapWithReflection=null;
}*/
Bitmap reflectionImage = Bitmap.createBitmap(originalImage, 0,
height / 2, width, height / 2, matrix, false);
// Create a new bitmap with same width but taller to fit reflection
Bitmap bitmapWithReflection = Bitmap.createBitmap(width,(height + height / 2), Config.ARGB_8888);
// Create a new Canvas with the bitmap that's big enough for
// the image plus gap plus reflection
Canvas canvas = new Canvas(bitmapWithReflection);
// Draw in the original image
canvas.drawBitmap(originalImage, 0, 0, null);
//Draw the reflection Image
canvas.drawBitmap(reflectionImage, 0, height + reflectionGap, null);
// Create a shader that is a linear gradient that covers the reflection
Paint paint = new Paint();
LinearGradient shader = new LinearGradient(0,
originalImage.getHeight(), 0, bitmapWithReflection.getHeight()
+ reflectionGap, 0x40ffffff, 0x00ffffff, TileMode.CLAMP);
// Set the paint to use this shader (linear gradient)
paint.setShader(shader);
// Set the Transfer mode to be porter duff and destination in
paint.setXfermode(new PorterDuffXfermode(Mode.DST_IN));
// Draw a rectangle using the paint with our linear gradient
canvas.drawRect(0, height, width, bitmapWithReflection.getHeight()
+ reflectionGap, paint);
if(originalImage!=null && originalImage.isRecycled()){
originalImage.recycle();
originalImage=null;
}
if(reflectionImage!=null && reflectionImage.isRecycled()){
reflectionImage.recycle();
reflectionImage=null;
}
return bitmapWithReflection;
}
Have you gone through the Android Coverflow which is bit different form the Carousel which you want.
I made cover flow widget which is not dependent on gallery.
You can find it here. I will add some samples later.
http://applm.github.io/ma-components/

Android bitmap with border

I have this function, with this function I can show an image with a little rotation.
I'm trying to display a white border arround the bitmap.
Matrix m = new Matrix();
m.postRotate( rotation, center.x, center.y );
m.postTranslate( ( position.x - center.x ) - xOffset , position.y - ( center.x ) );
// set the current position to the updated position
positionMatrix.set( m );
renderAnimation();
c.drawBitmap( this.bitmap , positionMatrix, paint );
I'm trying to add the white border with this function: reference: stackoverflow border
RectF targetRect = new RectF(left+10, top+10, left + scaledWidth, top + scaledHeight);
Bitmap dest = Bitmap.createBitmap(this.bitmap.getWith() +20, this.bitmap.getHeight() +20, this.bitmap.getConfig());
Canvas canvas = new Canvas(dest);
canvas.drawColor(Color.WHITE);
canvas.drawBitmap(this.bitmap, null, targetRect, null);
c.drawBitmap( this.bitmap , positionMatrix, paint );
But, not works, can some help me
I think you should follow these steps:
Create a bitmap that width = yourImageWidth + boderThick and height= yourImageHeight + boderThick
Canvas draw a White rectangle (draw your background first)
Canvas draw your image (you need to center your image)
Maybe you made a mistake when calculating the side, or draw in a wrong order. Remember to use the same canvas when drawing. In your code i see you use c.draw and canvas.draw... That may cause the problem.
Refer to the code below:
Paint paint = new Paint();
paint.setColor(Color.WHITE);
paint.setStrokeWidth(3);
canvas.drawRect(0, 0, 200, 200, paint);//draw your bg
canvas.drawBitmap(bitmap, 20, 20, paint);//draw your image on bg
Sorry, i don't have much time to check your calculated size. I hope this can help.

Canvas.drawBitmap() ignoring the tile mode of the paint

I want to draw subparts of a bitmap, but at a different size. If the size is bigger than the source rectangle in the bitmap, then I want that section of the bitmap to tile to fill the destination area. However, instead of getting tiled they are getting stretched.
I set up all the variables as follows:
Bitmap b = BitmapFactory.decodeResource(getResources(), R.drawable.image);
Rect srcRect = ...
Rect dstRect = ...
Paint p = new Paint();
p.setShader(new BitmapShader(b, Shader.TileMode.REPEAT, Shader.TileMode.REPEAT));
And then in the draw() method I draw as follows:
canvas.drawBitmap(b, srcRect, dstRect, p);
What am I doing wrong? How should I draw srcRect to dstRect such that my subpart of the bitmap gets tiled?
I discovered the problem, put succinctly: shaders on bitmaps don't work that way.
To draw a rectangle tiled with a specific Bitmap you have to use Canvas.drawRect(), with a Paint that has a BitmapShader. However, Android dev can't ever be as simple as that.
First you have to cut out the srcRect to a separate Bitmap (caching this somewhere since I don't think this is a cheap operation), like so:
Bitmap t = Bitmap.createBitmap(b, srcRect.left, srcRect.top, srcRect.right-srcRect.left, srcRect.bottom-srcRect.top);
Then you have to create the Paint and the BitmapShader:
BitmapShader bs = new BitmapShader(t, TileMode.REPEAT, TileMode.REPEAT);
Paint p = new Paint();
p.setShader(bs);
Then you can finally draw to the destination rectangle, but first you have to set up a translation matrix for the shader or else it won't start from the correct place and might bugger up completely if your tile mode is CLAMP:
Matrix m = new Matrix();
m.postTranslate(dstRect.left, dstRect.right);
p.getShader().setMatrix(m);
canvas.drawRect(dstRect, p);

android - adding a String over a Drawable image?

I'm trying to add a String to a Drawable image. I'm currently not using a Panel to draw and I'd like to keep it that way. Any ideas or do I need to invoke an onDraw() method?
My image is showing up with this code:
Drawable image = getResources().getDrawable(tile_types[tileType]);
setImageDrawable(image);
I'd like to add a String over this image.
Thanks.
Sam's answer was my starting point, but the image didn't show up, only the text (I use it on a Google Map). Finally I got it working with a LayerDrawable. Here is my solution:
private Drawable createMarkerIcon(Drawable backgroundImage, String text,
int width, int height) {
Bitmap canvasBitmap = Bitmap.createBitmap(width, height,
Bitmap.Config.ARGB_8888);
// Create a canvas, that will draw on to canvasBitmap.
Canvas imageCanvas = new Canvas(canvasBitmap);
// Set up the paint for use with our Canvas
Paint imagePaint = new Paint();
imagePaint.setTextAlign(Align.CENTER);
imagePaint.setTextSize(16f);
// Draw the image to our canvas
backgroundImage.draw(imageCanvas);
// Draw the text on top of our image
imageCanvas.drawText(text, width / 2, height / 2, imagePaint);
// Combine background and text to a LayerDrawable
LayerDrawable layerDrawable = new LayerDrawable(
new Drawable[]{backgroundImage, new BitmapDrawable(canvasBitmap)});
return layerDrawable;
}
Drawable image = getResources().getDrawable(tile_types[tileType]);
// Store our image size as a constant
final int IMAGE_WIDTH = image.getIntrinsicWidth();
final int IMAGE_HEIGHT = image.getIntrinsicHeight();
// You can also use Config.ARGB_4444 to conserve memory or ARGB_565 if
// you don't have any transparency.
Bitmap canvasBitmap = Bitmap.createBitmap(IMAGE_WIDTH,
IMAGE_HEIGHT,
Bitmap.Config.ARGB_8888);
// Create a canvas, that will draw on to canvasBitmap. canvasBitmap is
// currently blank.
Canvas imageCanvas = new Canvas(canvasBitmap);
// Set up the paint for use with our Canvas
Paint imagePaint = new Paint();
imagePaint.setTextAlign(Align.CENTER);
imagePaint.setTextSize(16f);
// Draw the image to our canvas
image.draw(imageCanvas);
// Draw the text on top of our image
imageCanvas.drawText("Sample Text",
IMAGE_WIDTH / 2,
IMAGE_HEIGHT / 2,
imagePaint);
// This is the final image that you can use
BitmapDrawable finalImage = new BitmapDrawable(canvasBitmap);
If your resulted text looks "angular" due to resizing, it's better to use TextPaint instead of plain Paint with these parameters:
TextPaint textPaint = new TextPaint(TextPaint.ANTI_ALIAS_FLAG | TextPaint.LINEAR_TEXT_FLAG);

Android Circular Gradient Alpha Mask

Is there a way to draw a circular gradient mask on a bitmap in Android? Trying to produce something similar to a foggy window. Click the window and a transparent circle shows up revealing whats behind the window. Prefferably using a gradient so the center of the circle is completely transparent and the further out from the center the less transparent. Is this possible?
I'm new to Android so any code samples would be appreciated.
Thanks.
private void drawFoggyWindowWithTransparentCircle(Canvas canvas,
float circleX, float circleY, float radius) {
// Get the "foggy window" bitmap
BitmapDrawable foggyWindow =
(BitmapDrawable) getResources().getDrawable(R.drawable.foggy_window);
Bitmap foggyWindowBmp = foggyWindow.getBitmap();
// Create a temporary bitmap
Bitmap tempBitmap = Bitmap.createBitmap(
foggyWindowBmp.getWidth(),
foggyWindowBmp.getHeight(),
Bitmap.Config.ARGB_8888);
Canvas tempCanvas = new Canvas(tempBitmap);
// Copy foggyWindowBmp into tempBitmap
tempCanvas.drawBitmap(foggyWindowBmp, 0, 0, null);
// Create a radial gradient
RadialGradient gradient = new android.graphics.RadialGradient(
circleX, circleY,
radius, 0xFF000000, 0x00000000,
android.graphics.Shader.TileMode.CLAMP);
// Draw transparent circle into tempBitmap
Paint p = new Paint();
p.setShader(gradient);
p.setColor(0xFF000000);
p.setXfermode(new PorterDuffXfermode(Mode.DST_OUT));
tempCanvas.drawCircle(circleX, circleY, radius, p);
// Draw tempBitmap onto the screen (over what's already there)
canvas.drawBitmap(tempBitmap, 0, 0, null);
}

Categories

Resources