How to efficiently resize image with antialias? - android

I try to resize an image like this:
aPaint.setAntiAlias(true); // Enabling this flag will cause all draw operations that support antialiasing to use it.
aPaint.setFilterBitmap(True); // enable bilinear sampling on scaled bitmaps. If cleared, scaled bitmaps will be drawn with nearest neighbor sampling, likely resulting in artifacts.
apaint.setDither(true); // Enabling this flag applies a dither to any blit operation where the target's colour space is more constrained than the source.
aCanvas.drawBitmap(aBitmap, aJSrcRect, aJDestRectf, apaint);
But I don't have a very good antialised image (it's antialiased, but not very good). Here is an image showing my problem
What can i do to increase the quality of the antialias under android ?

For antialias effect, you can try to create a Paint like this:
Paint paint= new Paint();
paint.setFlags(Paint.ANTI_ALIAS_FLAG);
paint.setAntiAlias(true);
paint.setFilterBitmap(true);
Finally apply paint on canvas with:
canvas.drawBitmap(mBitmap, 0.f, 0.f, paint)

Related

Porterduff Mode DST_IN drawing a rectangle around path

I'm attempting to draw a path, and then mask it with another path using the DST_IN Porterduff Mode.
Here's my block of code that does the drawing
int saveCount = canvas.saveLayer(
0, 0, canvas.getWidth(), canvas.getHeight(), null);
canvas.drawPath(mPath, mFillPaint);
mClipPaint = new Paint();
mClipPaint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.DST_IN));
canvas.drawPath(mClipPath, mClipPaint);
This does the masking but also has a rectangle around the path beyond which the masking doesn't work as seen below. The outer star is the original path and the blob is the masking path. You can see that the blob has a rectangular border beyond which masking doesn't work
As a side note, this only seems to work if hardware acceleration is enabled. Is this expected?

Punch a Transparent hole in my semi Black Canvas

I am trying to create a Black screen with a transparent Hole in the middle of the screen. Here is what i have tried.
#Override
public void draw(Canvas canvas)
{
Paint myPaint = new Paint();
myPaint.setColor(0xC0000000);
canvas.drawRect(mBlackRect, myPaint);
myPaint = new Paint();
myPaint.setColor(Color.TRANSPARENT);
myPaint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.CLEAR));
canvas.drawRect(mTransparentRect, myPaint);
}
The second paint, shows black color instead of transparent. How can i punch a transparent hole in MY SemiBlack Canvas?
you didn't save the canvas, try the code below
Paint myPaint = new Paint();
int sc = canvas.saveLayer(mBlackRect.left, mBlackRect.top,
mBlackRect.right, mBlackRect.bottom, myPaint,
Canvas.ALL_SAVE_FLAG);
myPaint.setColor(0xC0000000);
canvas.drawRect(mBlackRect, myPaint);
myPaint.setColor(Color.TRANSPARENT);
myPaint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.CLEAR));
canvas.drawRect(mTransparentRect, myPaint);
myPaint.setXfermode(null);
canvas.restoreToCount(sc);
You can not really "punch" a hole by "removing pixels" from something already drawn, at least not with a hardware layer. And if you use a software layer, it will be bad for performance.
What you want to do is draw your shape with an alpha mask applied to your paint. A mask will prevent some parts of the shape to be drawn on the canvas, like cutting a piece of paper and stick it on a wall before spreading the painting.
To apply an alpha mask to your paint, you first need to create a bitmap containing the "hole" shape (programmatically or by loading a custom image from resources), then create a BitmapShader from this bitmap with the proper Xfermode (depending if you want the transparent part in your mask bitmap to be cut out or the non-transparent part) and finally apply this shader to your paint before drawing the semitransparent rectangle or anything you want.
Be careful with performance: only create the Paint object once (do not allocate any object in onDraw() because this method gets called up to 60 times per second on the UI thread), and recreate the alpha mask bitmap only when the bounds of your View/Drawable change (if its dimensions depend on the View dimensions of course, otherwise you just create it once).
I'm sorry if I don't have time to give you ready-to-use code but I think you should find plenty of information about the technique I just described and you can start experimenting and figuring out the solution by yourself which is more rewarding I think ;)

How to Crop only face from an image in android?

I got a requirement to display only face from an image. But, I am trying to use only android native methods to implement this.
I have gone through the following link
Crop Image with face detection in android
But, the code mentioned in the above link is not working for all images.
Please guide me if anyone has already got the same requirement.
Thanks.
A face detection algorithm is never (and will never be) accurate. Even humans sometimes see the face of jezus in a toast. How can you expect computers to detect a face 100% correctly, if even the reference implementation (the human brain) contains bugs.
You should include a fallback scenario, when there is no (or more as one) face detected. Or do some quality check on the pictures before they are used.
You can use this rounded rectangle code with bigger corner radius to achieve a circle (recipe by Romain Guy):
BitmapShader shader;
shader = new BitmapShader(bitmap, Shader.TileMode.CLAMP, Shader.TileMode.CLAMP);
Paint paint = new Paint();
paint.setAntiAlias(true);
paint.setShader(shader);
RectF rect = new RectF(0.0f, 0.0f, width, height);
// rect contains the bounds of the shape
// radius is the radius in pixels of the rounded corners
// paint contains the shader that will texture the shape
canvas.drawRoundRect(rect, radius, radius, paint);

Android - Apply a bitmap texture to API drawing routines

I have a bitmap that spans the whole screen that will function as texture for a Path object that I need to draw to my canvas. I then have a background image that this textured path needs to be drawn on top of.
I tried using the PorterDuff modes, but nothing seemed to work correctly. I was having a hard time figuring out exactly how the PorterDuff modes act, because none of them seem to act the way I always thought they were supposed to function.
I've figured out a way to texture the path with this test code:
Paint paint = new Paint();
//draw the texture
canvas.drawBitmap(BitmapFactory.decodeResource(getResources(), R.drawable.texture),0,0,paint);
//construct the Path with an inverse even-odd fill
Path p = new Path();
p.setFillType(Path.FillType.INVERSE_EVEN_ODD);
p.addCircle(this.getHeight()/2, this.getWidth()/2, 200, Path.Direction.CCW);
//use CLEAR to remove inverted fill, thus showing only the originally filled section
paint.setXfermode(new PorterDuffXfermode(android.graphics.PorterDuff.Mode.CLEAR));
//draw path
canvas.drawPath(p, paint);
But I can't figure out how to then place that on top of a background image. Am I just using the PorterDuff modes wrong?
Maybe my questions could lead you to your solution:
The paint used in your drawPath call:
What is the paint style?
What is the paint stroke width?
What is the paint stroke/fill color?
If you are not using a stoke/fill color, but a texture instead, where is the call to the paint's setShader (using a BitmapShader)?

Android clipPath equivalent for hardware accelerated View

The only part of my app that is still software rendered is the rendering of one view where I need to draw a round bitmap. I'm using clipPath to clip the bitmap that I need to render to the round shape.
I understand that clipPath is not hardware accelerated, but I am looking for an algorithm that would allow me to provide the equivalent functionality using hardware acceleration.
Specifically I need to create a round clipping region of a source bitmap and have that rendered to my canvas.
If you have to use clipPath you could shut down the hardware acceleration as below.
<application
android:label="#string/application_name"
android:hardwareAccelerated="false">
And you also could control hardware acceleration among Application, Activity, Window and View layers. Detail information describes on this Hardware Acceleration article on Android Development web site.
You could try to this, though I am not sure it is hardware accelerated :
in onCreate :
create a paint (called bitmapPaint) that uses setXfermode :
http://developer.android.com/reference/android/graphics/Paint.html#setXfermode(android.graphics.Xfermode)
put an AvoidXfermode, also its deprecated, it work pretty well. Pass it the white color and target mode with a high tolerance (like 240)
in onLayout :
create a bitmap of the same size as your view
draw your circle inside on of its canvas, in white, using anti alias for a clean border
in onDraw :
draw the bitmap with the white circle in your paint canvas
now, draw your bitmap inside your paint canvas using the bitmapPaint you created in onCreate
The bitmap should be rendered inside the circle only.
If your bitmap does not change a lot, clip it once to the shape into a new bitmap, and then draw the clipped bitmap in your onDraw.
Here is an example how to clip a circle from a source bitmap
Bitmap bitmap = Bitmap.createBitmap(source.getWidth(), source.getHeight(), Bitmap.Config.ARGB_8888);
Paint paint = new Paint(Paint.ANTI_ALIAS_FLAG);
Canvas canvas = new Canvas(bitmap);
paint.setColor(Color.RED);
// Draw your shape here
canvas.drawCircle(cx, cy, radius, paint);
paint.setXfermode(new PorterDuffXfermode(Mode.SRC_IN));
canvas.drawBitmap(sourceBitmap, 0, 0, paint);

Categories

Resources