Is it possible to put an alpha on an imageview?
Not on the image but directly on the view?
At the moment I need to photoshop the image and
I don't want to edit every image.
It should look like this:
You might be able to fake the effect you're trying to achieve using:
android:foreground="#drawable/image_overlay"
or
imageView.setForeground(imageOverlayDrawable);
This will not actually make the image transparent, but if you have a static solid background color it should be enough to create the illusion of the image blending with the background.
If that's not an option try something like this:
// Get the image from wherever it lives and create a Bitmap of it
...
// Draw the image to a canvas so that we can modify it
Canvas canvas = new Canvas(image);
Paint imagePaint = new Paint(Paint.ANTI_ALIAS_FLAG | Paint.FILTER_BITMAP_FLAG);
canvas.drawBitmap(imageBitmap, 0, 0, imagePaint);
// Create a paint to draw the overlay with
PorterDuffXfermode porterDuffXfermode = new PorterDuffXfermode(PorterDuff.Mode.MULTIPLY);
Paint overlayPaint = new Paint(Paint.ANTI_ALIAS_FLAG | Paint.FILTER_BITMAP_FLAG);
overlayPaint.setXfermode(porterDuffXfermode);
// The overlay in this case needs to be a white gradient (where fully opaque means that
// the image will be left untouched and fully transparent will completely erase the image)
Bitmap overlayBitmap = BitmapFactory.decodeResource(getResources(), R.id.drawable.gradient_overlay, Bitmap.Config.ARGB_8888);
// Apply the overlay to create the alpha effect
canvas.drawBitmap(overlayBitmap, 0, 0, overlayPaint);
// Update the ImageView
imageView.setImageBitmap(bitmap);
Related
I'm trying to get cut a jigsaw puzzle piece out of an image, creating a new Bitmap image. I'm using a Path object to do this. This is the current result.
And how I achived this
Path path = new Path();
// Multiple path methods to create shape of puzzle piece...
path.close();
Bitmap source = BitmapFactory.decodeResource(getResources(), R.drawable.flowers);
Bitmap workingCopy = source.copy(Bitmap.Config.ARGB_8888, true);
Canvas canvas = new Canvas(workingCopy);
path.setFillType(Path.FillType.INVERSE_WINDING);
Paint paint = new Paint();
paint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.CLEAR));
canvas.drawPath(path, paint);
((ImageView) findViewById(R.id.myImage)).setImageBitmap(workingCopy);
I wish I could have it transparent instead of black and cut out everything outside the bounds of path.
I've tried it using a PNG-file with transparancy, and the background is transparent in stead of black.
So I have the following image to be used as a mask:
Now I want to apply this mask to images so that the image will fill the inner white space but will not fill the borders, keeping it as it is. However, when I use the code below, the image takes the inner white space plus the border.
public static Bitmap applyMask(Bitmap scaledBitmap, Bitmap mask) {
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(scaledBitmap, 0, 0, null);
mCanvas.drawBitmap(mask, 0, 0, paint);
paint.setXfermode(null);
return result;
}
So is there any way to make the image fill only the white space? How can I keep the mask borders intact?
Thanks in advance.
I had to download your image to see the transparent areas. They are on the outside of your shape (which is why DST_IN is the mode that works for this).
What the DST_IN mode does is erases any pixels already on the canvas where the pixels in the mask are transparent. So whether it's the dark border or the white inside, those pixels all have alpha > 0, so they mask the canvas just the same. Those pixels outside the shape have alpha == 0, so they erase the canvas pixels.
Since the final bitmap is the size of your mask, as I see it you have two options:
OPTION 1: If you can put the background color in the mask image:
Change your mask image so that the transparent pixels are inside the shape, and the pixels outside the shape are your background color. Then use SRC_OVER as your xfer mode. The background color outside the border, plus the black border will overwrite the existing pixels in this mode, and since the inner pixels are transparent, the middle part of the image will come through the way you want.
OPTION 2: If you have to specify the background color in the app so you can't put it in the mask image:
For this you'll need two mask images, the one you have and a copy with the inside pixels transparent as well, so you are left with the border. Draw with your mask image the way you are doing right now using DST_IN, then draw the image with just the border using SRC_OVER to draw the border on top of your masked image.
Here you have an example of what you want and you can adapt it to your case:
public static Bitmap getRoundedCornerBitmap(Bitmap bitmap) {
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 = 12;
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);
return output;
}
I've found it here. Hope it helps! :)
So I tried the code from here: Creating an ImageView with a mask. I'm using the following images as original and mask:
However, the result I get is this:
Note that the window background is not black, but holo light (which on the galaxy nexus looks like a very pale gray, not completely white). The second image is the result I get when an item is selected on a list view.
If instead I create a new Bitmap using the same algorithm and then pass it to the image view instead of overriding onDraw(), it draws correctly:
Canvas canvas = new Canvas();
Bitmap mainImage = //get original image
Bitmap maskImage = //get mask image
Bitmap result = Bitmap.createBitmap(mainImage.getWidth(), mainImage.getHeight(), Bitmap.Config.ARGB_8888);
canvas.setBitmap(result);
Paint paint = new Paint();
paint.setFilterBitmap(false);
canvas.drawBitmap(mainImage, 0, 0, paint);
paint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.DST_IN));
canvas.drawBitmap(maskImage, 0, 0, paint);
paint.setXfermode(null);
imageView.setImageBitmap(result);
I get the expected result:
Note the fade is correctly applied. This is more evident when a selection is made.
So what's going on on ImageView's onDraw method to create this black backdrop instead of letting the window background show through? What's interesting is that if the original image itself has some transparency, that transparency is respected, for example:
I can't figure it out by myself. I'd rather be able to do it on onDraw instead of pre-creating the bitmap because it only works for bitmaps as source and mask. I want to be able to do it with other drawables like gradients and solid colours but on those cases the width and height are not set.
I have found the perfect combination for creating masking without black border after researching through all the stackoverflow posts. It suits my purpose quite well.
Currently I'm creating a draggable view using one normal image and a masking image (a png with transparency), so I'll need to override the onDraw function.
private Bitmap mImage = ...;
private Bitmap mMask = ...; // png mask with transparency
private int mPosX = 0;
private int mPosY = 0;
private final Paint maskPaint;
private final Paint imagePaint;
public CustomView (final Context context) {
maskPaint = new Paint();
maskPaint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.CLEAR));
imagePaint = new Paint();
imagePaint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.DST_OVER));
}
/* TODO
if you have more constructors, make sure you initialize maskPaint and imagePaint
Declaring these as final means that all your constructors have to initialize them.
Failure to do so = your code won't compile.
*/
#Override
public void onDraw(Canvas canvas) {
super.onDraw(canvas);
canvas.save();
canvas.drawBitmap(mMask, 0, 0, maskPaint);
canvas.drawBitmap(mImage, mPosX, mPosY, imagePaint);
canvas.restore();
}
Answering my own question. The Xfermode was working as intended. The paint was making the resulting are of the canvas transparent (which was the canvas used by the window activity). Since the canvas itself was being set transparent, the window was showing what was behind it: the black background.
To do it properly, indeed a new Bitmap has to be created to hold the result of the alpha mask. I updated the code to take into account drawables of all types.
In this Code Apply:
mask_over = BitmapFactory.decodeResource(
getResources(), mask_over1[0]);
icon = Bitmap.createScaledBitmap(icon, screenwidth, screenwidth, false);
mask_over = Bitmap.createScaledBitmap(mask_over, screenwidth, screenwidth, false);
back_img=createBitmap_ScriptIntrinsicBlur(Bitmap.createScaledBitmap(cropview.croppedImage, screenwidth, screenwidth, false),25.0f);
LinearLayout.LayoutParams layoutParams111 = new LinearLayout.LayoutParams(screenwidth, screenwidth);
Hi every am new to this android development.
Currently am developing drawing application with adding stamps/labels to drawn image.so i have done drawing part so now i have to implement adding stamps/labels to that drawn image.
So please help me out this..
Bitmap Rbitmap = Bitmap.createBitmap(bitmap).copy(Config.ARGB_4444, true);
Canvas canvas = new Canvas(Rbitmap);
canvas.drawBitmap(label, -9, Rbitmap.getHeight()-label.getHeight()-10, null);
canvas.save();
return Rbitmap;
Making your question little more specific will help you more.If I understood is correct this piece of code will help you out to draw a bitmap to a drawn canvas.
private Paint green = new Paint();
private int greenx , greeny;
green.setColor(Color.GREEN);
green.setAntiAlias(false);
canvas.drawCircle(greenx,greeny,20,green);
how to add image in this code replace drawcircle with image how ?
You could be a little more specific, i.e posting some code to show what you have to get more specific answers. Anyway, you can draw a bitmap on top of another bitmap by using something like this:
//You will have a Bitmap bottomBmp, a Bitmap topBmp and a Canvas canvas.
//If you are inside an onDraw() method the canvas will be provided to you, otherwise you will have to create it yourself, use a mutable bitmap of the same size as the bottomBmp.
canvas.drawBitmap(bottomBmp, 0, 0, null); //Draw the bottom bitmap in the upper left corner of the canvas without any special paint effects.
canvas.drawBitmap(topBmp, 0, 0, null); //Draw the top bitmap over the bottom bitmap, change the zeroes to offset this bitmap.
Try with this code:
private Bitmap background;
public birdClass(Context context) {
super(context);
background = BitmapFactory.decodeResource(getResources(),R.drawable.splash );
}
I want to set a background of a View with a tiled bitmap, but the tiling needs to be anchored to the bottom-left, instead of the top-left corner (the default). For example, if the tiles are the smiley faces below, I want it to be tiled like:
Using xml drawables I could achieve either tiling (using tileMode="repeat") or bottom positioning (using gravity="bottom"), but combining both is not possible, even the documentation says so:
android:tileMode
Keyword. Defines the tile mode. When the tile mode is
enabled, the bitmap is repeated. Gravity is ignored when the tile mode
is enabled.
Although it's not internally supported, is there any way to achieve this, perhaps using custom views?
Another way would be to extend BitmapDrawable and override the paint() method:
In this method we avoid creating a new bitmap having the size of the view.
class MyBitmapDrawable extends BitmapDrawable {
private Paint mPaint = new Paint(Paint.FILTER_BITMAP_FLAG | Paint.DITHER_FLAG);
private boolean mRebuildShader = true;
private Matrix mMatrix = new Matrix();
#Override
public void draw(Canvas canvas) {
Bitmap bitmap = getBitmap();
if (bitmap == null) {
return;
}
if (mRebuildShader) {
mPaint.setShader(new BitmapShader(bitmap, TileMode.REPEAT, TileMode.REPEAT));
mRebuildShader = false;
}
// Translate down by the remainder
mMatrix.setTranslate(0, getBounds().bottom % getIntrinsicHeight());
canvas.save();
canvas.setMatrix(mMatrix);
canvas.drawRect(getBounds(), mPaint);
canvas.restore();
}
}
It can be set to the view like this:
view.setBackgroundDrawable(new MyBitmapDrawable(getResources().getDrawable(R.drawable.smiley).getBitmap()));
Just a thought, and it's pretty roundabout, but could you flip your image vertically, and then apply a transform to your background to flip that vertically as well?
Using a custom view might involve handling all the drawing yourself, not just the background image.
Instead, I propose to set the view's background programmatically as shown:
// This drawable refers to an image directly and NOT an XML
BitmapDrawable smiley = (BitmapDrawable) getResources().getDrawable(R.drawable.smiley);
// Create a new bitmap with the size of the view
Bitmap bgBitmap = Bitmap.createBitmap(view.getWidth(), view.getHeight(), Bitmap.Config.ARGB_8888);
Canvas canvas = new Canvas(bgBitmap);
// Translate down by the remainder
Matrix matrix = new Matrix();
matrix.setTranslate(0, view.getHeight() % smiley.getIntrinsicHeight());
canvas.setMatrix(matrix);
// Tile the smileys
Paint paint = new Paint();
paint.setShader(new BitmapShader(smiley.getBitmap(), TileMode.REPEAT, TileMode.REPEAT));
canvas.drawPaint(paint);
view.setBackgroundDrawable(new BitmapDrawable(bgBitmap));
Points to consider:
I'm not sure if view.getWidth() & view.getHeight() are the correct
methods to get the dimensions.
What if smiley size is bigger than the view?