I'm trying to rotate an overlay drawable to represent an overlay item in Android.
I use this:
Bitmap bmpOriginal = BitmapFactory.decodeResource(this.getResources(), R.drawable.map_pin);
Bitmap targetBitmap = Bitmap.createBitmap((bmpOriginal.getWidth()),
(bmpOriginal.getHeight()),
Bitmap.Config.ARGB_8888);
Matrix matrix = new Matrix();
matrix.setRotate((float) lock.getDirection(),(float) (bmpOriginal.getWidth()/2),
(float)(bmpOriginal.getHeight()/2));
Canvas tempCanvas = new Canvas(targetBitmap);
tempCanvas.drawBitmap(bmpOriginal, matrix, null);
Drawable d = new BitmapDrawable(getResources(),targetBitmap);
//overlayitem.setMarker(drawable);
mapItemizedOverlay =
new MyItemizedOverlay<MyItemizedOverlayItem>(d, mapView);
The problem is that the image quality worsens. Pixelization happens. Any solution?
This code worked perfectly with me
Bitmap bmpOriginal = BitmapFactory.decodeResource(this.getResources(), R.drawable.map_pin);
Bitmap targetBitmap = Bitmap.createBitmap((bmpOriginal.getWidth()),
(bmpOriginal.getHeight()),
Bitmap.Config.ARGB_8888);
Paint p = new Paint();
p.setAntiAlias(true);
p.setDither(true);
p.setFilterBitmap(true);
Matrix matrix = new Matrix();
matrix.setRotate((float) lock.getDirection(),(float) (bmpOriginal.getWidth()/2),
(float)(bmpOriginal.getHeight()/2));
RectF rectF = new RectF(0, 0, bmpOriginal.getWidth(), bmpOriginal.getHeight());
matrix.mapRect(rectF);
targetBitmap = Bitmap.createBitmap((int)rectF.width(), (int)rectF.height(), Bitmap.Config.ARGB_8888);
Canvas tempCanvas = new Canvas(targetBitmap);
tempCanvas.drawBitmap(bmpOriginal, matrix, p);
You could try to apply a paint with antialiasing but if its about pixels within the bitmap the only chance is filtering and android has its limits. Depending on the bitmap you might never be able to get it really smooth, i did try a lot but never found anything that would give it a real nice finish
public static Bitmap createScaledBitmap (Bitmap src, int dstWidth, int dstHeight, boolean filter)
the filter boolean should be true, thats all that you can do for filtering afaik
void android.graphics.Canvas.drawBitmap(Bitmap bitmap, Rect src, RectF dst, Paint paint)
here you can apply a paint, you can experiment with settings on this paint, but anti-alias will work on the edges of the bitmap. Shader settings might work on the bitmap as well but there are no shaders that can fix the rotation inaccuracy
Add the following:
Paint p = new Paint();
p.setAntiAlias(true);
p.setDither(true);
p.setFilterBitmap(true);
change the following:
tempCanvas.drawBitmap(bmpOriginal, matrix, null);
to:
tempCanvas.drawBitmap(bmpOriginal, matrix, p);
Related
I am working on image filter app and facing an issue.
So I want to know how to apply colour, saturation and brightness on image view?
(please consider that my image view have only one flat color)
For Color:
public void setImageColor(int color) {
image.setColorFilter(color);
}
For Saturation:
public void setSaturationBitmap(int saturation) {
image.setDrawingCacheEnabled(true);
image.buildDrawingCache();
Bitmap bm = image.getDrawingCache();
Bitmap alteredBitmap = Bitmap.createBitmap(bm.getWidth(), bm.getHeight(), bm.getConfig());
Canvas canvas = new Canvas(alteredBitmap);
Paint paint = new Paint();
paint.reset();
ColorMatrix cm = new ColorMatrix();
cm.setSaturation(satur);
paint.setColorFilter(image.getColorFilter());
paint.setColorFilter(new ColorMatrixColorFilter(cm));
Matrix matrix = new Matrix();
canvas.drawBitmap(bm, matrix, paint);
image.setImageBitmap(alteredBitmap);}
Thank you.
You can edit the bitmap and use it in Image view:
follow this post on SOF:
https://stackoverflow.com/a/35055244/7147289
I'm facing an issue related to Bitmap rotation, issue is follow code rotates the bitmap fine but with a back background when draw rotated bitmap on canvas, I see this only for version 5.0 above and 4.0 I get transparent background... any clue please share.
int resID = context.getResources().getIdentifier(mDrawableName,
"drawable", context.getPackageName());
Matrix mat = new Matrix();
mat.postRotate(i*6%30); // angle to be rotated
Bitmap Logobm = BitmapFactory.decodeResource(context.getResources(), resID) ;
Logobm = Density.getInstance().scaleit(Logobm,
Density.getInstance().getPixelforDP(80), 0);
Logobm = Bitmap.createBitmap(Logobm, 0, 0, Logobm.getWidth(), Logobm.getHeight(), mat, true);
I also get this issue. After Goolge, I find that if you use BitmapFactory.decodeResourceļ¼this issue can't be fixed at some devices. So I use these code instead of BitmapFactory.decodeResource:
Bitmap bitmap = yourBitmap;
Matrix matrix = new Matrix();
matrix.postRotate(angle);
Rect srcR = new Rect(0, 0, bitmap.getWidth(), bitmap.getHeight());
RectF dstR = new RectF(0, 0, bitmap.getWidth(), bitmap.getHeight());
RectF deviceR = new RectF();
matrix.mapRect(deviceR, dstR);
int neww = Math.round(deviceR.width());
int newh = Math.round(deviceR.height());
Bitmap result = Bitmap.createBitmap(neww, newh, Bitmap.Config.ARGB_8888);
result.eraseColor(Color.TRANSPARENT);
Canvas canvas = new Canvas();
canvas.translate(-deviceR.left, -deviceR.top);
canvas.concat(matrix);
Paint paint = new Paint();
paint.setAntiAlias(true);
paint.setFilterBitmap(true);
canvas.setBitmap(result);
canvas.drawBitmap(bitmap, srcR, dstR, paint);
canvas.setBitmap(null);
the 'result' Bitmap is your rotated bitmap with transparent BG.
This is what I have:
Bitmap result = Bitmap.create(600, 600, Config.ARG_8888);
Canvas canvas = new Canvas(result);
canvas.clipPath(path) // custom path is a rotated rectangle that has an offset x and y within the 600x600 rectangle
canvas.drawBitmap(sourceBitmap, 0, 0, new Paint());
canvas.save();
When I check the result bitmap, I only see the clip path which is I want, but I want the result image to be the same size as the clip path and not still 600x600.
Thanks
as i said in the comment above, you can use drawBitmap(Bitmap bitmap, Rect src, Rect dst, Paint paint) to crop your Bitmap result to the cropped one or you can do it directly:
// get the Bitmap
Bitmap b = BitmapFactory.decodeResource(getResources(), R.drawable.ic_launcher);
// setup sample Path
Path path = new Path();
path.moveTo(10, 10);
path.lineTo(30, 10);
path.lineTo(30, 20);
path.close();
RectF bounds = new RectF();
path.computeBounds(bounds, true);
Rect pathBounds = new Rect();
bounds.roundOut(pathBounds);
Bitmap outBitmap = Bitmap.createBitmap(pathBounds.width(), pathBounds.height(), Bitmap.Config.ARGB_8888);
Shader shader = new BitmapShader(b, Shader.TileMode.CLAMP, Shader.TileMode.CLAMP);
Canvas c = new Canvas(outBitmap);
Paint paint = new Paint();
paint.setShader(shader);
c.translate(-pathBounds.left, -pathBounds.top);
c.drawPath(path, paint);
I've been looking for over a day for a solution to this problem but nothing helps, even the answers here. Documentation doesn't explain anything too.
I am simply trying to get a rotation in the direction of another object. The problem is that the bitmap is not rotated around a fixed point, but rather around the bitmaps (0,0).
Here is the code I am having troubles with:
Matrix mtx = new Matrix();
mtx.reset();
mtx.preTranslate(-centerX, -centerY);
mtx.setRotate((float)direction, -centerX, -centerY);
mtx.postTranslate(pivotX, pivotY);
Bitmap rotatedBMP = Bitmap.createBitmap(bitmap, 0, 0, spriteWidth, spriteHeight, mtx, true);
this.bitmap = rotatedBMP;
The weird part is, it doesn't matter how I change the values within pre/postTranslate() and the float arguments in setRotation(). Can someone please help and push me in the right direction? :)
I hope the following sequence of code will help you:
Bitmap targetBitmap = Bitmap.createBitmap(targetWidth, targetHeight, config);
Canvas canvas = new Canvas(targetBitmap);
Matrix matrix = new Matrix();
matrix.setRotate(mRotation,source.getWidth()/2,source.getHeight()/2);
canvas.drawBitmap(source, matrix, new Paint());
If you check the following method from ~frameworks\base\graphics\java\android\graphics\Bitmap.java
public static Bitmap createBitmap(Bitmap source, int x, int y, int width, int height,
Matrix m, boolean filter)
this would explain what it does with rotation and translate.
Edited: optimized code.
public static Bitmap RotateBitmap(Bitmap source, float angle)
{
Matrix matrix = new Matrix();
matrix.postRotate(angle);
return Bitmap.createBitmap(source, 0, 0, source.getWidth(), source.getHeight(), matrix, true);
}
To get Bitmap from resources:
Bitmap source = BitmapFactory.decodeResource(this.getResources(), R.drawable.your_img);
I came back to this problem now that we are finalizing the game and I just thought to post what worked for me.
This is the method for rotating the Matrix:
this.matrix.reset();
this.matrix.setTranslate(this.floatXpos, this.floatYpos);
this.matrix.postRotate((float)this.direction, this.getCenterX(), this.getCenterY());
(this.getCenterX() is basically the bitmaps X position + the bitmaps width / 2)
And the method for Drawing the bitmap (called via a RenderManager Class):
canvas.drawBitmap(this.bitmap, this.matrix, null);
So it is prettey straight forward but I find it abit strange that I couldn't get it to work by setRotate followed by postTranslate. Maybe some knows why this doesn't work? Now all the bitmaps rotate properly but it is not without some minor decrease in bitmap quality :/
Anyways, thanks for your help!
You can also rotate the ImageView using a RotateAnimation:
RotateAnimation rotateAnimation = new RotateAnimation(from, to,
Animation.RELATIVE_TO_SELF, 0.5f, Animation.RELATIVE_TO_SELF,
0.5f);
rotateAnimation.setInterpolator(new LinearInterpolator());
rotateAnimation.setDuration(ANIMATION_DURATION);
rotateAnimation.setFillAfter(true);
imageView.startAnimation(rotateAnimation);
You can use something like following:
Matrix matrix = new Matrix();
matrix.setRotate(mRotation,source.getWidth()/2,source.getHeight()/2);
RectF rectF = new RectF(0, 0, source.getWidth(), source.getHeight());
matrix.mapRect(rectF);
Bitmap targetBitmap = Bitmap.createBitmap(rectF.width(), rectF.height(), config);
Canvas canvas = new Canvas(targetBitmap);
canvas.drawBitmap(source, matrix, new Paint());
Look at the sample from Google called Lunar Lander, the ship image there is rotated dynamically.
Lunar Lander code sample
I used this configurations and still have the problem of pixelization :
Bitmap bmpOriginal = BitmapFactory.decodeResource(this.getResources(), R.drawable.map_pin);
Bitmap targetBitmap = Bitmap.createBitmap((bmpOriginal.getWidth()),
(bmpOriginal.getHeight()),
Bitmap.Config.ARGB_8888);
Paint p = new Paint();
p.setAntiAlias(true);
Matrix matrix = new Matrix();
matrix.setRotate((float) lock.getDirection(),(float) (bmpOriginal.getWidth()/2),
(float)(bmpOriginal.getHeight()/2));
RectF rectF = new RectF(0, 0, bmpOriginal.getWidth(), bmpOriginal.getHeight());
matrix.mapRect(rectF);
targetBitmap = Bitmap.createBitmap((int)rectF.width(), (int)rectF.height(), Bitmap.Config.ARGB_8888);
Canvas tempCanvas = new Canvas(targetBitmap);
tempCanvas.drawBitmap(bmpOriginal, matrix, p);
matrix.reset();
matrix.setTranslate( anchor.x, anchor.y );
matrix.postRotate((float) rotation , 0,0);
matrix.postTranslate(positionOfAnchor.x, positionOfAnchor.x);
c.drawBitmap(bitmap, matrix, null);
I've been looking for over a day for a solution to this problem but nothing helps, even the answers here. Documentation doesn't explain anything too.
I am simply trying to get a rotation in the direction of another object. The problem is that the bitmap is not rotated around a fixed point, but rather around the bitmaps (0,0).
Here is the code I am having troubles with:
Matrix mtx = new Matrix();
mtx.reset();
mtx.preTranslate(-centerX, -centerY);
mtx.setRotate((float)direction, -centerX, -centerY);
mtx.postTranslate(pivotX, pivotY);
Bitmap rotatedBMP = Bitmap.createBitmap(bitmap, 0, 0, spriteWidth, spriteHeight, mtx, true);
this.bitmap = rotatedBMP;
The weird part is, it doesn't matter how I change the values within pre/postTranslate() and the float arguments in setRotation(). Can someone please help and push me in the right direction? :)
I hope the following sequence of code will help you:
Bitmap targetBitmap = Bitmap.createBitmap(targetWidth, targetHeight, config);
Canvas canvas = new Canvas(targetBitmap);
Matrix matrix = new Matrix();
matrix.setRotate(mRotation,source.getWidth()/2,source.getHeight()/2);
canvas.drawBitmap(source, matrix, new Paint());
If you check the following method from ~frameworks\base\graphics\java\android\graphics\Bitmap.java
public static Bitmap createBitmap(Bitmap source, int x, int y, int width, int height,
Matrix m, boolean filter)
this would explain what it does with rotation and translate.
Edited: optimized code.
public static Bitmap RotateBitmap(Bitmap source, float angle)
{
Matrix matrix = new Matrix();
matrix.postRotate(angle);
return Bitmap.createBitmap(source, 0, 0, source.getWidth(), source.getHeight(), matrix, true);
}
To get Bitmap from resources:
Bitmap source = BitmapFactory.decodeResource(this.getResources(), R.drawable.your_img);
I came back to this problem now that we are finalizing the game and I just thought to post what worked for me.
This is the method for rotating the Matrix:
this.matrix.reset();
this.matrix.setTranslate(this.floatXpos, this.floatYpos);
this.matrix.postRotate((float)this.direction, this.getCenterX(), this.getCenterY());
(this.getCenterX() is basically the bitmaps X position + the bitmaps width / 2)
And the method for Drawing the bitmap (called via a RenderManager Class):
canvas.drawBitmap(this.bitmap, this.matrix, null);
So it is prettey straight forward but I find it abit strange that I couldn't get it to work by setRotate followed by postTranslate. Maybe some knows why this doesn't work? Now all the bitmaps rotate properly but it is not without some minor decrease in bitmap quality :/
Anyways, thanks for your help!
You can also rotate the ImageView using a RotateAnimation:
RotateAnimation rotateAnimation = new RotateAnimation(from, to,
Animation.RELATIVE_TO_SELF, 0.5f, Animation.RELATIVE_TO_SELF,
0.5f);
rotateAnimation.setInterpolator(new LinearInterpolator());
rotateAnimation.setDuration(ANIMATION_DURATION);
rotateAnimation.setFillAfter(true);
imageView.startAnimation(rotateAnimation);
You can use something like following:
Matrix matrix = new Matrix();
matrix.setRotate(mRotation,source.getWidth()/2,source.getHeight()/2);
RectF rectF = new RectF(0, 0, source.getWidth(), source.getHeight());
matrix.mapRect(rectF);
Bitmap targetBitmap = Bitmap.createBitmap(rectF.width(), rectF.height(), config);
Canvas canvas = new Canvas(targetBitmap);
canvas.drawBitmap(source, matrix, new Paint());
Look at the sample from Google called Lunar Lander, the ship image there is rotated dynamically.
Lunar Lander code sample
I used this configurations and still have the problem of pixelization :
Bitmap bmpOriginal = BitmapFactory.decodeResource(this.getResources(), R.drawable.map_pin);
Bitmap targetBitmap = Bitmap.createBitmap((bmpOriginal.getWidth()),
(bmpOriginal.getHeight()),
Bitmap.Config.ARGB_8888);
Paint p = new Paint();
p.setAntiAlias(true);
Matrix matrix = new Matrix();
matrix.setRotate((float) lock.getDirection(),(float) (bmpOriginal.getWidth()/2),
(float)(bmpOriginal.getHeight()/2));
RectF rectF = new RectF(0, 0, bmpOriginal.getWidth(), bmpOriginal.getHeight());
matrix.mapRect(rectF);
targetBitmap = Bitmap.createBitmap((int)rectF.width(), (int)rectF.height(), Bitmap.Config.ARGB_8888);
Canvas tempCanvas = new Canvas(targetBitmap);
tempCanvas.drawBitmap(bmpOriginal, matrix, p);
matrix.reset();
matrix.setTranslate( anchor.x, anchor.y );
matrix.postRotate((float) rotation , 0,0);
matrix.postTranslate(positionOfAnchor.x, positionOfAnchor.x);
c.drawBitmap(bitmap, matrix, null);