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);
Related
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.
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.
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)?
I have a custom view that extends SurfaceView. I am drawing an image on the canvas. When the user touches a point on the canvas, i want to show a magnified view of the area around the touched co-ordinates. And preferably, as the finger moves around, i would like to update the magnified view's content accordingly.
I was wondering if the android platform supports such a functionality natively. If not, can one of you point me to a good example that can get me started or share ideas on how to implement it. I don't do much 2D or 3D graphics of this sort and am still trying to understand the Canvas and Matrix Classes to see what i can be use.
I searched the forum for a similar question but could not find any. So, pls don't flag me for asking a question that already exists.
And no - i am not using OpenGL-ES or any such 3rd party library (yet).
Thanks All.
To zoom the image you're drawing on the canvas:
Create a BitmapShader (using the bitmap of the image you're drawing), a Matrix and a Paint:
shader = new BitmapShader(bmp, TileMode.CLAMP, TileMode.CLAMP);
matrix = new Matrix();
shaderPaint = new Paint();
shaderPaint.setShader(shader);
On a touch event record the touch position (e.g. in a PointF):
zoomPos.x = event.getX();
zoomPos.y = event.getY();
...and set up the shader's matrix (I do this on each touch, there's probably a better way):
matrix.reset();
matrix.postScale(2f, 2f);
matrix.postTranslate(-zoomPos.x, -zoomPos.y);
shader.setLocalMatrix(matrix);
Then in the drawing code, draw a circle using the shader Paint.
canvas.drawCircle(zoomPos.x, zoomPos.y, size_of_the_circle, shaderPaint);
Edit
The two lines:
matrix.postScale(2f, 2f);
matrix.postTranslate(-zoomPos.x, -zoomPos.y);
Can be replaced with one:
matrix.postScale(2f, 2f, zoomPos.x, zoomPos.y);
This allows the scale factor to be changed without breaking the offset.
So this is what I have for a vignette style effect in Android (image is a Bitmap):
public void vignette() {
float radius = (float) (image.getWidth()/1.5);
RadialGradient gradient = new RadialGradient(image.getWidth()/2, image.getHeight()/2, radius, Color.TRANSPARENT, Color.BLACK, Shader.TileMode.CLAMP);
Canvas canvas = new Canvas(image);
canvas.drawARGB(1, 0, 0, 0);
final Paint paint = new Paint();
paint.setAntiAlias(true);
paint.setColor(Color.BLACK);
paint.setShader(gradient);
final Rect rect = new Rect(0, 0, image.getWidth(), image.getHeight());
final RectF rectf = new RectF(rect);
canvas.drawRect(rectf, paint);
paint.setXfermode(new PorterDuffXfermode(Mode.SRC_IN));
canvas.drawBitmap(image, rect, rect, paint);
}
This "works" but there are a couple of problems. First of all, this is not really a vignette, it's just a gradient so you can see bits of the black going nearly all the way to the center rather than feathering out closer to the edges.
The RadialGradient used also only allows for setting the radius of a circle rather than an ellipse. An ellipse would be able to more effectively match the dimensions of a non-square image than a circle.
The quality of the gradient is also not superb.
I'm trying to replicate the vignetteImage method from ImageMagick (I'm referring specifically to the php version). I have this code in PHP that produces the style of image that I want:
$im = new IMagick('city.png');
$im->vignetteImage($width/1.5, 350, 20, 20);
I've tried building ImageMagick with the NDK but have been unsuccessful in properly linking the various image libraries (I've only successfully built with gif support but no png, jpeg or tiff).
I've also attached an image comparing the two methods shown above. The image on the left was generated with ImageMagick through php and the image on the right was generated using the method shown above for Android.
If you look carefully at the image on left, tf uses exponential increase in Alpha (transparency) vs. image on right which is very linear.
Clearly Shader.TitleMode.CLAMP is a linear function. What you should do instead is use RadialGradient(float x, float y, float radius, int[] colors, float[] positions, Shader.TileMode tile) to define 10 or more points on the image with exponentially decreasing color values (black to transparent).
Alternatively, you can refer gallery 3d source for ICS gallery http://grepcode.com/file/repository.grepcode.com/java/ext/com.google.android/android-apps/4.0.1_r1/com/android/gallery3d/photoeditor/filters/VignetteFilter.java?av=h
I know this is an old discussion but it may help someone.
You can use AccelerateInterpolator to generate the points that Taranfx had mentioned and it will lock awesome.