I am trying to blend two images the same way photoshop or paint.net blend them, with different blend modes like Difference, Multiply, Additive, Color Burn, Glow, etc.
I have found that PorterDuff.Mode works quite well, but it lacks blending effects ( it only has Add, Multiply, screen) is there a way to get a bigger range of blend modes? Is there a way to edit the android.graphics.PorterDuff; library to get more blend modes?
Any ideas?
For example:
THIS
turns into this:
Result
This is the porterduff code im using btw:
private static Bitmap Result(Bitmap bottomImage, Bitmap topImage){
int sizex = bottomImage.getWidth();
int sizey = bottomImage.getHeight();
Paint paint = new Paint();
Bitmap imageBitmap = Bitmap.createBitmap(sizex, sizey , Bitmap.Config.ARGB_8888);
Canvas comboImage = new Canvas(imageBitmap);
comboImage.drawBitmap(bottomImage, 0f, 0f, paint);;
PorterDuff.Mode mode = PorterDuff.Mode.MULTIPLY;//Porterduff MODE
paint.setXfermode(new PorterDuffXfermode(mode));
Bitmap ScaledtopImage = Bitmap.createScaledBitmap(topImage, sizex, sizey, false);
comboImage.drawBitmap(ScaledtopImage, 0f, 0f, paint);
return imageBitmap;
}
I'm not really an expert on image processing but PorterDuff has some blending modes, namely darken, lighten, multiply, screen and overlay. You can then use the in, atop, xor, etc to get the selection you want of the blended sections.
http://ssp.impulsetrain.com/porterduff.html
https://developer.android.com/reference/android/graphics/PorterDuff.Mode
Related
I am preparing a chess game and I have to declare many ImageViews Buttons dynamically.
However, my friends said that it will not support other screen sizes, but I heard about DisplayMetrics code; we can get the screen width and height through code only.
Well I am using different drawables for different screen sizes. Can I release my application in google playstore like this?
You can do it however you feel better, but using xml files would result in less code to write, to maintain and to execute at runtime.
So, i'd go the standard way (xml files).
You can still use the programmatic way, but then you have to mess with getWidth, getHeight and multiply by the density scale factor, ... you have to do some math!!
This could be done without XML, but i would use a canvas for chess.
Maybe something like this:
private Paint createChessrBoard(int size)
{
Bitmap bitmap = Bitmap.createBitmap(size* 2, size* 2, Bitmap.Config.ARGB_8888);
Paint fill = new Paint(Paint.ANTI_ALIAS_FLAG);
fill.setStyle(Paint.Style.FILL);
fill.setColor(0x22000000);
Canvas canvas = new Canvas(bitmap);
Rect rect = new Rect(0, 0, size, size);
canvas.drawRect(rect, fill);
rect.offset(size, size);
canvas.drawRect(rect, fill);
Paint paint = new Paint(Paint.ANTI_ALIAS_FLAG);
paint.setShader(new BitmapShader(bitmap, BitmapShader.TileMode.REPEAT, BitmapShader.TileMode.REPEAT));
return paint;
}
You can use this to get the devices DPI
int dpi = getResources().getDisplayMetrics().density;
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 an application which takes picture from camera .And normally this pictures have either rectangle shapes or square shapes.But due to make these pictures circular in shape i limited the shape to only square.So now my problem is to make this square picture into a circular shape having radius of half of width or height.And the clipped part should be removed from the picture.
Its same like making a circle from the square which touches midpoint of all of the faces of square.
I don't have any experience with canvas or other in built drawing functions.
For example i have square at first now i want to make image circular such that parts pointed by arrow should get clipped from image.
Note:as i have to work with camera images .quality is crucial factor.So please suggest the possible ways that will not affect the pixel quality and other important factors.
You can do it by masking the image with your desired shape, see this post for detailed info.
example code:
Resources resources = context.getResources();
Bitmap original = BitmapFactory.decodeResource(resources,R.drawable.original);
Bitmap mask = BitmapFactory.decodeResource(resources,R.drawable.mask);
Bitmap result = Bitmap.createBitmap(mask.getWidth(), mask.getHeight(), Config.ARGB_8888);
Canvas c = new Canvas(result);
Paint paint = new Paint(Paint.ANTI_ALIAS_FLAG);
paint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.DST_IN));
c.drawBitmap(original, 0, 0, null);
c.drawBitmap(mask, 0, 0, paint);
paint.setXfermode(null);
imageView.setImageBitmap(result);
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.
I'm trying to draw the contour of my drawable,
I tried to use Blur, as in this page:
How to make glow effect around a bitmap?
Its effect is not what I want,
I want a "solid" contour,
not blurred.
anyone knows how?
There is no outline type filter or mask that I can find, while blur and shadow mask are not very strong. Hence you could create your own effect by using color filter and scale. This example would create a red contour
ColorFilter filter;
filter = new PorterDuffColorFilter(0xFFFF0000, PorterDuff.Mode.SRC_IN);
paint = new Paint(Paint.ANTI_ALIAS_FLAG);
paint.setColorFilter(filter);
canvas.save();
canvas.scale(1.1f, 1.1f,imageCenterX , imageCenterY);
canvas.drawBitmap(image, imageX, imageY, paint);
canvas.restore();
canvas.drawBitmap(image, imageX, imageY, null);
It is fast enough for a game frame animation, I've tested it.