I'm having problems while trying to rotate a picture with java android canvas.drawImage. I'm doing a little game, and I'm painting different pictures on the screen using my drawImage function. However now I want to rotate some little images, I have created a function called drawMirroredImage for this. However now this little images don't appear on the same place.
Here is my code:
public void drawImage(Image Image, int x, int y) {
canvas.drawBitmap(((AndroidImage) Image).bitmap, x, y, null);
}
public void drawMirroredImage(Image Image, int x, int y) {
canvas.save();
canvas.scale(-1.0f, 1.0f);
canvas.drawBitmap(((AndroidImage) Image).bitmap, x - canvas.getWidth(), y, null);
canvas.restore();
}
Anyone knows what I'm doing wrong?
Lot of thanks for helping
Following will work for you.
I found it somewhere on SO itself but don't remember where.
public static Bitmap getReflectionedBitmap(Context context,int resourceId,Bitmap originalImage,int reflectionGap) {
if(originalImage==null)
originalImage = BitmapFactory.decodeResource(context.getResources(),resourceId);
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
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 in the gap
Paint deafaultPaint = new Paint();
deafaultPaint.setColor(0xffffffff);
canvas.drawRect(0, height, width, height + reflectionGap , deafaultPaint);
canvas.drawBitmap(reflectionImage, 0, height + reflectionGap, null);
Paint paint = new Paint();
LinearGradient shader = new LinearGradient(0,
originalImage.getHeight(), 0, bitmapWithReflection.getHeight()
+ reflectionGap, 0x70ffffff, 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));
canvas.drawRect(0, height, width, bitmapWithReflection.getHeight()
+ reflectionGap, paint);
return bitmapWithReflection;
}
I tweaked the snippet a little bit to use it with resource images as well.
Pass in null as parameter in place of Bitmap if you want to create reflection for images in resource.
Related
I'm working with Java to store and modify .jpg images, (not Android or Swing). I want to transform an image with a new dimension keeping the aspect ratio and filling the background with white color if the new dimension is not proportional to the original image.
BufferedImage image = /*Here i read from disk and load the image */;
image = resizeImage(image, newWidth, newHeight);
ImageIO.write(image, extension, new File(filename + "_" + page + "." + extension));
The function I'm trying to implement is resizeImage: in the example resizes the image but it doesn't keep the aspect ratio.
private static BufferedImage resizeImage(BufferedImage originalImage, int width, int height) {
BufferedImage resizedImage = new BufferedImage(width, height, originalImage.getType());
Graphics2D g = resizedImage.createGraphics();
g.drawImage(originalImage, 0, 0, width, height, null);
g.dispose();
return resizedImage;
}
I think a picture will be more illustrative of what I'm asking for:
If the original image is 200x200 and is asked to resize to 400x300 the result should be a picture with white margin and the original picture resized inside. In this example should be 300x300.
The problem is not how to resize, it's how to fill the remaining image with white and the original resized image on the center of it.
This code worked for me:
private static BufferedImage resizeImage(BufferedImage originalImage, int newWidth, int newHeight) {
BufferedImage resizedImage = new BufferedImage(newWidth, newHeight, originalImage.getType());
Graphics2D graphics = resizedImage.createGraphics();
graphics.setColor(Color.WHITE);
// fill the entire picture with white
graphics.fillRect(0, 0, newWidth, newHeight);
int maxWidth = 0;
int maxHeight = 0;
// go along the width and height in increments of 1 until one value is equal to the specified resize value
while (maxWidth <= newWidth && maxHeight <= newHeight)
{
++maxWidth;
++maxHeight;
}
// calculate the x value with which the original image is centred
int centerX = (resizedImage.getWidth() - maxWidth) / 2;
// calculate the y value with which the original image is centred
int centerY = (resizedImage.getHeight() - maxHeight) / 2;
// draw the original image
graphics.drawImage(originalImage, centerX, centerY, maxWidth, maxHeight, null);
graphics.dispose();
return resizedImage;
}
Before:
After:
I have an image, and I am trying to overlay a cropped version of the image over the original. Something like this:
Original
Overlay Image
Image after the overlay image is cropped to roughly 50%
Right now, my code below reverses what I want, and returns an image like this:
public void setOverlay(ImageView image, Bitmap originalBitmap, double percentageCompleted) {
int percentHeight;
int height = originalBitmap.getHeight();
Bitmap cropped;
if(percentageCompleted == 0){
cropped = Bitmap.createBitmap(overlay, 0, 0, overlay.getWidth() , 0 );
} else {
percentHeight = (int) Math.floor(height * (percentageCompleted));
Log.d("HEIGHT", Double.toString(height));
Log.d("PERCENT Completed", Double.toString(percentageCompleted));
Log.d("PERCENT HEIGHT", Integer.toString(percentHeight));
cropped = Bitmap.createBitmap(overlay, 0, 0, overlay.getWidth() , height-percentHeight);
}
originalBitmap = overlay(originalBitmap, cropped);
//set imageview to new bitmap
image.setImageBitmap(originalBitmap );
}
public Bitmap overlay(Bitmap bmp1, Bitmap bmp2) {
Bitmap bmp3 = bmp1.copy(Bitmap.Config.ARGB_8888,true);//mutable copy
Canvas canvas = new Canvas(bmp3 );
canvas.drawBitmap(bmp2, new Matrix(), null);
return bmp3;
}
I know I could reverse the image files, but I want to start with the original image and have the overlay draw upwards, rather than starting with the overlay, and drawing the original downwards. Any help is appreciated!
You can use this method:
Canvas.drawBitmap(Bitmap bitmap, Rect src, Rect dst, Paint paint)
Here is my overlay method that may meet your need:
public static Bitmap overlay(Bitmap base, Bitmap overlay, Float percentage) {
Bitmap resultBitmap = Bitmap.createBitmap(base.getWidth(), base.getHeight(), Bitmap.Config.ARGB_8888);
Canvas canvas = new Canvas(resultBitmap);
Paint paint = new Paint();
// base bitmap
canvas.drawBitmap(base, 0F, 0F, paint);
// overlay bitmap
int yOffset = (int) (percentage * base.getHeight());
Rect rect = new Rect(0, yOffset, overlay.getWidth(), overlay.getHeight());
canvas.drawBitmap(overlay, rect, rect, paint);
return resultBitmap;
}
I built a simple app that you can pick a photo of yourself, select a border for it and then save it as image. The way I did this is adding 2 ImageViews on top of each other in a parent view. Then converting this parent view to image and save. However with this way, the resulting image size depends on the device screen size. If the device screen is small, a small final image is generated.
What I want is creating an image file with a size of 500x800 pixels at all times regardless of device. What is the correct way to do this?
The preview on the screen could be small, but when I click save button I need it to be exactly 500x800.
First, convert your image to bitmap by :
Bitmap bitmapImage= BitmapFactory.decodeResource(getResources(), R.drawable.large_icon);
Or, if you have Uri of image then use this to convert it to bitmap:
Bitmap bitmap = BitmapFactory.decodeFile(imageUri.getPath());
Both of this will give you a bitmap of your image.
Now to resize your image use this code:
Bitmap scaledBitmap = Bitmap.createScaledBitmap(bitmap, imageWidth, imageHeight, true);
Then convert it into File.
To Add to Jason Answer, we found the best way to scale the image, is to use this to scale it up or down.
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;
}
Please try to below code to save bitmap image as custom height & width, Below is a snippet of code that will allow you to resize a Bitmap.
public Bitmap getResizeBitmap(Bitmap bmp, int newHeight, int newWidth) {
int width = bmp.getWidth();
int height = bmp.getHeight();
float scaleWidth = ((float) newWidth) / width;
float scaleHeight = ((float) newHeight) / height;
// CREATE A MATRIX FOR THE MANIPULATION
Matrix matrix = new Matrix();
// RESIZE THE BIT MAP
matrix.postScale(scaleWidth, scaleHeight);
// RECREATE THE NEW BITMAP
Bitmap resizeBitmap = Bitmap.createBitmap(bmp, 0, 0, width, height, matrix, false);
return resizeBitmap;
}
I want to draw a rounded rectangle with drawRoundRect method in Android.
void drawRoundRect (RectF rect, float rx, float ry, Paint paint)
I'm using Android Studio, and my testing device use Android 6.0.1, API 23
This is part of my code. It works find when I put zeros in rx and ry.
public void draw(Canvas canvas){
canvas.drawColor(Color.WHITE);
canvas.drawRoundRect(rect, 0, 0, pnt);
}
This draws a black rectangle in my screen.
But when I try to make it rounded,
public void draw(Canvas canvas){
canvas.drawColor(Color.WHITE);
canvas.drawRoundRect(rect, 10, 10, pnt);
}
It draws nothing. This only draws white background....
I tried different numbers like 100, 3, 5, 0.03f etc in rx and ry,
but any numbers bigger than 0 make drawRoundRect() not working.
Is there anything wrong with my code...?
Make sure that coordinates in RectF that is used to draw rounded rectangle are correct. That means: rect.left < rect.right and rect.top < rect.bottom.
It seems that Android 7 corrects wrong coordinates itself and draws desired rounded rectangle, but Android 6 is drawing nothing if there is problem with coordinates.
you can try this we have a little calculation but it works awesomely
private void drawRoundedRect(Canvas canvas, float left, float top, float right, float bottom) {
float radius = getHeight() / 2;
canvas.drawCircle(radius, radius, radius, mainPaint);
canvas.drawCircle(right - radius, radius, radius, mainPaint);
canvas.drawRect(left + radius, top, right - radius, bottom, mainPaint);
}
or you can check this
RectF rect = new RectF(10,10,20,20);
canvas.drawRoundRect(rect , 0, 0, mPaint);
Try this,
Bitmap bitmap = Bitmap.createBitmap(
600, // Width
300, // Height
Bitmap.Config.ARGB_8888 // Config
);
Canvas canvas = new Canvas(bitmap);
canvas.drawColor(Color.WHITE);
Paint paint = new Paint();
paint.setStyle(Paint.Style.FILL);
paint.setColor(Color.RED);
paint.setAntiAlias(true);
int offset = 50;
RectF rectF = new RectF(
offset, // left
offset, // top
canvas.getWidth() - offset, // right
canvas.getHeight() - offset // bottom
);
int cornersRadius = 25;
canvas.drawRoundRect(
rectF, // rect
cornersRadius, // rx
cornersRadius, // ry
paint // Paint
);
mImageView.setImageBitmap(bitmap);
You could do this,
RectF rect = new RectF(0f, 0f, width, height);
canvas.drawRoundRect(rect , 0, 0, mPaint);
I'm trying to round corners of a bitmap using this code below. The problem is that no matter what I set the paint's color to, e.g. Color.TRANSPARENT , it is always black. How can I actually clip the corners of a bitmap, not just color them black?
Thanks!
public static Bitmap roundCorners(Bitmap src, int radius) {
//Create a *mutable* location, and a canvas to draw into it
int width = src.getWidth();
int height = src.getHeight();
Bitmap result = Bitmap.createBitmap(width, height, Config.ARGB_8888);
Canvas canvas = new Canvas(result);
Paint paint = new Paint(Paint.ANTI_ALIAS_FLAG);
RectF rect = new RectF(0, 0, width, height);
Shader bitmapShader = new BitmapShader(src, TileMode.CLAMP, TileMode.CLAMP);
paint.setColor(0xFF000000);
paint.setShader(bitmapShader);
canvas.drawRoundRect(rect, radius, radius, paint);
return result;
}
There's an easier method that works in one pass. Just draw a rounded rect but set a BitmapShader on the Paint. This will fill the rounded rect with your bitmap. No need to change the xfermode or to call drawBitmap.