I have some question about water mark within android code!
Following code showed my idea about WaterMark!
However,It does not work normally.
e.g. only the image end with .png can be watered mark
Is there a scheme about water mark(.jpeg, .jpg, .wbmp, .bmp, .png or others)
protected static Bitmap getDrmPicture(Context context,String path){
BitmapFactory.Options options = new BitmapFactory.Options();
options.inPreferredConfig = Bitmap.Config.ARGB_8888;
Bitmap originMap = BitmapFactory.decodeFile (path,options);
Bitmap waterMark = BitmapFactory.decodeResource(context.getResources(), R.drawable.close);
InputStream input;
byte[] b;
Bitmap waterMark = null;
try {
input = context.getResources().openRawResource(R.drawable.lock);
b = new byte[input.available()];
input.read(b);
waterMark = DecodeUtils.requestDecode(jc, b, null);
}catch(IOException e){
}
int w = originMap.getWidth();
int h = originMap.getHeight();
int ww = waterMark.getWidth();
int wh = waterMark.getHeight();
Bitmap newb = Bitmap.createBitmap(w, h,Bitmap.Config.ARGB_8888;);
Canvas cv = new Canvas(newb);
cv.drawBitmap(originMap, 0, 0, null);
cv.drawBitmap(waterMark, w - ww, h - wh, null);
cv.save(Canvas.ALL_SAVE_FLAG);
cv.restore();
return newb;
}
Thanks !
This is the code I use to apply watermark to a jpeg, it should work for you too,
public Bitmap applyWatermarkColorFilter(Drawable drawable) {
Bitmap image = ((BitmapDrawable)drawable).getBitmap();
Bitmap result = Bitmap.createBitmap(image.getWidth(), image.getHeight(), Config.ARGB_8888);
Canvas canvas = new Canvas(result);
canvas.drawBitmap(image, 0, 0, null);
Bitmap watermark = BitmapFactory.decodeResource(getResources(), R.drawable.watermark);
canvas.drawBitmap(watermark, image.getWidth()/2 - watermark.getWidth()/2,
image.getHeight()/2 - watermark.getHeight()/2,
null);
return result;
}
Basically after this u have to use Bitmap.compress(<arguments>) to get a jpg out of it.
Din't try for the other formats. May be it might be possible if you can extract the Bitmap out of them like how we do for jpg and png.
https://stackoverflow.com/questions/6756975/draw-multi-line-text-to-canvas
Measure height of multiline text
To center text vertically we need to know text height. Instantiate StaticLayout with text width according to your needs, for us it is simple the width of Bitmap/Canvas minus 16dp padding. The getHeight() then returns height of text.
Positioning text on Canvas
There are four simple steps to position text on Canvas:
Save the current matrix and clip with Canvas.save().
Apply translation to Canvas matrix with Canvas.translate(x,y).
Draw StaticLayout on Canvas with StaticLayout.draw(canvas).
Revert matrix translation with Canvas.restore() method.
Related
This question already has answers here:
How to draw text On image?
(7 answers)
Closed 2 years ago.
I am new for android and i want to add watermark effect on captured images and i am trying find the solution for it since 2 days but still not able to add watermark effect on captured images can some one help me what i did mistack in my below code..
I want add water mark effect on bottom middle of image
Code
private void onCaptureImageResult(Intent data) {
Bitmap photo;Bitmap watermark_bitmap=null;
String selectedFilePath = null;
if (data.getExtras().get("data") != null) {
photo = (Bitmap) data.getExtras().get("data");
watermark_bitmap=Utilities.mark(this,photo,"Hello World",true);
Uri contentUri = Utilities.getImageUri1(
this, watermark_bitmap);
selectedFilePath = ImageFilePath.getPath(
this, contentUri);
newMeter_image.setImageBitmap(watermark_bitmap);
}
public static Bitmap mark(Context context,Bitmap src, String watermark, 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();
int color = ContextCompat.getColor(context, R.color.black);
paint.setColor(color);
paint.setAlpha(1);
paint.setTextSize(5);
paint.setAntiAlias(true);
paint.setUnderlineText(underline);
canvas.drawText(watermark, 50,50, paint);
return result;
}
I would have also used the same approach.
Load the image in a canvas.
Canvas canvas = new Canvas(result);
canvas.drawBitmap(src, 0, 0, null);
Set the paint and draw the text/drawable/bitmap of your watermark at the location you desire.
Instead of using hardcoded values (50,50) try using calculated values.
canvas.drawText("Watermark",canvas.width/2, canvas.height/2, paint)
This will make the watermark as a part of your image.
If you want to keep it separate but create an illusion of watermark, then you can display your watermark as src in an imageView and overlay it over your actual image display view.
Sorry if I misunderstood. Do share a better solution though!
I'm working with a set of layered images (think stacked) and I need to combine them into one element.
I'm basing my solution off Combine multiple bitmap into one
//send a map to the method that has my stored image locations in order
private Bitmap combineImageIntoOne(NavigableMap<Integer, String> layerImages) {
//size of my bitmaps
int w = 400, h = 400;
//bitmap placeholder
Bitmap productIndex = null;
//flattened layers
Bitmap temp = Bitmap.createBitmap(w, h, Bitmap.Config.ARGB_8888);
//canvas to write layers to
Canvas canvas = new Canvas(temp);
int top = 0;
for (Map.Entry<Integer, String> e : layerImages.entrySet()) {
//create the layer bitmap
productIndex = decodeSampledBitmapFromResource(getResources(), e.getValue(), 400, 400);
//add layer to canvas
canvas.drawBitmap(productIndex, 0f, top, null);
}
//convert temp to a BitmapDrawable
Drawable d = new BitmapDrawable(getResources(),temp);
//set my image view to have the flattened image
carBase.setImageDrawable(d);
return temp;
}
The decodeSampledBitmapFromResource come from the Android docs about loading large bitmaps: Loading Large Bitmaps Efficiently You can review the code on that doc to see what I"m doing. I didn't edit the Android code much.
I've been using the Android code just fine to add layers to the FrameLayout but ended up running out of memory when the layers starting getting pretty high in number. This combining method is being used to conserve memory space.
Any ideas why the final bitmap doesn't have any content?
Reference LINK <-------------------------
public Bitmap combineImages(Bitmap c, Bitmap s) { // can add a 3rd parameter 'String loc' if you want to save the new image - left some code to do that at the bottom
Bitmap cs = null;
int width, height = 0;
if(c.getWidth() > s.getWidth()) {
width = c.getWidth() + s.getWidth();
height = c.getHeight();
} else {
width = s.getWidth() + s.getWidth();
height = c.getHeight();
}
cs = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888);
Canvas comboImage = new Canvas(cs);
comboImage.drawBitmap(c, 0f, 0f, null);
comboImage.drawBitmap(s, c.getWidth(), 0f, null);
// this is an extra bit I added, just incase you want to save the new image somewhere and then return the location
/*String tmpImg = String.valueOf(System.currentTimeMillis()) + ".png";
OutputStream os = null;
try {
os = new FileOutputStream(loc + tmpImg);
cs.compress(CompressFormat.PNG, 100, os);
} catch(IOException e) {
Log.e("combineImages", "problem combining images", e);
}*/
return cs;
}
I want to merge two images and then save them on the Android SDCard.One is from the camera and one from the resources folder. The problem is that i get this error: Caused by: java.lang.IllegalStateException: Immutable bitmap passed to Canvas constructor. Thanks.
Bitmap bottomImage = BitmapFactory.decodeResource(getResources(),R.drawable.blink);
Bitmap topImage = (Bitmap) data.getExtras().get("data");
// As described by Steve Pomeroy in a previous comment,
// use the canvas to combine them.
// Start with the first in the constructor..
Canvas comboImage = new Canvas(bottomImage);
// Then draw the second on top of that
comboImage.drawBitmap(topImage, 0f, 0f, null);
// bottomImage is now a composite of the two.
// To write the file out to the SDCard:
OutputStream os = null;
try {
os = new FileOutputStream("/sdcard/DCIM/Camera/" + "myNewFileName.png");
bottomImage.compress(CompressFormat.PNG, 50, os);
//Bitmap image.compress(CompressFormat.PNG, 50, os);
} catch(IOException e) {
Log.v("error saving","error saving");
e.printStackTrace();
}
Managed to fix it by simply doing this change:
int w = bottomImage.getWidth();
int h = bottomImage.getHeight();
Bitmap new_image = Bitmap.createBitmap(w, h ,bottomImage.getConfig());
The problem now is that it doesn't saves the image. Do you know why?
This will help you =)
Edit: (embed answer from link)
the only static "constructor" for Bitmap returning a mutable one is:
(Class: Bitmap) public static Bitmap createBitmap(int width, int
height, boolean hasAlpha)
Returns: a mutable bitmap with the specified width and height.
So you could work with getPixels/setPixels or like this:
Bitmap bitmapResult = bm.createBitmap(widthOfOld, heightOfOld, hasAlpha);
Canvas c = new Canvas();
c.setDevice(bitmapResult); // drawXY will result on that Bitmap
c.drawBitmap(bitmapOld, left, top, paint);
how to get the drawable from Bitmap: by using the BitmapDrawable-Subclass which extends Drawable, like this:
Bitmap myBitmap = BitmapFactory.decode(path);
Drawable bd = new BitmapDrawable(myBitmap);
The bitmap you are retrieving is immutable, meaning it can't be modified. Although it doesn't specify on the Canvas page that the constructor needs a mutable bitmap, it does.
To create a mutable bitmap, you can use this method.
I'm beating my head against a wall here, and I'm fairly certain I'm doing something stupid, so time to make my stupidity public.
I'm trying to take two images, blend them together into a third image using standard blending algorithms (Hardlight, softlight, overlay, multiply, etc).
Because Android does not have such blend properties build in, I've gone down the path of taking each pixel and combine them using an algorithm. However, the results are garbage. Below is the results of a simple multiply blend (images used, and expected result).
BASE:
BLEND:
EXPECTED RESULT:
GARBAGE RESULT:
Any help would be appreciated. Below is the code, which I've tried to strip out all the "junk", but some may have made it through. I'll clean it up if something isn't clear.
ImageView imageView = (ImageView) findViewById(R.id.ImageView01);
Bitmap base = BitmapFactory.decodeResource(getResources(), R.drawable.base);
Bitmap result = base.copy(Bitmap.Config.RGB_565, true);
Bitmap blend = BitmapFactory.decodeResource(getResources(), R.drawable.blend);
IntBuffer buffBase = IntBuffer.allocate(base.getWidth() * base.getHeight());
base.copyPixelsToBuffer(buffBase);
buffBase.rewind();
IntBuffer buffBlend = IntBuffer.allocate(blend.getWidth() * blend.getHeight());
blend.copyPixelsToBuffer(buffBlend);
buffBlend.rewind();
IntBuffer buffOut = IntBuffer.allocate(base.getWidth() * base.getHeight());
buffOut.rewind();
while (buffOut.position() < buffOut.limit()) {
int filterInt = buffBlend.get();
int srcInt = buffBase.get();
int redValueFilter = Color.red(filterInt);
int greenValueFilter = Color.green(filterInt);
int blueValueFilter = Color.blue(filterInt);
int redValueSrc = Color.red(srcInt);
int greenValueSrc = Color.green(srcInt);
int blueValueSrc = Color.blue(srcInt);
int redValueFinal = multiply(redValueFilter, redValueSrc);
int greenValueFinal = multiply(greenValueFilter, greenValueSrc);
int blueValueFinal = multiply(blueValueFilter, blueValueSrc);
int pixel = Color.argb(255, redValueFinal, greenValueFinal, blueValueFinal);
buffOut.put(pixel);
}
buffOut.rewind();
result.copyPixelsFromBuffer(buffOut);
BitmapDrawable drawable = new BitmapDrawable(getResources(), result);
imageView.setImageDrawable(drawable);
}
int multiply(int in1, int in2) {
return in1 * in2 / 255;
}
After reproducing, I think your issue has to do with manipulating the images in RGB565 mode. As discussed in this post, Bitmaps apparently need to be in ARGB8888 mode to manipulate properly. I first got the expected result on a multiply blend by doing the following:
Resources res = getResources();
BitmapFactory.Options options = new BitmapFactory.Options();
options.inPreferredConfig = Bitmap.Config.ARGB_8888;
Bitmap base = BitmapFactory.decodeResource(res, R.drawable.base, options);
Bitmap blend = BitmapFactory.decodeResource(res, R.drawable.blend, options);
// now base and blend are in ARGB8888 mode, which is what you want
Bitmap result = base.copy(Config.ARGB_8888, true);
// Continue with IntBuffers as before...
Converting the Bitmaps to ARGB8888 mode did seem to work for me, at least with the gradient test patterns. However, it you only need to do Screen or Multiply, you might try this as well:
// Same image creation/reading as above, then:
Paint p = new Paint();
p.setXfermode(new PorterDuffXfermode(Mode.MULTIPLY));
p.setShader(new BitmapShader(blend, TileMode.CLAMP, TileMode.CLAMP));
Canvas c = new Canvas();
c.setBitmap(result);
c.drawBitmap(base, 0, 0, null);
c.drawRect(0, 0, base.getWidth(), base.getHeight(), p);
With that, you aren't doing the per-pixel calculations, but you are limited to the preset PorterDuff.Modes. In my quick (and dirty) testing, this was the only way I was able to get the blending to work on non-gradient images.
Simple overlay you can do this way (for simplicity it is supposed that bmp1 is equal or bigger than bmp2):
private Bitmap bitmapOverlay(Bitmap bmp1, Bitmap bmp2)
{
Bitmap bmOverlay = Bitmap.createBitmap(bmp1.getWidth(), bmp1.getHeight(), bmp1.getConfig());
Canvas canvas = new Canvas(bmOverlay);
canvas.drawBitmap(bmp1, 0, 0, null);
canvas.drawBitmap(bmp2, 0, 0, null);
return bmOverlay;
}
For more complex blending algorithms, maybe you can help yourself with some available Bitmap/Canvas functions.
I have some .png icons that are alpha masks. I need to render them as an drawable image using the Android SDK.
On the iPhone, I use the following to get this result, converting the "image" alpha mask to the 'imageMasked' image using black as a fill:
CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceRGB();
CGContextRef context = CGBitmapContextCreate(NULL, thumbWidth,
thumbHeight, 8, 4*thumbWidth, colorSpace, kCGImageAlphaPremultipliedFirst);
CGRect frame = CGRectMake(0,0,thumbWidth,thumbHeight);
CGContextClipToMask(context, frame, [image CGImage]);
CGContextFillRect(context, frame);
CGImageRef imageMasked = CGBitmapContextCreateImage(context);
CGContextRelease(context);
How do I accomplish the above in Android SDK?
I've started to write the following:
Drawable image = myPngImage;
final int width = image.getMinimumWidth();
final int height = image.getMinimumHeight();
Bitmap imageMasked = Bitmap.createBitmap(width,
height, Config.ARGB_8888);
Canvas canvas = new Canvas(iconMasked);
image.draw(canvas); ???
I'm not finding how to do the clipping on imageMasked using image.
Solved:
Drawable icon = An_Icon_That_Is_An_Alpha_Mask;
int width = icon.getIntrinsicWidth();
int height = icon.getIntrinsicHeight();
Bitmap bm = Bitmap.createBitmap(width, height, Bitmap.Config.ALPHA_8);
Canvas canvas = new Canvas(bm);
icon.setBounds(new Rect(0,0,width,height));
icon.draw(canvas);