Related
I'm facing an issue that I'm drawing an image with PDFbox, when I draw it without rotation I got the correct dimensions but when I draw it with rotation the dimensions will be smaller.
Here are the images and the code:
Without rotation
With rotation 45 degree
The code:
public void placeImage(String imagePath, float x, float y, float rotation, float width, float height) throws Exception {
File imageFile;
boolean isTemp = false;
if (imagePath.contains("http")) {
imageFile = saveImageFromUrlToTempFile(imagePath);
isTemp = true;
} else {
imageFile = new File(imagePath);
}
PDImageXObject imageToPutInside = PDImageXObject.createFromFileByExtension(imageFile, outputDocument);
float newWidth;
float newHeight;
float imageHeight = imageToPutInside.getHeight();
float imageWidth = imageToPutInside.getWidth();
if (imageHeight > imageWidth) {
newHeight = height > imageHeight ? imageHeight : height;
newWidth = (newHeight * imageToPutInside.getWidth()) / imageToPutInside.getHeight();
} else {
newWidth = width > imageWidth ? imageWidth : width;
newHeight = (newWidth * imageToPutInside.getHeight()) / imageToPutInside.getWidth();
}
x = x + ((width - newWidth) / 2);
y = y + ((height - newHeight) / 2);
y = calculateYAxisFromTop(y) - newHeight;
outputPageContentStream.saveGraphicsState();
AffineTransform transform = new AffineTransform(newWidth, 0, 0, newHeight, x, y);
if(rotation != 0) {
transform.concatenate(AffineTransform.getRotateInstance(rotation, 0.5, 0.5));
}
outputPageContentStream.drawImage(imageToPutInside, new Matrix(transform));
outputPageContentStream.restoreGraphicsState();
if (isTemp) {
imageFile.delete();
}
}
Could you please help me with this?
Image sample
I have this method written for cropping my image, but HEIGHT dimension doesnt work on the cropping, only weight is done right. I cant find the issue. I want to use my screen width and height as a dynamic width and height.
public Bitmap cropToSquare(Bitmap bitmap){
int width = mScreenWidth ;
int height = mScreenHeight;
int newWidth = width - 2 * 10;
int newHeight = (height- newWidth) / 2;
Bitmap cropImg = Bitmap.createBitmap(bitmap, 0, 0, newWidth, newHeight);
return cropImg; }
}
Here is my solution:
public static Bitmap getResizedClippedBitmap (Bitmap bm, int newWidth, int newHeight) {
Bitmap targetBitmap = Bitmap.createBitmap(newWidth, newHeight, Bitmap.Config.ARGB_8888);
Canvas canvas = new Canvas(targetBitmap);
float originalWidth = bm.getWidth();
float originalHeight = bm.getHeight();
float scale, xTranslation = 0.0f, yTranslation = 0.0f;
if (originalWidth > originalHeight) {
scale = newHeight/originalHeight;
xTranslation = (newWidth - originalWidth * scale)/2.0f;
}
else {
scale = newWidth / originalWidth;
yTranslation = (newHeight - originalHeight * scale)/2.0f;
}
Matrix transformation = new Matrix();
transformation.postTranslate(xTranslation, yTranslation);
transformation.preScale(scale, scale);
Paint paint = new Paint();
paint.setFilterBitmap(true);
canvas.drawBitmap(bm, transformation, paint);
return targetBitmap;
}
You can find some other utils here: BitmapUtils.java
Hope it helps.
I have been working on an android application. There is feature in my application which requires an image with exact dimensions of device screen, for which i am using this code,
Intent cropIntent = new Intent("com.android.camera.action.CROP");
cropIntent.setDataAndType(picUri, "image/*");
cropIntent.putExtra("crop", "true");
cropIntent.putExtra("aspectX", 0);
cropIntent.putExtra("aspectY", 0);
cropIntent.putExtra("outputX", width);
cropIntent.putExtra("outputY", height);
cropIntent.putExtra("return-data", true);
but the problem with this code is that since aspect ratio has been set to zero, in some devices like samsung, the crop window is in square size and cannot be adjusted. So how could i set the aspect ratio in aspectX as well as aspectY field so that there is no problem in image cropping,
I have also written a java progrem to calculate aspect ratio but it doesnt seem to work nice with all resolutions.
import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.io.IOException;
class AspectRatio
{ public static void main(String args[])
{ BufferedReader buff=new BufferedReader(new InputStreamReader(System.in));
int width=0,height=0;
try
{ System.out.print("Enter the width of the screen:");
width=Integer.parseInt(buff.readLine());
System.out.println("Enter the height of the screen:");
height=Integer.parseInt(buff.readLine());
}
catch(IOException e)
{ e.printStackTrace();
}
int factor=0;
for(int i=2;i<new AspectRatio().minimum(width,height)/2;i++)
{ if(width%i==0&&height%1==0)
{ factor=i;
}
}
System.out.println("The aspect ratio is:"+width/factor+":"+height/factor);
}
public int minimum(int a,int b)
{ return (a<b?a:b);
}
}
you can get the Width and Height from the System using the next Class :
DisplayMetrics
check the link it will also give the example how to use this class..
this is my helper class to reduce any image with perfect ratio and it works with image taken from camera and img on the device:
public class ImageUtils {
private static final String TAG = "ImageUtils";
private static final float maxHeight = 1280.0f;
private static final float maxWidth = 1280.0f;
public static byte[] compressImage(String imagePath) {
Bitmap scaledBitmap = null;
BitmapFactory.Options options = new BitmapFactory.Options();
options.inJustDecodeBounds = true;
Bitmap bmp = BitmapFactory.decodeFile(imagePath, options);
int actualHeight = options.outHeight;
int actualWidth = options.outWidth;
float imgRatio = (float) actualWidth / (float) actualHeight;
float maxRatio = maxWidth / maxHeight;
if (actualHeight > maxHeight || actualWidth > maxWidth) {
if (imgRatio < maxRatio) {
imgRatio = maxHeight / actualHeight;
actualWidth = (int) (imgRatio * actualWidth);
actualHeight = (int) maxHeight;
} else if (imgRatio > maxRatio) {
imgRatio = maxWidth / actualWidth;
actualHeight = (int) (imgRatio * actualHeight);
actualWidth = (int) maxWidth;
} else {
actualHeight = (int) maxHeight;
actualWidth = (int) maxWidth;
}
}
options.inSampleSize = ImageUtils.calculateInSampleSize(options, actualWidth, actualHeight);
options.inJustDecodeBounds = false;
options.inDither = false;
options.inPurgeable = true;
options.inInputShareable = true;
options.inTempStorage = new byte[16 * 1024];
try {
bmp = BitmapFactory.decodeFile(imagePath, options);
} catch (OutOfMemoryError exception) {
exception.printStackTrace();
}
try {
scaledBitmap = Bitmap.createBitmap(actualWidth, actualHeight, Bitmap.Config.ARGB_8888);
} catch (OutOfMemoryError exception) {
exception.printStackTrace();
}
float ratioX = actualWidth / (float) options.outWidth;
float ratioY = actualHeight / (float) options.outHeight;
float middleX = actualWidth / 2.0f;
float middleY = actualHeight / 2.0f;
Matrix scaleMatrix = new Matrix();
scaleMatrix.setScale(ratioX, ratioY, middleX, middleY);
Canvas canvas = new Canvas(scaledBitmap);
canvas.setMatrix(scaleMatrix);
canvas.drawBitmap(bmp, middleX - bmp.getWidth() / 2, middleY - bmp.getHeight() / 2, new Paint(Paint.FILTER_BITMAP_FLAG));
ExifInterface exif;
try {
exif = new ExifInterface(imagePath);
int orientation = exif.getAttributeInt(ExifInterface.TAG_ORIENTATION, 0);
Matrix matrix = new Matrix();
if (orientation == 6) {
matrix.postRotate(90);
} else if (orientation == 3) {
matrix.postRotate(180);
} else if (orientation == 8) {
matrix.postRotate(270);
}
scaledBitmap = Bitmap.createBitmap(scaledBitmap, 0, 0, scaledBitmap.getWidth(), scaledBitmap.getHeight(), matrix, true);
} catch (IOException e) {
e.printStackTrace();
}
ByteArrayOutputStream out = new ByteArrayOutputStream();
scaledBitmap.compress(Bitmap.CompressFormat.JPEG, 85, out);
return out.toByteArray();
}
public static boolean compressImage(Bitmap image, FileOutputStream fos){
Bitmap scaledBitmap = null;
int actualHeight = image.getHeight();
int actualWidth = image.getWidth();
float imgRatio = (float) actualWidth / (float) actualHeight;
float maxRatio = maxWidth / maxHeight;
if (actualHeight > maxHeight || actualWidth > maxWidth) {
if (imgRatio < maxRatio) {
imgRatio = maxHeight / actualHeight;
actualWidth = (int) (imgRatio * actualWidth);
actualHeight = (int) maxHeight;
} else if (imgRatio > maxRatio) {
imgRatio = maxWidth / actualWidth;
actualHeight = (int) (imgRatio * actualHeight);
actualWidth = (int) maxWidth;
} else {
actualHeight = (int) maxHeight;
actualWidth = (int) maxWidth;
}
}
Log.d(TAG, "ActualHeight " + actualHeight);
Log.d(TAG, "ActualHidht " + actualWidth);
BitmapFactory.Options options = new BitmapFactory.Options();
options.inSampleSize = ImageUtils.calculateInSampleSize(options, actualWidth, actualHeight);
options.inJustDecodeBounds = false;
options.inDither = false;
options.inPurgeable = true;
options.inInputShareable = true;
options.inTempStorage = new byte[16 * 1024];
Bitmap bmp = null;
try {
// int bytes = byteSizeOf(image);
// //or we can calculate bytes this way. Use a different value than 4 if you don't use 32bit images.
// //int bytes = b.getWidth()*b.getHeight()*4;
// ByteBuffer buffer = ByteBuffer.allocate(bytes); //Create a new buffer
// image.copyPixelsToBuffer(buffer); //Move the byte data to the buffer
// byte[] array = buffer.array(); //Get the underlying array containing the data.
// bmp = BitmapFactory.decodeByteArray(array, 0, array.length, options);
ByteArrayOutputStream blob = new ByteArrayOutputStream();
image.compress(Bitmap.CompressFormat.PNG, 0 /*ignored for PNG*/, blob);
byte[] bitmapdata = blob.toByteArray();
bmp = BitmapFactory.decodeByteArray(bitmapdata , 0, bitmapdata.length);
} catch (OutOfMemoryError exception) {
exception.printStackTrace();
}
try {
scaledBitmap = Bitmap.createBitmap(actualWidth, actualHeight, Bitmap.Config.ARGB_8888);
} catch (OutOfMemoryError exception) {
exception.printStackTrace();
}
float ratioX = actualWidth / (float) options.outWidth;
float ratioY = actualHeight / (float) options.outHeight;
float middleX = actualWidth / 2.0f;
float middleY = actualHeight / 2.0f;
Matrix scaleMatrix = new Matrix();
scaleMatrix.setScale(ratioX, ratioY, middleX, middleY);
Canvas canvas = new Canvas(scaledBitmap);
canvas.setMatrix(scaleMatrix);
canvas.drawBitmap(bmp, middleX - bmp.getWidth() / 2, middleY - bmp.getHeight() / 2, new Paint(Paint.FILTER_BITMAP_FLAG));
// ExifInterface exif;
// try {
//// exif = new ExifInterface(imagePath);
//// int orientation = exif.getAttributeInt(ExifInterface.TAG_ORIENTATION, 0);
//// Matrix matrix = new Matrix();
//// if (orientation == 6) {
//// matrix.postRotate(90);
//// } else if (orientation == 3) {
//// matrix.postRotate(180);
//// } else if (orientation == 8) {
//// matrix.postRotate(270);
//// }
//
// } catch (IOException e) {
// e.printStackTrace();
// }
scaledBitmap = Bitmap.createBitmap(scaledBitmap, 0, 0, scaledBitmap.getWidth(), scaledBitmap.getHeight(), null, true);
scaledBitmap.compress(Bitmap.CompressFormat.JPEG, 85, fos);
return true;
}
public static void compressImage(String imagePath, FileOutputStream fos) {
Bitmap scaledBitmap = null;
BitmapFactory.Options options = new BitmapFactory.Options();
options.inJustDecodeBounds = true;
Bitmap bmp = BitmapFactory.decodeFile(imagePath, options);
int actualHeight = options.outHeight;
int actualWidth = options.outWidth;
float imgRatio = (float) actualWidth / (float) actualHeight;
float maxRatio = maxWidth / maxHeight;
if (actualHeight > maxHeight || actualWidth > maxWidth) {
if (imgRatio < maxRatio) {
imgRatio = maxHeight / actualHeight;
actualWidth = (int) (imgRatio * actualWidth);
actualHeight = (int) maxHeight;
} else if (imgRatio > maxRatio) {
imgRatio = maxWidth / actualWidth;
actualHeight = (int) (imgRatio * actualHeight);
actualWidth = (int) maxWidth;
} else {
actualHeight = (int) maxHeight;
actualWidth = (int) maxWidth;
}
}
options.inSampleSize = ImageUtils.calculateInSampleSize(options, actualWidth, actualHeight);
options.inJustDecodeBounds = false;
options.inDither = false;
options.inPurgeable = true;
options.inInputShareable = true;
options.inTempStorage = new byte[16 * 1024];
try {
bmp = BitmapFactory.decodeFile(imagePath, options);
} catch (OutOfMemoryError exception) {
exception.printStackTrace();
}
try {
scaledBitmap = Bitmap.createBitmap(actualWidth, actualHeight, Bitmap.Config.ARGB_8888);
} catch (OutOfMemoryError exception) {
exception.printStackTrace();
}
float ratioX = actualWidth / (float) options.outWidth;
float ratioY = actualHeight / (float) options.outHeight;
float middleX = actualWidth / 2.0f;
float middleY = actualHeight / 2.0f;
Matrix scaleMatrix = new Matrix();
scaleMatrix.setScale(ratioX, ratioY, middleX, middleY);
Canvas canvas = new Canvas(scaledBitmap);
canvas.setMatrix(scaleMatrix);
canvas.drawBitmap(bmp, middleX - bmp.getWidth() / 2, middleY - bmp.getHeight() / 2, new Paint(Paint.FILTER_BITMAP_FLAG));
ExifInterface exif;
try {
exif = new ExifInterface(imagePath);
int orientation = exif.getAttributeInt(ExifInterface.TAG_ORIENTATION, 0);
Matrix matrix = new Matrix();
if (orientation == 6) {
matrix.postRotate(90);
} else if (orientation == 3) {
matrix.postRotate(180);
} else if (orientation == 8) {
matrix.postRotate(270);
}
scaledBitmap = Bitmap.createBitmap(scaledBitmap, 0, 0, scaledBitmap.getWidth(), scaledBitmap.getHeight(), matrix, true);
} catch (IOException e) {
e.printStackTrace();
}
//ByteArrayOutputStream out = new ByteArrayOutputStream();
scaledBitmap.compress(Bitmap.CompressFormat.JPEG, 85, fos);
}
public static int calculateInSampleSize(BitmapFactory.Options options, int reqWidth, int reqHeight) {
final int height = options.outHeight;
final int width = options.outWidth;
int inSampleSize = 1;
if (height > reqHeight || width > reqWidth) {
final int heightRatio = Math.round((float) height / (float) reqHeight);
final int widthRatio = Math.round((float) width / (float) reqWidth);
inSampleSize = heightRatio < widthRatio ? heightRatio : widthRatio;
}
final float totalPixels = width * height;
final float totalReqPixelsCap = reqWidth * reqHeight * 2;
while (totalPixels / (inSampleSize * inSampleSize) > totalReqPixelsCap) {
inSampleSize++;
}
return inSampleSize;
}
static protected int byteSizeOf(Bitmap data) {
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.HONEYCOMB_MR1) {
return data.getRowBytes() * data.getHeight();
} else if (Build.VERSION.SDK_INT < Build.VERSION_CODES.KITKAT) {
return data.getByteCount();
} else {
return data.getAllocationByteCount();
}
}
}
/**
* reduces the size of the image
* #param image
* #param maxSize
* #return
*/
public Bitmap getResizedBitmap(Bitmap image, int maxSize) {
int width = image.getWidth();
int height = image.getHeight();
float bitmapRatio = (float)width / (float) height;
if (bitmapRatio > 0) {
width = maxSize;
height = (int) (width / bitmapRatio);
} else {
height = maxSize;
width = (int) (height * bitmapRatio);
}
return Bitmap.createScaledBitmap(image, width, height, true);
}
private void setVideoViewRatio(VideoView vv, int maxSize, int cWidth, int cHeight){
int width = cWidth;
int height = cHeight;
float ratio = (float)cWidth / (float) height;
if (ratio > 0) {
width = maxSize;
height = (int) (width / ratio);
} else {
height = maxSize;
width = (int) (height * ratio);
}
vv.setMinimumWidth(width);
vv.setMinimumHeight(height);
}
I have 4608x3456 image that I want to adjust the size of. I want to adjust the resolution of the image to 640x480, yet when I do this the quality of the image drops. Is there a way to decrease image resolution and and still have a better image quality?
Resized Image 640x480 :
Bitmap temobitmpa = loadScaledBitmapFromUri(path,640,480);
return getImageUri(getApplicationContext(), temobitmpa);
public Bitmap loadScaledBitmapFromUri(String filePath, int width, int height) {
BitmapFactory.Options options = new BitmapFactory.Options();
options.inJustDecodeBounds = true;
// calc aspect ratio
int[] retval = calculateAspectRatio(options.outWidth, options.outHeight);
options.inJustDecodeBounds = false;
options.inSampleSize = calculateSampleSize(options.outWidth,
options.outHeight, width, height);
Log.i("test", "sample size::" + options.inSampleSize);
Bitmap unscaledBitmap = BitmapFactory.decodeFile(filePath, options);
return Bitmap.createScaledBitmap(unscaledBitmap, retval[0], retval[1],
true);
}
private int[] calculateAspectRatio(int origWidth, int origHeight) {
int newWidth = 640;
int newHeight = 480;
// If no new width or height were specified return the original bitmap
if (newWidth <= 0 && newHeight <= 0) {
newWidth = origWidth;
newHeight = origHeight;
}
// Only the width was specified
else if (newWidth > 0 && newHeight <= 0) {
newHeight = (newWidth * origHeight) / origWidth;
}
// only the height was specified
else if (newWidth <= 0 && newHeight > 0) {
newWidth = (newHeight * origWidth) / origHeight;
}
// If the user specified both a positive width and height
// (potentially different aspect ratio) then the width or height is
// scaled so that the image fits while maintaining aspect ratio.
// Alternatively, the specified width and height could have been
// kept and Bitmap.SCALE_TO_FIT specified when scaling, but this
// would result in whitespace in the new image.
else {
double newRatio = newWidth / (double) newHeight;
double origRatio = origWidth / (double) origHeight;
if (origRatio > newRatio) {
newHeight = (newWidth * origHeight) / origWidth;
} else if (origRatio < newRatio) {
newWidth = (newHeight * origWidth) / origHeight;
}
}
int[] retval = new int[2];
retval[0] = newWidth;
retval[1] = newHeight;
return retval;
}
private int calculateSampleSize(int srcWidth, int srcHeight, int dstWidth,
int dstHeight) {
final float srcAspect = (float) srcWidth / (float) srcHeight;
final float dstAspect = (float) dstWidth / (float) dstHeight;
if (srcAspect > dstAspect) {
return srcWidth / dstWidth;
} else {
return srcHeight / dstHeight;
}
}
You can try this image scaling library, it gives a very good image quality.
https://github.com/thebuzzmedia/imgscalr
I have an image which I resize:
if((width != null) || (height != null))
{
try{
// Scale image on disk
BufferedImage originalImage = ImageIO.read(file);
int type = originalImage.getType() == 0 ? BufferedImage.TYPE_INT_ARGB
: originalImage.getType();
BufferedImage resizedImageJpg = resizeImage(originalImage, type, 200, 200);
ImageIO.write(resizedImageJpg, "jpg", file);
} catch(IOException e) {
System.out.println(e.getMessage());
}
}
This is how I resize the image:
private static BufferedImage resizeImage(BufferedImage originalImage, int type,
Integer imgWidth, Integer imgHeight)
{
var resizedImage = new BufferedImage(imgWidth, imgHeight, type);
Graphics2D g = resizedImage.createGraphics();
g.drawImage(originalImage, 0, 0, imgWidth, imgHeight, null);
g.dispose();
return resizedImage;
}
Now the problem is, I also need to maintain aspect ratio. That is, I need the new 200/200 image to contain the new image scaled. Something like this:
I tried some things but they didn't work out as expected.
Any help is appreciated.
Here we go:
Dimension imgSize = new Dimension(500, 100);
Dimension boundary = new Dimension(200, 200);
Function to return the new size depending on the boundary:
public static Dimension getScaledDimension(Dimension imgSize, Dimension boundary) {
int original_width = imgSize.width;
int original_height = imgSize.height;
int bound_width = boundary.width;
int bound_height = boundary.height;
int new_width = original_width;
int new_height = original_height;
// first check if we need to scale width
if (original_width > bound_width) {
//scale width to fit
new_width = bound_width;
//scale height to maintain aspect ratio
new_height = (new_width * original_height) / original_width;
}
// then check if we need to scale even with the new height
if (new_height > bound_height) {
//scale height to fit instead
new_height = bound_height;
//scale width to maintain aspect ratio
new_width = (new_height * original_width) / original_height;
}
return new Dimension(new_width, new_height);
}
In case anyone also needs the image resizing code, here is a decent solution.
If you're unsure about the above solution, there are different ways to achieve the same result.
Translated from here:
Dimension getScaledDimension(Dimension imageSize, Dimension boundary) {
double widthRatio = boundary.getWidth() / imageSize.getWidth();
double heightRatio = boundary.getHeight() / imageSize.getHeight();
double ratio = Math.min(widthRatio, heightRatio);
return new Dimension((int) (imageSize.width * ratio),
(int) (imageSize.height * ratio));
}
You can also use imgscalr to resize images while maintaining aspect ratio:
BufferedImage resizeMe = ImageIO.read(new File("orig.jpg"));
Dimension newMaxSize = new Dimension(255, 255);
BufferedImage resizedImg = Scalr.resize(resizeMe, Method.QUALITY,
newMaxSize.width, newMaxSize.height);
You will want to check out Image.getScaledInstance(), and more in this answer: How to improve the performance of g.drawImage() method for resizing images
Load image:
BufferedImage bufferedImage = ImageIO.read(file);
Resize it:
private BufferedImage resizeAndCrop(BufferedImage bufferedImage, Integer width, Integer height) {
Mode mode = (double) width / (double) height >= (double) bufferedImage.getWidth() / (double) bufferedImage.getHeight() ? Scalr.Mode.FIT_TO_WIDTH
: Scalr.Mode.FIT_TO_HEIGHT;
bufferedImage = Scalr.resize(bufferedImage, Scalr.Method.ULTRA_QUALITY, mode, width, height);
int x = 0;
int y = 0;
if (mode == Scalr.Mode.FIT_TO_WIDTH) {
y = (bufferedImage.getHeight() - height) / 2;
} else if (mode == Scalr.Mode.FIT_TO_HEIGHT) {
x = (bufferedImage.getWidth() - width) / 2;
}
bufferedImage = Scalr.crop(bufferedImage, x, y, width, height);
return bufferedImage;
}
Using Scalr library:
<dependency>
<groupId>org.imgscalr</groupId>
<artifactId>imgscalr-lib</artifactId>
<version>4.2</version>
</dependency>
Here's a small piece of code that I wrote, it resizes the image to fit the container while keeping the image's original aspect ratio. It takes in as parameters the container's width, height and the image. You can modify it to fit your needs.
It's simple and works fine for my applications.
private Image scaleimage(int wid, int hei, BufferedImage img){
Image im = img;
double scale;
double imw = img.getWidth();
double imh = img.getHeight();
if (wid > imw && hei > imh){
im = img;
}else if(wid/imw < hei/imh){
scale = wid/imw;
im = img.getScaledInstance((int) (scale*imw), (int) (scale*imh), Image.SCALE_SMOOTH);
}else if (wid/imw > hei/imh){
scale = hei/imh;
im = img.getScaledInstance((int) (scale*imw), (int) (scale*imh), Image.SCALE_SMOOTH);
}else if (wid/imw == hei/imh){
scale = wid/imw;
im = img.getScaledInstance((int) (scale*imw), (int) (scale*imh), Image.SCALE_SMOOTH);
}
return im;
}
try this
float rateX = (float)jpDisplayImagen.getWidth()/(float)img.getWidth();
float rateY = (float)jpDisplayImagen.getHeight()/(float)img.getHeight();
if (rateX>rateY){
int W=(int)(img.getWidth()*rateY);
int H=(int)(img.getHeight()*rateY);
jpDisplayImagen.getGraphics().drawImage(img, 0, 0,W,H, null);
}
else{
int W=(int)(img.getWidth()*rateX);
int H=(int)(img.getHeight()*rateX);
jpDisplayImagen.getGraphics().drawImage(img, 0, 0,W,H, null);
}
public class ImageTransformation {
public static final String PNG = "png";
public static byte[] resize(FileItem fileItem, int width, int height) {
try {
ResampleOp resampleOp = new ResampleOp(width, height);
BufferedImage scaledImage = resampleOp.filter(ImageIO.read(fileItem.getInputStream()), null);
ByteArrayOutputStream baos = new ByteArrayOutputStream();
ImageIO.write(scaledImage, PNG, baos);
return baos.toByteArray();
} catch (Exception ex) {
throw new MapsException("An error occured during image resizing.", ex);
}
}
public static byte[] resizeAdjustMax(FileItem fileItem, int maxWidth, int maxHeight) {
try {
BufferedInputStream bis = new BufferedInputStream(fileItem.getInputStream());
BufferedImage bufimg = ImageIO.read(bis);
//check size of image
int img_width = bufimg.getWidth();
int img_height = bufimg.getHeight();
if(img_width > maxWidth || img_height > maxHeight) {
float factx = (float) img_width / maxWidth;
float facty = (float) img_height / maxHeight;
float fact = (factx>facty) ? factx : facty;
img_width = (int) ((int) img_width / fact);
img_height = (int) ((int) img_height / fact);
}
return resize(fileItem,img_width, img_height);
} catch (Exception ex) {
throw new MapsException("An error occured during image resizing.", ex);
}
}
}
This is my solution:
/*
Change dimension of Image
*/
public static Image resizeImage(Image image, int scaledWidth, int scaledHeight, boolean preserveRatio) {
if (preserveRatio) {
double imageHeight = image.getHeight();
double imageWidth = image.getWidth();
if (imageHeight/scaledHeight > imageWidth/scaledWidth) {
scaledWidth = (int) (scaledHeight * imageWidth / imageHeight);
} else {
scaledHeight = (int) (scaledWidth * imageHeight / imageWidth);
}
}
BufferedImage inputBufImage = SwingFXUtils.fromFXImage(image, null);
// creates output image
BufferedImage outputBufImage = new BufferedImage(scaledWidth, scaledHeight, inputBufImage.getType());
// scales the input image to the output image
Graphics2D g2d = outputBufImage.createGraphics();
g2d.drawImage(inputBufImage, 0, 0, scaledWidth, scaledHeight, null);
g2d.dispose();
return SwingFXUtils.toFXImage(outputBufImage, null);
}
All other answers show how to calculate the new image height in function of the new image width or vice-versa and how to resize the image using Java Image API. For those people who are looking for a straightforward solution I recommend any java image processing framework that can do this in a single line.
The exemple below uses Marvin Framework:
// 300 is the new width. The height is calculated to maintain aspect.
scale(image.clone(), image, 300);
Necessary import:
import static marvin.MarvinPluginCollection.*
I have found the selected answer to have problems with upscaling, and so I have made (yet) another version (which I have tested):
public static Point scaleFit(Point src, Point bounds) {
int newWidth = src.x;
int newHeight = src.y;
double boundsAspectRatio = bounds.y / (double) bounds.x;
double srcAspectRatio = src.y / (double) src.x;
// first check if we need to scale width
if (boundsAspectRatio < srcAspectRatio) {
// scale width to fit
newWidth = bounds.x;
//scale height to maintain aspect ratio
newHeight = (newWidth * src.y) / src.x;
} else {
//scale height to fit instead
newHeight = bounds.y;
//scale width to maintain aspect ratio
newWidth = (newHeight * src.x) / src.y;
}
return new Point(newWidth, newHeight);
}
Written in Android terminology :-)
as for the tests:
#Test public void scaleFit() throws Exception {
final Point displaySize = new Point(1080, 1920);
assertEquals(displaySize, Util.scaleFit(displaySize, displaySize));
assertEquals(displaySize, Util.scaleFit(new Point(displaySize.x / 2, displaySize.y / 2), displaySize));
assertEquals(displaySize, Util.scaleFit(new Point(displaySize.x * 2, displaySize.y * 2), displaySize));
assertEquals(new Point(displaySize.x, displaySize.y * 2), Util.scaleFit(new Point(displaySize.x / 2, displaySize.y), displaySize));
assertEquals(new Point(displaySize.x * 2, displaySize.y), Util.scaleFit(new Point(displaySize.x, displaySize.y / 2), displaySize));
assertEquals(new Point(displaySize.x, displaySize.y * 3 / 2), Util.scaleFit(new Point(displaySize.x / 3, displaySize.y / 2), displaySize));
}
Just add one more block to Ozzy's code so the thing looks like this:
public static Dimension getScaledDimension(Dimension imgSize,Dimension boundary) {
int original_width = imgSize.width;
int original_height = imgSize.height;
int bound_width = boundary.width;
int bound_height = boundary.height;
int new_width = original_width;
int new_height = original_height;
// first check if we need to scale width
if (original_width > bound_width) {
//scale width to fit
new_width = bound_width;
//scale height to maintain aspect ratio
new_height = (new_width * original_height) / original_width;
}
// then check if we need to scale even with the new height
if (new_height > bound_height) {
//scale height to fit instead
new_height = bound_height;
//scale width to maintain aspect ratio
new_width = (new_height * original_width) / original_height;
}
// upscale if original is smaller
if (original_width < bound_width) {
//scale width to fit
new_width = bound_width;
//scale height to maintain aspect ratio
new_height = (new_width * original_height) / original_width;
}
return new Dimension(new_width, new_height);
}