How to mask Bitmap with LinearGradient shader properly? - android

I'm trying to mask Bitmap with gradient alpha at bottom. Gradient size are fixed and independed of Bitmap size. But it draws incorrect: bottom of gradient at top, than top.
What's wrong?
There is sample code:
final int GRADIENT_HEIGHT = 32;
public Bitmap addGradient(Bitmap src) {
int w = src.getWidth();
int h = src.getHeight();
Bitmap overlay = Bitmap.createBitmap(w, h, Bitmap.Config.ARGB_8888);
Canvas canvas = new Canvas(overlay);
canvas.drawBitmap(src, 0, 0, null);
Paint paint = new Paint();
LinearGradient shader = new LinearGradient(0, 0, 0, GRADIENT_HEIGHT, 0xFFFFFFFF, 0x00FFFFFF, TileMode.REPEAT);
paint.setShader(shader);
paint.setXfermode(new PorterDuffXfermode(Mode.DST_IN));
canvas.drawRect(0, h - GRADIENT_HEIGHT, w, h, paint);
return overlay;
}
Thanks!

Change your LinearGradient to this:
LinearGradient shader = new LinearGradient(0, h - GRADIENT_HEIGHT, 0, h, 0xFFFFFFFF, 0x00FFFFFF, Shader.TileMode.CLAMP);

Related

Using multiple porterduffmodes with bitmap

I have a problem trying to achieve particular blending situation:
Create canvas
Draw raw bitmap
Draw rect with color and multiply mode
Draw another rect with color and lighten mode
Following code is working solution with iOS:
+ (UIImage *)compositeBackgroundImageFromImage:(UIImage *)image
{
if (image.size.width < 1 || image.size.height < 1)
return nil;
UIColor *multiplyColor = [UIColor blueColor];
UIColor *lightenColor = [UIColor cyanColor];
UIGraphicsBeginImageContextWithOptions(image.size, YES, [UIScreen mainScreen].scale);
CGContextRef c = UIGraphicsGetCurrentContext();
CGRect rect = CGRectMake(0, 0, image.size.width, image.size.height);
[image drawAtPoint:CGPointZero];
CGContextSetFillColorWithColor(c, multiplyColor.CGColor);
CGContextSetBlendMode(c, kCGBlendModeMultiply);
CGContextFillRect(c, rect);
CGContextSetFillColorWithColor(c, lightenColor.CGColor);
CGContextSetBlendMode(c, kCGBlendModeLighten);
CGContextFillRect(c, rect);
UIImage *result = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
return result;
}
And this is corresponding with Java with Android Universal Image Loader with custom BitmapDisplayer:
.displayer(new BitmapDisplayer() {
#Override
public void display(Bitmap bitmap, ImageAware imageAware,
LoadedFrom loadedFrom) {
int w = bitmap.getWidth();
int h = bitmap.getHeight();
if (w > 0 && h > 0) {
int multiplyColor = // color here
int lightenColor = // color here
Paint p = new Paint(Paint.ANTI_ALIAS_FLAG);
p.setFilterBitmap(true);
Bitmap bm = Bitmap.createBitmap(w, h,
Config.ARGB_8888);
Canvas c = new Canvas(bm);
c.drawBitmap(bitmap, 0, 0, p);
p.setColorFilter(new PorterDuffColorFilter(
multiplyColor, Mode.MULTIPLY));
c.drawRect(0, 0, w, h, p);
p.setColorFilter(new PorterDuffColorFilter(
lightenColor, Mode.LIGHTEN));
c.drawRect(0, 0, w, h, p);
((ImageView) imageAware.getWrappedView())
.setImageBitmap(bm);
}
}
The result is just a mess far away from iOS.
Thanks.
After couple of different tries ended up using shader to draw 3 rectangles. The visual look seems to be very close, if someone knows if this does exact same than the iOS code that would be nice.
int w = bitmap.getWidth();
int h = bitmap.getHeight();
if (w > 0 && h > 0) {
int multiplyColor = // get color
int lightenColor = // get color
Paint p = new Paint(Paint.ANTI_ALIAS_FLAG);
BitmapShader shader = new BitmapShader(bitmap,
TileMode.CLAMP, TileMode.CLAMP);
p.setShader(shader);
Bitmap bm = Bitmap.createBitmap(w, h,
Config.ARGB_8888);
Canvas c = new Canvas(bm);
c.drawRect(0, 0, w, h, p);
p.setColorFilter(new PorterDuffColorFilter(
multiplyColor, Mode.MULTIPLY));
c.drawRect(0, 0, w, h, p);
p.setColorFilter(new PorterDuffColorFilter(
lightenColor, Mode.LIGHTEN));
c.drawRect(0, 0, w, h, p);
((ImageView) imageAware.getWrappedView())
.setImageBitmap(bm);
}

thumbnail reflection with Drawable instead of Bitmap

working on generate reflection for thumbnail in recent app menu
the code works very well with CM10 but since update to CM11 (kitkat) they moved to use Drawable instead of Bitmap for reduce memory usage
https://github.com/CyanogenMod/android_frameworks_base/commit/9926272f32868c858b24b45e048210cf3515741e
here should add the changes:
https://github.com/CyanogenMod/android_frameworks_base/blob/1e3c4a9e687b19cd7837fed51eb25e92a4f691c1/packages/SystemUI/src/com/android/systemui/recent/RecentsPanelView.java#L509
here my code:
final int reflectionGap = 4;
int width = thumbnail.getWidth();
int height = thumbnail.getHeight();
Matrix matrix = new Matrix();
matrix.preScale(1, -1);
Bitmap reflectionImage = Bitmap.createBitmap(thumbnail, 0, height * 2 / 3, width, height/3, matrix, false);
Bitmap bitmapWithReflection = Bitmap.createBitmap(width, (height + height/3), Config.ARGB_8888);
Canvas canvas = new Canvas(bitmapWithReflection);
canvas.drawBitmap(thumbnail, 0, 0, null);
Paint defaultPaint = new Paint();
canvas.drawRect(0, height, width, height + reflectionGap, defaultPaint);
canvas.drawBitmap(reflectionImage, 0, height + reflectionGap, null);
Paint paint = new Paint();
LinearGradient shader = new LinearGradient(0, thumbnail.getHeight(), 0,
bitmapWithReflection.getHeight() + reflectionGap, 0x70ffffff, 0x00ffffff,
TileMode.CLAMP);
paint.setShader(shader);
paint.setXfermode(new PorterDuffXfermode(Mode.DST_IN));
canvas.drawRect(0, height, width,
bitmapWithReflection.getHeight() + reflectionGap, paint);
h.thumbnailViewImage.setImageBitmap(bitmapWithReflection);
my question is :
how i can make this code works with Drawable instead of Bitmap
thanks
try this:
Drawable drawable = getResources().getDrawable(R.drawable.ic_launcher);
int w = drawable.getIntrinsicWidth();
int h = drawable.getIntrinsicHeight();
drawable.setBounds(0, 0, w, h);
Bitmap b = Bitmap.createBitmap(w, h, Config.ARGB_8888);
Canvas c = new Canvas(b);
c.translate(0, h);
c.scale(1, -1);
drawable.draw(c);
// test it
ImageView iv = new ImageView(this);
iv.setImageBitmap(b);
setContentView(iv);

Add water effect on bitmap android

How can i add water waves in bitmap image?
i have found water ripple effect on touch event here: https://github.com/esteewhy/whater but can not implement on my single bitmap.
can anyone help in making water wave effect on my bitmap?
or should i go for image processing?
Thank you in advance.
Here is my sample code in which i have to make water reflection effect:
public static Bitmap reflection(Bitmap mainImage) {
int width = mainImage.getWidth();
int height = mainImage.getHeight();
Matrix matrix = new Matrix();
matrix.preScale(1, -1);
reflectionImage = Bitmap.createBitmap(mainImage, 0,
0, width, height , matrix, false);
reflectedBitmap = Bitmap.createBitmap(width,
(height + height), Config.ARGB_8888);
Canvas canvas = new Canvas(reflectedBitmap);
canvas.drawBitmap(mainImage, 0, 0, null);
Paint defaultPaint = new Paint();
canvas.drawRect(0, height, width, height, defaultPaint);
canvas.drawBitmap(reflectionImage, 0, height-6 , null);
Paint paint = new Paint();
LinearGradient shader = new LinearGradient(0,
mainImage.getHeight(), 0, reflectedBitmap.getHeight()
, 0x70ffffff, 0x00ffffff, TileMode.CLAMP);
paint.setShader(shader);
paint.setXfermode(new PorterDuffXfermode(Mode.DST_IN));
canvas.drawRect(0, height, width, reflectedBitmap.getHeight()
, paint);
return reflectedBitmap;
}

Add Watermark to an image just like flipboard in Android

I want to add watermark to images just like flipboard does.
As you can see text is added at the bottom of the images with black transparent background. I want to do the exact same thing. Till now I've managed to write text on image but I am not able to make it's background black transparent just like the above picture.
Here's my code so far which I found from here.
public Bitmap mark(Bitmap src, String watermark) {
int w = src.getWidth();
int h = src.getHeight();
Shader shader = new LinearGradient(0, 0, 100, 0, Color.TRANSPARENT, Color.BLACK, TileMode.CLAMP);
Bitmap result = Bitmap.createBitmap(w, h, src.getConfig());
Canvas canvas = new Canvas(result);
canvas.drawBitmap(src, 0, 0, null);
Paint paint = new Paint();
paint.setColor(Color.WHITE);
paint.setTextSize(50);
paint.setAntiAlias(true);
paint.setShader(shader);
paint.setUnderlineText(false);
canvas.drawText(watermark, 10 , h-15, paint);
return result;
}
I think it doesn't require gradient, you can draw it using simple color and using drawRect() method.
Sample code is below, i gonna take the black background size as 25% of whole image.
public Bitmap mark(Bitmap src, String watermark) {
int w = src.getWidth();
int h = src.getHeight();
Paint bgPaint=new Paint();
bgPaint.setColor(Color.parse("AA000000")); //transparent black,change opacity by changing hex value "AA" between "00" and "FF"
Bitmap result = Bitmap.createBitmap(w, h, src.getConfig());
Canvas canvas = new Canvas(result);
canvas.drawBitmap(src, 0, 0, null);
Paint paint = new Paint();
paint.setColor(Color.WHITE);
paint.setTextSize(50);
paint.setAntiAlias(true);
paint.setUnderlineText(false);
//should draw background first,order is important
int left=0;
int right=w;
int bottom=h;
int top=bottom-(h*.25);
canvas.drawRect(left,top,right,bottom,bgPaint);
canvas.drawText(watermark, 10 , h-15, paint);
return result;
}

android mask bitmap

I need to create a custom view amd in onDraw method I need to draw some bitmaps, using a mask. I created a paint:
Paint maskPaint = new Paint();
maskPaint.setAntiAlias(true);
maskPaint.setXfermode(new AvoidXfermode(Color.RED, 0, AvoidXfermode.Mode.TARGET));
and I draw my bitmap on canvas using this paint. My problem is that at the corners, my mask have some pixels with alpha less than 255. Is there a way to draw my bitmap's pixels on the mask with the same alpha that mask image has on those pixels with aplha greater than zero?
private Bitmap maskingImage(Bitmap s, int drawable) {
Bitmap original = s;
Bitmap mask = BitmapFactory.decodeResource(getResources(),drawable);
Bitmap result = Bitmap.createBitmap(mask.getWidth(), mask.getHeight(),Bitmap.Config.ARGB_8888);
Canvas mCanvas = new Canvas(result);
Paint paint = new Paint(Paint.ANTI_ALIAS_FLAG);
paint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.DST_IN));
mCanvas.drawBitmap(original, 0, 0, null);
mCanvas.drawBitmap(mask, 0, 0, paint);
paint.setXfermode(null);
return result;
}
Resources resources = this.getResources();
Bitmap mask = BitmapFactory.decodeResource(resources,R.drawable.fx_lightleak2_small);
int width=bMap.getWidth();
int height=bMap.getHeight();
Bitmap resizedbitmap=Bitmap.createScaledBitmap(mask, width, height, true);
Bitmap result = Bitmap.createBitmap(bMap.getWidth(), bMap.getHeight(), Config.ARGB_8888);
Canvas c = new Canvas(result);
Paint paint = new Paint(Paint.ANTI_ALIAS_FLAG);
paint.setXfermode(new PorterDuffXfermode(Mode.LIGHTEN));
c.drawBitmap(bMap, 0, 0, null);
paint.setAlpha(200);
c.drawBitmap(resizedbitmap, 0, 0, paint);
paint.setXfermode(null);
effect_5.setImageBitmap(result);

Categories

Resources