For example I want a white border of 10pixel around all 4 side of the bitmap. I am not using it for imageview
I am currently using this code to crop image. May I know how I could add a white border into it?
public Bitmap scaleCenterCrop(Bitmap source, int newHeight, int newWidth) {
int sourceWidth = source.getWidth();
int sourceHeight = source.getHeight();
// Compute the scaling factors to fit the new height and width, respectively.
// To cover the final image, the final scaling will be the bigger
// of these two.
float xScale = (float) newWidth / sourceWidth;
float yScale = (float) newHeight / sourceHeight;
float scale = Math.max(xScale, yScale);
// Now get the size of the source bitmap when scaled
float scaledWidth = scale * sourceWidth;
float scaledHeight = scale * sourceHeight;
// Let's find out the upper left coordinates if the scaled bitmap
// should be centered in the new size give by the parameters
float left = (newWidth - scaledWidth) / 2;
float top = (newHeight - scaledHeight) / 2;
// The target rectangle for the new, scaled version of the source bitmap will now
// be
RectF targetRect = new RectF(left, top, left + scaledWidth, top + scaledHeight);
// Finally, we create a new bitmap of the specified size and draw our new,
// scaled bitmap onto it.
Bitmap dest = Bitmap.createBitmap(newWidth, newHeight, source.getConfig());
Canvas canvas = new Canvas(dest);
canvas.drawBitmap(source, null, targetRect, null);
return dest;
}
I wrote a function for this:
private Bitmap addWhiteBorder(Bitmap bmp, int borderSize) {
Bitmap bmpWithBorder = Bitmap.createBitmap(bmp.getWidth() + borderSize * 2, bmp.getHeight() + borderSize * 2, bmp.getConfig());
Canvas canvas = new Canvas(bmpWithBorder);
canvas.drawColor(Color.WHITE);
canvas.drawBitmap(bmp, borderSize, borderSize, null);
return bmpWithBorder;
}
Basically it creates a new Bitmap adding 2 * bordersize to each dimension and then paints the original Bitmap over it, offsetting it with bordersize.
As for a way of doing this. You make your bitmap bigger than the one your adding to it and then fill the canvas with the background you want. If you need to add other effects you can look into the canvas options for clipping the rect and adding rounded corners and such.
RectF targetRect = new RectF(left+10, top+10, left + scaledWidth, top + scaledHeight);
Bitmap dest = Bitmap.createBitmap(newWidth+20, newHeight+20, source.getConfig());
Canvas canvas = new Canvas(dest);
canvas.drawColor(Color.WHITE);
canvas.drawBitmap(source, null, targetRect, null);
You can draw 4 rectangles after painting your bitmap's stuff.
point 0,0,3,sizey
point 0,0,sizex,3
point 0,sizey-3,sizex,sizey
point sizex-3,0,sizex,sizey
the accepted answer is nice but in the cases that bitmap contains a transparent background, it fills all over the background of source bitmap with white pixels. so it doesn't work fine for all cases.
a better way to achieve this goal is using Canvas#drawLine method like the following code:
Bitmap drawBorder(Bitmap source) {
int width = source.getWidth();
int height = source.getHeight();
Bitmap bitmap = Bitmap.createBitmap(width, height, source.getConfig());
Canvas canvas = new Canvas(bitmap);
Paint paint = new Paint();
paint.setStrokeWidth(50);
paint.setColor(Color.WHITE);
canvas.drawLine(0, 0, width, 0, paint);
canvas.drawLine(width, 0, width, height, paint);
canvas.drawLine(width, height, 0, height, paint);
canvas.drawLine(0, height, 0, 0, paint);
canvas.drawBitmap(source, 0, 0, null);
return bitmap;
}
in this way we first create a second bitmap using source bitmap width, height and config and use drawline() mathod four times to draw four lines using coordinates of end points of each line around the second bitmap and then draw the source bitmap on the second bitmap that must be returned.
A super easy way of doing it would be to set the ImageView background to white and add a padding value.
If that doesn't work, create a FrameLayout with w/h of wrap_content, set its background to white, put the ImageView in there, and set the ImageView's margins to the desired border width.
Its not elegant but you can always just draw a rectangle behind it, you already have the code to do this and any performance impact is going to be unnoticeable
You can create your targetRectangle 20px wider and 20px higher
RectF targetRect = new RectF(left, top, left + scaledWidth + 20, top + scaledHeight + 20);
and paint the background white
Try this it will also add border to your canvas
canvas.drawLine(0, 0, canvas.getWidth(), 0, paint2);
canvas.drawLine(0, 0, 0, canvas.getHeight(), paint2);
canvas.drawLine(0, canvas.getHeight(), canvas.getWidth(),
canvas.getHeight(), paint2);
canvas.drawLine(canvas.getWidth(), 0, canvas.getWidth(),
canvas.getHeight(), paint2);
Related
I want to place the watermark on the bottom right of the picture. But, in some mobiles it is coming perfectly and in some mobile phones, the watermark is coming on the whole image.
Here is my code:
rotatedBitmap = Bitmap.createBitmap(loadedImage, 0, 0,
loadedImage.getWidth(), loadedImage.getHeight(),
rotateMatrix, false);
int w = rotatedBitmap.getWidth();
int h = rotatedBitmap.getHeight();
Bitmap result = Bitmap.createBitmap(w, h, rotatedBitmap.getConfig());
Canvas canvas = new Canvas(result);
canvas.drawBitmap(rotatedBitmap, 0, 0, null);
Bitmap waterMark = BitmapFactory.decodeResource(getResources(), R.drawable.watermark2);
int ww = waterMark.getWidth();
int hh = waterMark.getHeight();
canvas.drawBitmap(waterMark,(w-ww),(h-hh), null);
EDIT: Here are the screenshots of the result. In second picture, the watermark is coming perfectly and in first picture, it is coming on the whole picture.
Make use of aspect ratio. Calculate aspect ratio of device and accordingly calculate appropriate size for your water mark.
How to calculate aspect ratio?
Check for width and height of screen whichever is bigger divide it by smaller one
example:
if(screen_width > screen_height){
aspectRatio = screen_width/screen_height
}else{
aspectRatio = screen_height/screen_width
}
now that you have calculated aspect ratio multiply it with size of you water mark and scale it accordingly.
like:
float ww = watermark.getWidth()*aspectRatio;
float wh = watermark.getHeight()*aspectRatio;
and use these values.
Hope this helps...
Just Give ratio and you go to go,try changing ratio values that best fit for your src bitmap .
Embeds an image watermark over a source image to produce a
watermarked one.
#param source The source image where watermark should be placed
#param ratio A float value < 1 to give the ratio of watermark's
height to image's height,
try changing this from 0.20 to 0.60 to obtain right results
public static Bitmap addWatermark(Context context, Bitmap source, float ratio)
{
Canvas canvas;
Paint paint;
Bitmap bmp;
Matrix matrix;
RectF r;
int width, height;
float scale;
Bitmap waterMark = BitmapFactory.decodeResource(context.getResources(), R.drawable.watermark3x);
width = source.getWidth();
height = source.getHeight();
// Create the new bitmap
bmp = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888);
paint = new Paint(Paint.ANTI_ALIAS_FLAG | Paint.DITHER_FLAG | Paint.FILTER_BITMAP_FLAG);
// Copy the original bitmap into the new one
canvas = new Canvas(bmp);
canvas.drawBitmap(source, 0, 0, paint);
// Scale the watermark to be approximately to the ratio given of the source image height
scale = (float) (((float) height * ratio) / (float) waterMark.getHeight());
// Create the matrix
matrix = new Matrix();
matrix.postScale(scale, scale);
// Determine the post-scaled size of the watermark
r = new RectF(0, 0, waterMark.getWidth(), waterMark.getHeight());
matrix.mapRect(r);
// Move the watermark to the bottom right corner
matrix.postTranslate(width - r.width(), height - r.height());
// Move the watermark to the bottom left corner
// matrix.postTranslate(0 , height - r.height());
// Move the watermark to the top-left corner
// matrix.postTranslate(0 ,0);
// Move the watermark to the top right corner
// matrix.postTranslate(width - r.width(), 0l̥);
// Draw the watermark
canvas.drawBitmap(waterMark, matrix, paint);
return bmp;
}
I've been searching here about cut bitmaps in android, however I could not make it work for me.
I would like to cut off some part of one specific bitmap, but I want to do that starting from center to the bottom of my image.
I already tried to use:
createBitmap(android.graphics.Bitmap source, int x, int y, int width, int height)
However, it always start to cut my image from the TOP, even changing x and y values.
I want to cut my bitmap as below blue square.
Someone have any idea about how to cut my bitmap?
You should take a look at this:
private Bitmap cropBitmap1()
{
Bitmap bmp2 = BitmapFactory.decodeResource(this.getResources(), R.drawable.image1);
Bitmap bmOverlay = Bitmap.createBitmap(320, 480, Bitmap.Config.ARGB_8888);
Paint p = new Paint();
p.setXfermode(new PorterDuffXfermode(Mode.CLEAR));
Canvas c = new Canvas(bmOverlay);
c.drawBitmap(bmp2, 0, 0, null);
c.drawRect(30, 30, 100, 100, p);
return bmOverlay;
}
Link: Source
Try this:
Bitmap source = BitmapFactory.decodeResource(getResources(),
R.drawable.ic_launcher);
int width = source.getWidth();
int height = source.getHeight();
int required = 25;// 25 pixels width and height
int startX = (width - required) / 2;
int startY = (height - required) / 2;
Bitmap resized = Bitmap.createBitmap(source, startX, startY, required,
required);
The only relevant part is the startX and startY calculations. The code asumes that you need a 25*25 pixels image.
I have searched for many answers here for drawing a circle on bitmap using canvas. However, I got some error in the code and the application stopped without any exception.
Can anyone give me some help? It works fine with I create a blank bitmap and draw a circle on it.
Any help will be appreciated!
Bitmap bmp = BitmapFactory.decodeResource(getResources(), R.drawable.main);
Paint paint = new Paint();
//paint.setAntiAlias(true);
paint.setColor(Color.BLUE);
Canvas canvas = new Canvas(bmp);
canvas.drawCircle(50, 50, 10, paint);
ImageView imageView = (ImageView)findViewById(R.id.imageView1);
//imageView.setAdjustViewBounds(true);
imageView.setImageBitmap(bmp);
Read somewhere that Resource bitmaps are immutable. Try...
bmp = bmp.copy(bmp.getConfig(), true);
This will draw a circle for you for given height
private RectF outerCircle;
diameter =400;
int left = (width - diameter) / 2;
int top = (height - diameter) / 2;
int bottom = top + diameter;
int right = left + diameter;
outerCircle = new RectF(left, top, right, bottom);
I have an image with frames and I need to add a watermark effect. How might I do this?
I found great tutorial on Android Image Processing here.
public static Bitmap mark(Bitmap src, String watermark, Point location, Color color, int alpha, int size, boolean underline) {
int w = src.getWidth();
int h = src.getHeight();
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);
paint.setAlpha(alpha);
paint.setTextSize(size);
paint.setAntiAlias(true);
paint.setUnderlineText(underline);
canvas.drawText(watermark, location.x, location.y, paint);
return result;
}
Thanks to Pete Houston who shares such useful tutorial on basic image processing.
For others reference, if you want to add the logo of your application (which is in your drawable folder(s)) on top of image use following method:
private Bitmap addWaterMark(Bitmap src) {
int w = src.getWidth();
int h = src.getHeight();
Bitmap result = Bitmap.createBitmap(w, h, src.getConfig());
Canvas canvas = new Canvas(result);
canvas.drawBitmap(src, 0, 0, null);
Bitmap waterMark = BitmapFactory.decodeResource(mContext.getResources(), R.drawable.logo);
canvas.drawBitmap(waterMark, 0, 0, null);
return result;
}
If someone is still searching for this, I found a good solution here
It adds a watermark to the bottom right portion and scales it according to the source image which was exactly what I was looking for.
/**
* Embeds an image watermark over a source image to produce
* a watermarked one.
* #param source The source image where watermark should be placed
* #param watermark Watermark image to place
* #param ratio A float value < 1 to give the ratio of watermark's height to image's height,
* try changing this from 0.20 to 0.60 to obtain right results
*/
public static Bitmap addWatermark(Bitmap source, Bitmap watermark, float ratio) {
Canvas canvas;
Paint paint;
Bitmap bmp;
Matrix matrix;
RectF r;
int width, height;
float scale;
width = source.getWidth();
height = source.getHeight();
// Create the new bitmap
bmp = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888);
paint = new Paint(Paint.ANTI_ALIAS_FLAG | Paint.DITHER_FLAG | Paint.FILTER_BITMAP_FLAG);
// Copy the original bitmap into the new one
canvas = new Canvas(bmp);
canvas.drawBitmap(source, 0, 0, paint);
// Scale the watermark to be approximately to the ratio given of the source image height
scale = (float) (((float) height * ratio) / (float) watermark.getHeight());
// Create the matrix
matrix = new Matrix();
matrix.postScale(scale, scale);
// Determine the post-scaled size of the watermark
r = new RectF(0, 0, watermark.getWidth(), watermark.getHeight());
matrix.mapRect(r);
// Move the watermark to the bottom right corner
matrix.postTranslate(width - r.width(), height - r.height());
// Draw the watermark
canvas.drawBitmap(watermark, matrix, paint);
return bmp;
}
And it is well commented which is what is a huge plus!
It seems you are looking for a waterrippleeffect as this one. Checkout the complete source code. Also check the screenshot how does the effect look like.
In Kotlin:
Note: Its just modified code of above answers
private fun mark(src: Bitmap, watermark: String): Bitmap {
val w = src.width
val h = src.height
val result = Bitmap.createBitmap(w, h, src.config)
val canvas = Canvas(result)
canvas.drawBitmap(src, 0f, 0f, null)
val paint = Paint()
paint.color = Color.RED
paint.textSize = 10f
paint.isAntiAlias = true
paint.isUnderlineText = true
canvas.drawText(watermark, 20f, 25f, paint)
return result
}
val imageBitmap = mark(yourBitmap, "Your Text")
binding.meetProofImageView.setImageBitmap(imageBitmap)
You can use androidWM to add a watermark into your image, even with invisible watermarks:
add dependence:
dependencies {
...
implementation 'com.huangyz0918:androidwm:0.2.3'
...
}
and java code:
WatermarkText watermarkText = new WatermarkText(“Hello World”)
.setPositionX(0.5)
.setPositionY(0.5)
.setTextAlpha(100)
.setTextColor(Color.WHITE)
.setTextFont(R.font.champagne)
.setTextShadow(0.1f, 5, 5, Color.BLUE);
WatermarkBuilder.create(this, backgroundBitmap)
.loadWatermarkText(watermarkText)
.getWatermark()
.setToImageView(backgroundView);
You can easily add an image type watermark or a text watermark like this, and the library size is smaller than 30Kb.
I tried a few libraries mentioned in other posts, like this, but unfortunately it is missing, and not downloadable now. So I followed AndroidLearner 's answer above, but after tweaking the code a little bit, for those of you who are having trouble rotating the watermark, and what values are valid for the various methods of Paint class, so that the text shows rotated at an angle(like most of the company watermarks do), you can use the below code.
Note that, w and h are the screen width and height respectively, which you can calculate easily, there are tons of ways you can find on stackoverflow only.
public static Bitmap waterMarkBitmap(Bitmap src, String watermark) {
int w = src.getWidth();
int h = src.getHeight();
Bitmap mutableBitmap = Utils.getMutableBitmap(src);
Bitmap result = Bitmap.createBitmap(w, h, mutableBitmap.getConfig());
Canvas canvas = new Canvas(result);
canvas.drawBitmap(src, 0f, 0f, null);
Paint paint = new Paint();
paint.setColor(Color.RED);
paint.setTextSize(92f);
paint.setAntiAlias(true);
paint.setAlpha(70); // accepts value between 0 to 255, 0 means 100% transparent, 255 means 100% opaque.
paint.setUnderlineText(false);
canvas.rotate(45, w / 10f, h / 4f);
canvas.drawText(watermark, w / 10f, h / 4f, paint);
canvas.rotate(-45, w / 10f, h / 4f);
return result;
}
It rotates the text watermark by 45 degrees, and places it at the centre of the bitmap.
Also note that, in case you are not able to get watermark, it might be the case that the bitmap you are using as source is immutable. For this worst case scenario, you can use below method to create a mutable bitmap from an immutable one.
public static Bitmap getMutableBitmap(Bitmap immutableBitmap) {
if (immutableBitmap.isMutable()) {
return immutableBitmap;
}
Bitmap workingBitmap = Bitmap.createBitmap(immutableBitmap);
return workingBitmap.copy(Bitmap.Config.ARGB_8888, true);
}
I found above method inside here. I have tested using both the methods in my application, and it works perfectly after I added above tweaks. Try it and let me know if it works or not.
use framelayout. put two imageviews inside the framelayout and specify the position of the watermark imageview.
I'm trying to draw a text on the center of a bitmap however I can't do it even though I used align.center. The code is:
public Bitmap drawTextToBitmap(Context gContext, String gText) {
Resources resources = gContext.getResources();
float scale = resources.getDisplayMetrics().density;
Bitmap bitmap =
BitmapFactory.decodeResource(resources, R.drawable.blank_marker);
android.graphics.Bitmap.Config bitmapConfig =
bitmap.getConfig();
// set default bitmap config if none
if(bitmapConfig == null) {
bitmapConfig = android.graphics.Bitmap.Config.ARGB_8888;
}
// resource bitmaps are imutable,
// so we need to convert it to mutable one
bitmap = bitmap.copy(bitmapConfig, true);
Canvas canvas = new Canvas(bitmap);
// new antialised Paint
Paint paint = new Paint(Paint.ANTI_ALIAS_FLAG);
// text color - #3D3D3D
paint.setColor(Color.rgb(61, 61, 61));
// text size in pixels
paint.setTextSize((int) (25 * scale));
// text shadow
paint.setShadowLayer(1f, 0f, 1f, Color.WHITE);
// draw text to the Canvas center
Rect bounds = new Rect();
paint.setTextAlign(Align.CENTER);
paint.getTextBounds(gText, 0, gText.length(), bounds);
int x = (bitmap.getWidth() - bounds.width())/2;
int y = (bitmap.getHeight() + bounds.height())/2;
canvas.drawText(gText, x * scale, y * scale, paint);
return bitmap;
}
What am I doing wrong?
It's a lot more straightforward than you think.
Draw the text at half the Bitmap's width and height (center point) in combination with Paint.setTextAlign(Align.CENTER).
The alignment property will take care of the rest.
I guess none of the answers given above are good enough so I post my answer. Try it out guys, it will work on all devices and is not complex at all:
String text = "Text"; //your string
Canvas canvas = new Canvas(bitmap);
Paint paint = new Paint(Paint.ANTI_ALIAS_FLAG);
paint.setColor(activity.getResources().getColor(R.color.white));
paint.setTextSize(30);
// draw text to the Canvas center
Rect boundsText = new Rect();
paint.getTextBounds(text, 0, text.length(), boundsText);
int x = (bitmap.getWidth() - boundsText.width()) / 2;
int y = (bitmap.getHeight() + boundsText.height()) / 2;
canvas.drawText(text, x, y, paint);
Where is the text drawing? The issue might be since you changed the text align to Align.CENTER. Your code calculating x and y assumes the text rendering is using Align.LEFT, I believe.
Either use setTextAlign(Align.CENTER) and render at the actual bitmap center, or use setTextAlign(Align.LEFT) and use the current x and y calculations you are using.