I trying to achieve water reflection effect on bitmap. As I saw some apps called water reflection. I know how to do the reflection of the image but the wave on the image is what making me confused on how it is done.
see this image for example
I did many apps on bitmap manipulation but this is quite hard to achieve.
So any idea on where to start. Just an idea to start can be helpful.
For any one needed, I tried some simple tricks to get as closer as water reflection effect. It is not great but it looks fine to me.
I used two methods
Bitmap reflection method (give bitmap as a parameter)
public static Bitmap Reflection(Bitmap imageBitmap) {
int width = imageBitmap.getWidth();
int height = imageBitmap.getHeight();
Matrix matrix = new Matrix();
matrix.preScale(1, -1);
Bitmap reflectionImage = Bitmap.createBitmap(imageBitmap, 0,
0, width, height , matrix, false);
Bitmap newbit=Bitmap.createScaledBitmap(reflectionImage, reflectionImage.getWidth()/8, reflectionImage.getHeight()/8, true);
Bitmap newbit1=Bitmap.createScaledBitmap(newbit, newbit.getWidth()*8, newbit.getHeight()*8, true);
Bitmap scalednew=Bitmap.createScaledBitmap(newbit1, width, height-(height/4), true);
Bitmap newscaledone=overlay(scalednew);
reflectionImage=newscaledone;
Bitmap reflectedBitmap = Bitmap.createBitmap(width,
(height + height), Config.ARGB_8888);
Canvas canvas = new Canvas(reflectedBitmap);
canvas.drawBitmap(imageBitmap, 0, 0, null);
Paint defaultPaint = new Paint();
canvas.drawRect(0, height, width, height, defaultPaint);
canvas.drawBitmap(reflectionImage, 0, height , null);
Paint paint = new Paint();
paint.setXfermode(new PorterDuffXfermode(Mode.DST_IN));
canvas.drawRect(0, height, width, reflectedBitmap.getHeight()
, paint);
return reflectedBitmap;
}
Bitmap overlay method. I am taking a wave bitmap with some opacity to overlay on the reflected image. So that it may look like water.
Bitmap wavebitmap=BitmapFactory.decodeResource(getResources(), R.drawable.waves1);
private static Bitmap overlay( Bitmap bmp2) {
Bitmap bmp1=WaterReflectionMainActivity.wavebitmap;
Bitmap bmp1new =Bitmap.createScaledBitmap(bmp1, bmp2.getWidth(), bmp2.getHeight(), true);
Bitmap bmOverlay = Bitmap.createBitmap(bmp1new.getWidth(), bmp1new.getHeight(), bmp1new.getConfig());
Canvas canvas = new Canvas(bmOverlay);
canvas.drawBitmap(bmp2, new Matrix(), null);
canvas.drawBitmap(bmp1new, new Matrix(), null);
return bmOverlay;
}
Well this is my version of water effect, I know this looks shit.
So if anyone still got some better effect please share your code .
thank you
Tutorial related to this: http://www.xaraxone.com/webxealot/workbook34/page_4.htm
Also have a read at this question: Add water effect on bitmap android.
Have a read at both of them, i hope you will get an idea from this
You may also want to look through these: 1, 2, 3
This is just an idea but basically, what you need is to apply a deformation on the bottom part of the image, meaning that for each pixel on the bottom half, you compute a position to get it's color from the top picture.
Here's a pseudo code to give you a hint :
for (int x = 0; x < width; x++) {
for (int y = 0; y < img.height; y++) {
// Compute a position on the original image
// tweak the values heres to get the effect you want
sourceX = x + (int) (cos(10000.0 / y) * 20);
sourceY = img.height - y - 1 +(int)( sin(y* 0.5) * 20);
// Maybe check the range of sourceX and source Y
int color = img.getColor(sourceX, sourceY)
outptut.setColor(x, y + img.height, color);
}
}
you can achieve this by masking may this code will help you
http://www.seeques.com/22527681/how-can-do-this-effect-in-android-may-be-android-bitmap-masking-effect.html
EDIT
also see this for reference
http://code.google.com/p/android-ripple-demo/source/browse/#svn%2Ftrunk%2Fsrc%2Fcom%2Fkesalin%2FRippleDemo
https://github.com/esteewhy/whater
http://code.google.com/p/waterrippleeffect/source/browse/trunk/src/com/example/android/watereffect/WaterEffectView.java?r=3
android noise effect on bitmap
Related
I want to implement cover flow as below
I have tried Carousel, but its not the same thing. Did some google search was not able to find something even near to the cover flow implemented in given example.
Definitely have a look at this, FancyCoverFlow.
There is a demo app for it in the Play store as well that shows the reflection requirement you'd like.
have you tried this:
blog post
public Bitmap getRefelection(Bitmap image) {
// The gap we want between the reflection and the original image
final int reflectionGap = 0;
// Get you bit map from drawable folder
Bitmap originalImage = image;
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
/*if(bitmapWithReflection!=null && !bitmapWithReflection.isRecycled()){
bitmapWithReflection.recycle();
bitmapWithReflection=null;
}*/
Bitmap reflectionImage = Bitmap.createBitmap(originalImage, 0,
height / 2, width, height / 2, matrix, false);
// Create a new bitmap with same width but taller to fit reflection
Bitmap bitmapWithReflection = Bitmap.createBitmap(width,(height + height / 2), 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 the reflection Image
canvas.drawBitmap(reflectionImage, 0, height + reflectionGap, null);
// Create a shader that is a linear gradient that covers the reflection
Paint paint = new Paint();
LinearGradient shader = new LinearGradient(0,
originalImage.getHeight(), 0, bitmapWithReflection.getHeight()
+ reflectionGap, 0x40ffffff, 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
canvas.drawRect(0, height, width, bitmapWithReflection.getHeight()
+ reflectionGap, paint);
if(originalImage!=null && originalImage.isRecycled()){
originalImage.recycle();
originalImage=null;
}
if(reflectionImage!=null && reflectionImage.isRecycled()){
reflectionImage.recycle();
reflectionImage=null;
}
return bitmapWithReflection;
}
Have you gone through the Android Coverflow which is bit different form the Carousel which you want.
I made cover flow widget which is not dependent on gallery.
You can find it here. I will add some samples later.
http://applm.github.io/ma-components/
I have tried several hours to rotate a bitmap with no success. I have read numerous articles about this subject on this web site and it seems the prefered solution involves creating a temporary canvas. Well I did this and I still do not see a roated bitmap.
My bitmap is a 40x40 blue square and I am trying to rotate it 45 degrees. Thats not asking for much is it? When the code runs, the bitmap that appears on the screen is the non-rotated original. ( I have also tried a translate with no success as well)
Here is my code:
// Load the bitmap resource
fillBMP2 = BitmapFactory.decodeResource(context.getResources(), R.drawable.test1);
// Copy to a mutable bitmap
mb = fillBMP2.copy(Bitmap.Config.ARGB_8888, true);
// Create canvas to draw to
Canvas offscreenCanvas = new Canvas (mb);
// Create Matrix so I can rotate it
Matrix matrix = new Matrix();
matrix.setRotate (45);
offscreenCanvas.setMatrix (matrix);
// Send the contents of the canvas into a bitmap
offscreenCanvas.setBitmap(mb);
Later in an OnDraw I do the following:
canvas.drawBitmap(mb, 200, 200, null);
Any ideas what I am doing wrong? Seems like it should work.
Thanks
Try using this
Matrix matrix = new Matrix();
matrix.setRotate(15);
canvas.drawBitmap(bmp, matrix, paint);
setRotation method takes in a float representing
the degrees of rotation.
Try this...
Matrix matrix = new Matrix();
float px = 200;
float py = 200;
matrix.postTranslate(-bitmap.getWidth()/2, -bitmap.getWidth()/2);
matrix.postRotate(45);
matrix.postTranslate(px, py);
canvas.drawBitmap(bitmap, matrix, paint);
You definitely want to use transformations: check out this link.
Basically it's this:
// save the canvas
ctx.save();
// move origin to center
ctx.translate(x,y);
// rotate
ctx.rotate(angle * (Math.PI / 180));
// draw image
ctx.drawImage(image, x, y, w, h, .w/2, h/2, w, h);
// restore
ctx.restore();
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 am trying to build a Magnify tool in my Android app. For this, I have an ImageView, which I converted to Bitmap (with some zoom/scale factor).
imageView.setDrawingCacheEnabled(true);
Bitmap drawingCache = imageView.getDrawingCache(true);
Matrix matrix = new Matrix();
matrix.postScale(5, 5);
Bitmap viewCapture = Bitmap.createBitmap(drawingCache, 0, 0,
drawingCache.getWidth(),
drawingCache.getHeight(),
matrix, true);
imageView.setDrawingCacheEnabled(false);
Now, I am drawing this Bitmap image "viewCapture" to my canvas. Here, I want only portion of the image to be rendered on the canvas.
I tried using approaches: "setRectToRect() on Matrix", "canvas.drawBitmap(bitmap, src, dst, paint)". But, didn't work out appropriately.
Would using SurfaceViews be helpful? Has anyone come across this situation? Please post your thoughts/ideas.
Why not just use the following?
Canvas.drawBitmap(Bitmap bitmap, Rect src, RectF dst, Paint paint)
src corresponds to which region of the bitmap you want to draw and dst says where you want the bitmap drawn. You can read more about it here: http://developer.android.com/reference/android/graphics/Canvas.html
When I do that, I get a smaller image of the bitmap, instead of cropped image. Following is the snippet I have used.
Canvas c = holder.lockCanvas();
c.drawRGB(10, 10, 10);
Rect src = new Rect((int)x - _image.getWidth(), (int) y - _image.getHeight(), (int)x + _image.getWidth(), (int) y + _image.getHeight());
RectF dst = new RectF((int)x - 50, (int) y - 50, (int)x + 50, (int) y + 50);
c.drawBitmap(_image, src, dst, null);
holder.unlockCanvasAndPost(c);
I'm trying to rotate an image around the center. This works generally using RotateAnimation, but I want to have it a bit faster. I'm now using the SurfaceView pattern with a separate drawing thread.
This is code, which draws the bitmap correctly (depending on the outer "heading")
heading = angle in degrees,
bitmap = the bitmap,
w = width of the bitmap,
h = height of the bitmap.
Matrix m = new Matrix();
m.preRotate(heading, w/2, h/2);
m.setTranslate(50,50);
canvas.drawBitmap(bitmap, m, null);
Drawback: The image is a circle and the code above produces visible aliasing effects...
The code below is also rotating the image, but while rotating (say from 0 to 45 degrees clockwise) the center of the new image moves bottom/right. I suppose, the eccentric effect is due to the enlarged width/height of the new image ?? However, this code doesn't produce aliasing, if filter=true is set. Is there a way to use code #1 but have sort of anti-aliasing or use code #2 but getting rid of the center movement?
Matrix m = new Matrix();
m.preRotate(heading, w/2, h/2);
m.setTranslate(50,50);
Bitmap rbmp = Bitmap.createBitmap(bitmap, 0, 0, w, h, m, true);
canvas.drawBitmap(rbmp, 50, 50, null);
UPDATE: As result of the discussion in this thread the correct version of code #2 (anti-aliasing and correct rotation) would look like this (offset of 50,50 omitted):
Matrix m = new Matrix();
m.setRotate(heading, w/2, h/2);
Bitmap rbpm = Bitmap.createBitmap(bitmap, 0, 0, w, h, m, true);
canvas.drawBitmap(rbpm, (w - rbpm.getWidth())/2, (h - rbpm.getHeight())/2, null);
Thanks.
Find the center of the original image and for the new image and center using that:
Matrix minMatrix = new Matrix();
//height and width are set earlier.
Bitmap minBitmap = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888);
Canvas minCanvas = new Canvas(minBitmap);
int minwidth = bitmapMin.getWidth();
int minheight = bitmapMin.getHeight();
int centrex = minwidth/2;
int centrey = minheight/2;
minMatrix.setRotate(mindegrees, centrex, centrey);
Bitmap newmin = Bitmap.createBitmap(minBitmap, 0, 0, (int) minwidth, (int) minheight, minMatrix, true);
minCanvas.drawBitmap(newmin, (centrex - newmin.getWidth()/2), (centrey - newmin.getHeight()/2), null);
minCanvas.setBitmap(minBitmap);