thumbnail reflection with Drawable instead of Bitmap - android

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);

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);
}

How to mask Bitmap with LinearGradient shader properly?

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);

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;
}

How to crop image in oval shape or facemask shape in android?

I am doing camera application.i have capture and crop image in square shape. But i need oval shape or human face shape. How is it come ?
I have used following method and passed my captured bitmap image to this method. And it will work.
public Bitmap getRoundedShape(Bitmap scaleBitmapImage) {
int targetWidth = 125;
int targetHeight = 125;
Bitmap targetBitmap = Bitmap.createBitmap(targetWidth,
targetHeight, Bitmap.Config.ARGB_8888);
Canvas canvas = new Canvas(targetBitmap);
Path path = new Path();
path.addCircle(
((float) targetWidth - 1) / 2,
((float) targetHeight - 1) / 2,
(Math.min(((float) targetWidth), ((float) targetHeight)) / 2),
Path.Direction.CCW);
canvas.clipPath(path);
Bitmap sourceBitmap = scaleBitmapImage;
canvas.drawBitmap(
sourceBitmap,
new Rect(0, 0, sourceBitmap.getWidth(), sourceBitmap
.getHeight()), new Rect(0, 0, targetWidth,
targetHeight), p);
return targetBitmap;
}
And the output is as follows:-
I used following in one of my project. May be this helps you.
public Drawable getRoundedCornerImage(Drawable bitmapDrawable) {
Bitmap bitmap = ((BitmapDrawable)bitmapDrawable).getBitmap();
Bitmap output = Bitmap.createBitmap(bitmap.getWidth(),
bitmap.getHeight(), Config.ARGB_8888);
Canvas canvas = new Canvas(output);
final int color = 0xff424242;
final Paint paint = new Paint();
final Rect rect = new Rect(0, 0, bitmap.getWidth(), bitmap.getHeight());
final RectF rectF = new RectF(rect);
final float roundPx = 10;
paint.setAntiAlias(true);
canvas.drawARGB(0, 0, 0, 0);
paint.setColor(color);
canvas.drawRoundRect(rectF, roundPx, roundPx, paint);
paint.setXfermode(new PorterDuffXfermode(Mode.SRC_IN));
canvas.drawBitmap(bitmap, rect, rect, paint);
Drawable image = new BitmapDrawable(output);
return image;
}
Explore com.android.camera.CropImage.java sources. It can crop circle images.
// if we're circle cropping we'll want alpha which is the third param here
464 mCroppedImage = Bitmap.createBitmap(width, height,
465 mCircleCrop ?
466 Bitmap.Config.ARGB_8888 :
467 Bitmap.Config.RGB_565);
468 Canvas c1 = new Canvas(mCroppedImage);
469 c1.drawBitmap(mBitmap, r, new Rect(0, 0, width, height), null);
470
471 if (mCircleCrop) {
472 // OK, so what's all this about?
473 // Bitmaps are inherently rectangular but we want to return something
474 // that's basically a circle. So we fill in the area around the circle
475 // with alpha. Note the all important PortDuff.Mode.CLEAR.
476 Canvas c = new Canvas (mCroppedImage);
477 android.graphics.Path p = new android.graphics.Path();
478 p.addCircle(width/2F, height/2F, width/2F, android.graphics.Path.Direction.CW);
479 c.clipPath(p, Region.Op.DIFFERENCE);
480
481 fillCanvas(width, height, c);
482 }
#vokilam you are right; I just explored into code and found a way to work around...
Just include this line in the main Activity
intent.putExtra(CropImage.CIRCLE_CROP, "circleCrop");
But you will only get circles, not oval; so #amarnathreddy you cannot cut perfect human face with this; instead go for Grabcut of OpenCv
Try with this ...to crop in human face shape
Uri ImageCaptureUri = Uri.fromFile(new File("filepath");
Intent intent = new Intent("com.android.camera.action.CROP");
intent.setType("image/*");
intent.setData(ImageCaptureUri);
intent.putExtra("outputX", 200);
intent.putExtra("outputY", 200);
intent.putExtra("aspectX", 1);
intent.putExtra("aspectY", 1);
intent.putExtra("scale", true);
intent.putExtra("return-data", true);
startActivityForResult(intent, 1);
For an oval shape try this android function or download demo here
public static Bitmap getOvalCroppedBitmap(Bitmap bitmap, int radius) {
Bitmap finalBitmap;
if (bitmap.getWidth() != radius || bitmap.getHeight() != radius)
finalBitmap = Bitmap.createScaledBitmap(bitmap, radius, radius,
false);
else
finalBitmap = bitmap;
Bitmap output = Bitmap.createBitmap(finalBitmap.getWidth(),
finalBitmap.getHeight(), Bitmap.Config.ARGB_8888);
Canvas canvas = new Canvas(output);
Paint paint = new Paint();
final Rect rect = new Rect(0, 0, finalBitmap.getWidth(),
finalBitmap.getHeight());
paint.setAntiAlias(true);
paint.setFilterBitmap(true);
paint.setDither(true);
canvas.drawARGB(0, 0, 0, 0);
paint.setColor(Color.parseColor("#BAB399"));
RectF oval = new RectF(0, 0, 130, 150);
canvas.drawOval(oval, paint);
paint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.SRC_IN));
canvas.drawBitmap(finalBitmap, rect, oval, paint);
return output;
}
The above function creates a uniform oval shape in android programmatically.
call your function onCreate function and pass the image to crop oval shape as a bitmap image
Read more

Reflection on the Right Side of Image in Android ImageView

I have an image and I want to give reflection to that image in Android application, below is the source code. I've found an example code
ImageView imageView = (ImageView) findViewById(R.id.image1);
imageView.setImageResource(imageIDs[position]);
//The gap we want between the reflection and the original image
final int reflectionGap = 4;
//Get you bit map from drawable folder
Bitmap originalImage = BitmapFactory.decodeResource(getResources(),
imageIDs[position]);
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
Bitmap reflectionImage ;
if(isVertical)
reflectionImage= Bitmap.createBitmap(originalImage, 0, height/2, width, height/2, matrix, false);
else
reflectionImage= Bitmap.createBitmap(originalImage, width/2, 0, width/2, height, matrix, false);
//Create a new bitmap with same width but taller to fit reflection
Bitmap bitmapWithReflection;
if(isVertical)
bitmapWithReflection = Bitmap.createBitmap(width
, (height + height/2), Config.ARGB_8888);
else
bitmapWithReflection = Bitmap.createBitmap(width +width/2
, height, 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 in the gap
Paint deafaultPaint = new Paint();
if(isVertical)
canvas.drawRect(0, height, width, height + reflectionGap, deafaultPaint);
else
canvas.drawRect(width, 0, width+reflectionGap, height, deafaultPaint);
//Draw in the reflection
if(isVertical)
canvas.drawBitmap(reflectionImage,0, height + reflectionGap, null);
else
canvas.drawBitmap(reflectionImage,width + reflectionGap,0 , null);
//Create a shader that is a linear gradient that covers the reflection
Paint paint = new Paint();
LinearGradient shader;
if(isVertical)
shader = new LinearGradient(0, originalImage.getHeight(), 0,
bitmapWithReflection.getHeight() + reflectionGap, 0x70ffffff, 0x00ffffff,
TileMode.CLAMP);
else
shader = new LinearGradient(originalImage.getWidth(),0,
bitmapWithReflection.getWidth() + reflectionGap,0, 0x70ffffff, 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
if(isVertical)
canvas.drawRect(0, height, width,
bitmapWithReflection.getHeight() + reflectionGap, paint);
else
canvas.drawRect(width, 0, bitmapWithReflection.getWidth() + reflectionGap,
height, paint);
//Create an Image view and add our bitmap with reflection to it
//ImageView imageView = new ImageView(this);
imageView.setImageBitmap(bitmapWithReflection);`
This example works gracefullt when I give isVertical value=true, ath the bottom of the image, but I want to use reflection effect at the right side of the image also because I think it will be better in landscape mode. But it does not work as I want. It shows reflection side top-bottom reversed. What is my mistake? Thanks.
Your matrix has to change:
if (isVertical) {
matrix.preScale(1, -1);
reflectionImage= Bitmap.createBitmap(originalImage, 0, height/2, width, height/2, matrix, false);
}
else {
matrix.preScale(-1, 1);
reflectionImage= Bitmap.createBitmap(originalImage, width/2, 0, width/2, height, matrix, false);
}

Categories

Resources