Android: Rotation of image around the center - android

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);

Related

Watermark coming on whole image Android

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;
}

Water reflection effect on bitmap

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

Android Crop parent bitmap with the child co-ordinates

I have two ImageView/Bitmap, one for visible background and it not movable one, Another one is movable bitmap on the background view. The movable bitmap have pinch zoom and rotate with matrix. Finally find movable co-ordinates/rect position and crop background bitmap using those rect position. My question is how to calculate/get rect position?.
For my sample, what i need for your view. Pleas post your idea here, it help to every one.
I spend more time to search and after few weeks for get this result.
private Bitmap getCroppedBmp(Bitmap childBmp, Bitmap ParentBmp) {
// viewBmp is movable bitmap, orgBitmap is Parent Bitmap
Bitmap viewBmp = childBmp;
Bitmap orgBitmap = ParentBmp;
float[] v = new float[9];
// get Matrix from View
cropImage.savedMatrix.getValues(v);
float left = v[Matrix.MTRANS_X];
float top = v[Matrix.MTRANS_Y];
// calculate the degree of rotation
float rAngle = Math.round(Math.atan2(v[Matrix.MSKEW_X],
v[Matrix.MSCALE_X]) * (180 / Math.PI));
// Rotate viewBmp
Matrix m = new Matrix();
m.postRotate(rAngle, viewBmp.getWidth() / 2, viewBmp.getHeight() / 2);
Bitmap bmap = Bitmap.createBitmap(viewBmp, 0, 0, viewBmp.getWidth(),
viewBmp.getHeight(), m, true);
// calculate real scale
float rScale = (float) Math
.sqrt((v[Matrix.MSCALE_X] * v[Matrix.MSCALE_X])
+ (v[Matrix.MSKEW_Y] * v[Matrix.MSKEW_Y]));
// Scale viewBmp
Matrix m1 = new Matrix();
m1.postScale(rScale, rScale, width / 2, height / 2);
Bitmap scaledBitmap = Bitmap.createBitmap(bmap, 0, 0, width, height,
m1, true);
// Finally Get cropped Bitmap
Bitmap resultingImage = Bitmap.createBitmap(orgBitmap, (int) left,
(int) top, scaledBitmap.getWidth(), scaledBitmap.getHeight());
return resultingImage;
}

Clearly understand matrix calculation

I have this code snippet. I don't understand the Matrix.preScale and the Bitmap.createBitmap with the matrix passed. What does it mean? Is there any simulation website to understand matrix calculation? Could you give me some websites about mathematics used for graphics? I'm sorry I'm not good at mathematics. :)
public Bitmap createReflectedImages(final Bitmap originalImage) {
final int width = originalImage.getWidth();
final int height = originalImage.getHeight();
final Matrix matrix = new Matrix();
matrix.preScale(1, -1);
final Bitmap reflectionImage = Bitmap.createBitmap(originalImage, 0, (int) (height * imageReflectionRatio),
width, (int) (height - height * imageReflectionRatio), matrix, false);
final Bitmap bitmapWithReflection = Bitmap.createBitmap(width, (int) (height + height * imageReflectionRatio + 400),
Config.ARGB_8888);
final Canvas canvas = new Canvas(bitmapWithReflection);
canvas.drawBitmap(originalImage, 0, 0, null);
final Paint deafaultPaint = new Paint();
deafaultPaint.setColor(color.transparent);
canvas.drawBitmap(reflectionImage, 0, height + reflectionGap, null);
final Paint paint = new Paint();
final LinearGradient shader = new LinearGradient(0, originalImage.getHeight(), 0,
bitmapWithReflection.getHeight() + reflectionGap, 0x70ffffff, 0x00ffffff, TileMode.CLAMP);
paint.setShader(shader);
paint.setXfermode(new PorterDuffXfermode(Mode.DST_IN));
canvas.drawRect(0, height, width, bitmapWithReflection.getHeight() + reflectionGap, paint);
return bitmapWithReflection;
}
Don't think about it too hard, at least not at the early stages.
Just think of a matrix as an array of numbers. In this case, an Android Matrix has 3 rows of 3 numbers. Each number tells an Android graphics function what to do to scale (bigger/smaller), translate (move), rotate (turn) or skew (distort in a 2D plane) the "thing" which the matrix is applied to.
The matrix looks like this (see the docs here).
{Scale X, Skew X, Transform X
Skew Y, Scale Y, Transform Y
Perspective 0, Perspective 1, Perspective 2}
The good news is that you don't need to know any matrix maths, indeed almost no maths, to use matrices in Android. That's what methods like preScale() do for you. To understand the maths behind is not that hard, for most things you only need add, multiply and SOHCAHTOA.
matrix-transform-for-the-mathematically-challenged/
When you read the Matrix documentation, you will see methods for rotate, translate etc with prefixes of 'set', 'post' or 'pre'.
Imagine that you create a new matrix. You then use setRotate() to setup the matrix to do a rotation. You then use preTranslate() to do a translation. Because you used 'pre', the translation happens before the rotation. Had you used 'post', the rotation would happen first. 'set' clears whatever is in the matrix and starts again.
To answer your specific question, new Matrix() creates the 'identity matrix'
{1, 0, 0
0, 1, 0
0, 0, 1}
which scales by 1 (therefore same size) and does no translation, rotation or skew. Therefore, applying the identity matrix will do nothing. The next method is preScale() which is applied to this identity matrix and in the case you've shown, results in a matrix that scales, and does nothing else so could also be done using setScale() or postScale().

How might I add a watermark effect to an image in Android?

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.

Categories

Resources