Tint Bitmap with Paint? - java

I'm trying to create a function that tints a Bitmap,
this works...
imgPaint = new Paint();
imgPaint.setColorFilter(new LightingColorFilter(color,0));
//when image is being drawn
canvas.drawBitmap(img,matrix,imgPaint);
However, when the bitmap has to be drawn constantly (every frame) , I start to see screen lag, because this didn't occur before the color filter was set, I believe that it is applying the filter every time I need the canvas drawn.
Is there a way to apply the paint once to the bitmap and have it permanently changed?
Any help appreciated :)

Create a second bitmap and draw the first bitmap into it using the color filter. Then use the second bitmap for the high-volume rendering.
EDIT: Per request, here is code that would do this:
public Bitmap makeTintedBitmap(Bitmap src, int color) {
Bitmap result = Bitmap.createBitmap(src.getWidth(), src.getHeight(), src.getConfig());
Canvas c = new Canvas(result);
Paint paint = new Paint();
paint.setColorFilter(new LightingColorFilter(color,0));
c.drawBitmap(src, 0, 0, paint);
return result;
}
You would then call this method once to convert a bitmap to a tinted bitmap and save the result in an instance variable. You would then use the tinted bitmap directly (without a color filter) in your method that draws to canvas. (It would also be a good idea to pre-allocate the Paint object you will be using in the main draw method and save it in an instance variable as well, rather than allocating a new Paint on every draw.)

Related

How to set an Image's alpha in android

so I'm in a bit of a pickle. I know how to set the alpha value of a bitmap in android. What I don't know how to do is make is reversible. So, let's say someone wanted to set the alpha of an image to 50%, so they do. Now lets say they wanted to set it 75% (keep in mind, this is of the original image alpha value). Currently, what I have is a function that will set the alpha value of the current image, so it would be 75% of the 50% alpha value if that makes sense. How can I make it so that it accounts for the original image?
public Pixmap setAlpha(float newAlpha) { //integer between 0-100
if (newAlpha != alpha) { //to check if the current alpha value of the image is equal to your desired alpha. to avoid always halving you alpha value
float test = newAlpha/100.0f;
float test2 = test * 255;
alpha = test2;
Bitmap newBM = Bitmap.createBitmap(backupImg.getBitmap().getWidth(),backupImg.getBitmap().getHeight(), Bitmap.Config.ARGB_8888);
Canvas cc = new Canvas(newBM);
cc.drawARGB(0,0,0,0);
Paint newPaint = new Paint();
newPaint.setAlpha((int)test2);
cc.drawBitmap(backupImg.getBitmap(), 0, 0, newPaint);
img.setBitmap(newBM);
return img;
} else {
return img;
}
}
The Pixmap part is just a custom Bitmap class. backupImg is just a copy of img, created in the constructor of the object this function belongs to.
please keep in mind that this will be a canvas based bitmap. If I recall correctly imageView's aren't drawn on the canvas? So, as a further example. Imagine a sprite drawn to the canvas that you want to alter the alpha of. So you do it using the function I've posted. Now, let's say you want to undo the changes and restore it to the sprite's original alpha, of some other value. Well, you can't because the alpha value of the image has been changed permanently. What I want to do is store reference to the original image with another variable, and refer to that whenever I need to adjust the alpha value of the image. Hopefully that makes sense
Why don't you set alpha to the ImageView instead of setting it to a bitmap.
By setting alpha to the ImageView or say any view you can reverse it easily.
Refer to this answer in order to do it.
You can do it from xml. Just add the below line in the imageview tag:-
android:alpha="0.5"
You can set alpha between 0 to 1. Above line will set alpha to half that is 0.5.
For bitmap:
Bitmap newBitmap = Bitmap.createBitmap(originalBitmap.getWidth(),
originalBitmap.getHeight(), Bitmap.Config.ARGB_8888);
Canvas canvas = new Canvas(newBitmap);
Paint alphaPaint = new Paint();
alphaPaint.setAlpha(75);
canvas.drawBitmap(originalBitmap, 0, 0, alphaPaint);
I've solved the problem myself. So, there is nothing wrong with the function I wrote. The problem instead lies within how Java uses pointers. because everything is passed via reference, I was actually referencing the same object, rather than creating two separate objects. So instead of:
Bitmap oldBM = new Bitmap();
Bitmap newBM = oldBM;
you would instead want to do
Bitmap oldBM = new Bitmap();
Bitmap newBM = new Bitmap(using old bitmap's value);

ImageView spread out animation

I basically have an ImageView which got modified with Canvas and looks like a cirlce. (original image had the dimensions of a square (500x500))
Image what the starting position looks like:
http://imgur.com/bvXdLoP
(red is transparent and got removed with help of the Canvas method)
The animation should take aroud 1000 miliseconds and during this time step for step restore to the original picture. So in the end there should be a sqaure again.
In other words the cut off corners, which are the differnce between a square and a circle (and red marked in the image), get step for step restored in around 1000 milliseconds, with a sort of spreading looking animation.
Don't really have any clue on how to achieve this, so I can just share the Canvas method I used to cut off the corners (if it helps :X):
private Bitmap createCircleImage(Bitmap bitmap) {
Bitmap bmp;
bmp = Bitmap.createBitmap(bitmap.getWidth(),
bitmap.getHeight(), Bitmap.Config.ARGB_8888);
BitmapShader shader = new BitmapShader(bitmap,
BitmapShader.TileMode.CLAMP,
BitmapShader.TileMode.CLAMP);
float radius = bitmap.getWidth() / 2f;
Canvas canvas = new Canvas(bmp);
Paint paint = new Paint();
paint.setAntiAlias(true);
paint.setShader(shader);
canvas.drawCircle(bitmap.getWidth()/2,bitmap.getHeight()/2,bitmap.getHeight()/2, paint);
return bmp;
}
Appreciate any help,
thank you!
There are many ways to achieve such behavior. For example you can create custom view and override its onDraw method such as
#Override
public void onDraw(Canvas canvas) {
canvas.drawCircle(viewWidth/2, viewHeight/2, currentRadius, paint);
}
and then you can just increase the radius little by little and invalidate the view.Since view is by default will clip on its clipBounds (you can only draw inside viewidth x viewheight rectangle unless you set it otherwise) you will get the effect that you want. And then you can tweak the interpolation to achieve smoother and more natural animation.
note: a bitmap shader is attached to the paint (you already know chow to create it). I don't include it in the code, since you shouldn't initialize it inside onDraw method for performance reason.

Android - use bitmap as a gradient mask

I have implemented a flood fill algorithm in an android app. The way I have implemented the algorithm doesn't actually change the source bitmap, but instead creates a new bitmap of the fill area. I.E.
Flood filling this circle with red
Would produce this bitmap (where everything else in the bitmap is transparent)
Which I then combine again into a single bitmap. This works great for solid colors, but I want to be able to implement a gradient flood fill so that if a user fills the same circle, choosing red and blue, the resulting bitmap would look like this
My question is, is there a way that I can use the red circle as some sort of mask to make the desired gradient? or do I have to write a gradient generator myself?
Thanks to pskink's hint, I was able to find an answer.
The idea is that you create a canvas, draw the mask to it, create the gradient that you want, then draw the gradient on top of it using the SRC_IN PorterDuffXfermode. Here's the code:
public Bitmap addGradient(Bitmap src, int color1, int color2)
{
int w = src.getWidth();
int h = src.getHeight();
Bitmap result = Bitmap.createBitmap(w,h, Bitmap.Config.ARGB_8888);
Canvas canvas = new Canvas(result);
canvas.drawBitmap(src, 0, 0, null);
Paint paint = new Paint();
LinearGradient shader = new LinearGradient(0,0,0,h, color1, color2, Shader.TileMode.CLAMP);
paint.setShader(shader);
paint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.SRC_IN));
canvas.drawRect(0,0,w,h,paint);
return result;
}
In this instance, the DST(destination) is the red circle and the SRC(source) is the gradient. The SRC_IN PorterDuff mode means draw the SRC everywhere that it intersects with the DST.
Note that it really doesn't matter what color the mask is, because the PorterDuff mode only pays attention to whether the DST pixel is transparent or not. The color of the resulting bitmap will be a gradient between color1 and color2.

android custom view ondraw, get bitmap from canvas?

So I seem to have a conundrum. I need to add multiple custom views to a framelayout. The code for this is working just fine. However, I wish to access the underlying bitmap that the canvas uses in the views onDraw method. Like this one (in a class that extends View):
#Override
protected void onDraw(Canvas canvas) {
// TODO Auto-generated method stub
super.onDraw(canvas);
canvas.drawARGB(Color.alpha(bgColor), Color.red(bgColor),
Color.green(bgColor), Color.blue(bgColor));
m.reset();
m.setTranslate(imgPosX - ((float) userImage.getWidth() / 2.0f), imgPosY
- ((float) userImage.getHeight() / 2.0f));
m.postRotate(angle);
m.postScale(1.0f, 1.0f);
canvas.drawBitmap(userImage, m, null);
}
I wish to erase certain pixels essentially. Now, I know I can do this via the setPixel method which is fine but it is exceptionally slow and not satisfactory. I have a working ndk function that does exactly what I want, but it passes in a bitmap. I know I can use a SurfaceView instead of a View to access the bitmap like that, however as mentioned here multiple SurfaceViews in a FrameLayout isn't an option. So, I would think I need to manipulate the bitmap itself used by the canvas in the onDraw method. How would I go about doing this? or alternatively I don't mind creating another bitmap, passing it into the ndk function and returning/drawing that, however would I do a canvas.drawBitmap with transparent pixels?
Have you looked into setting the PorterDuff mode on a Paint object?
use paint.setXfermode(new PorterDuffXfermode(Mode.CLEAR)) then draw over the pixels that you want to erase
edit: What exactly are you trying to clear? There are multiple modes and you may need to select a different one depending on what you are trying to do. Here is an example of a function I currently use to crop Bitmaps to a circle.
public static Bitmap crop_circle_center(Bitmap bitmap) {
final int diameter = Math.min(bitmap.getWidth(), bitmap.getHeight());
Bitmap output = Bitmap.createBitmap(diameter,
diameter, 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());
rect.offset(-(bitmap.getWidth()-diameter)/2, -(bitmap.getHeight()-diameter)/2);
paint.setAntiAlias(true);
canvas.drawARGB(0, 0, 0, 0);
paint.setColor(color);
canvas.drawCircle(diameter/ 2, diameter/ 2,
diameter / 2, paint);
paint.setXfermode(new PorterDuffXfermode(Mode.SRC_IN));
canvas.drawBitmap(bitmap, null, rect, paint);
return output;
}

Android: print date and time on photo captured by my application

In my android application I use camera to capture photo. I want to print date and time on captured photo. As in normal camera there is an option that, if you set date and time on camera then it will printed on right lower side of the photo.
To capture the photo I use cameraIntent:
Intent cameraIntent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
and in onActivityResult I save in photo.
Now how I print date and time on this photo.
This code adding a image on top of another image u can use this...
Bitmap bottomImage = BitmapFactory.decodeResource(ctx.getResources(),
R.drawable.first);
Bitmap topImage = BitmapFactory.decodeResource(ctx.getResources(),
R.drawable.second);
Canvas comboImage = new Canvas(bottomImage);
// Then draw the second on top of that
float f=(float) 0.1;
comboImage.drawBitmap(topImage, 38f, 35f, null);
open the bitmap as a canvas and write the date/time as text wherever you like. The changes would would saved on the bitmap.
Some sample code is as follows. Google Paint and Canvas classes for more options
Canvas canvas = new Canvas(bmp); //bmp is the bitmap to dwaw into
Paint paint== new Paint();
paint.setColor(Color.YELLOW);
paint.setTextSize(28);
paint.setTextAlign(Paint.Align.CENTER);
Finally, we can draw text with this font via the following Canvas method:
canvas.drawText("This is a test!", 100, 100, paint);
The first parameter is the text to draw. The next two parameters are the coordinates
where the text should be drawn to ( play with them to get the position right). Then is Paint instance. No need to use drawBimtap. Whatever you will do on the canvas will be saved on the original bitmap directly without over-writing.

Categories

Resources