J'ai une petite méthode qui est destinée à redimensionner une image (stockée comme un fichier) pour produire une nouvelle image avec une taille de fichier prédéfinie (dans mon cas 512 KB). La méthode ressemble à quelque chose comme ce qui suit:Android - réduire les dimensions de l'image ne réduit pas la taille dans la même proportion
private static final int maximumFileSizeInKBs = 512;
public static Uri resizeImage(Context context, Uri imageUri) {
// get image width and height
BitmapFactory.Options options = new BitmapFactory.Options();
options.inJustDecodeBounds = true;
Bitmap imageBitmap = BitmapFactory.decodeFile(new File(imageUri.getPath()).getAbsolutePath(), options);
int imageWidth = options.outWidth;
int imageHeight = options.outHeight;
// get image file size (in KBs)
File file = new File(imageUri.getPath());
int fileSizeInKBs = Integer.parseInt(String.valueOf(file.length()/1024));
// get the scaling factor
// (square root because when we scale both the width and height by the
// square root of the scaling factor, then the size of the final image
// will be scaled by the scaling factor)
double scalingFactor = Math.sqrt(fileSizeInKBs/maximumFileSizeInKBs);
// no need to scale if file already within maximum file size limit
if(scalingFactor <= 1) {
return imageUri;
}
// get scaled dimensions
int scaledImageWidth = (int) Math.floor(imageWidth/scalingFactor);
int scaledImageHeight = (int) Math.floor(imageHeight/scalingFactor);
// load original bitmap (load a scaled copy to avoid OutOfMemory errors)
options = new BitmapFactory.Options();
options.inSampleSize = Math.max(imageHeight/scaledImageWidth, imageHeight/scaledImageHeight);
imageBitmap = BitmapFactory.decodeFile(new File(imageUri.getPath()).getAbsolutePath(), options);
// the scaled image above will be scaled by a value equal to the
// nearest power of 2, hence it wont be scaled to the exact value
// that we want. So, we need to calculate new scaling factors
// based on the scaled loaded bitmap
Matrix m = new Matrix();
RectF inRect = new RectF(0, 0, imageWidth, imageHeight);
RectF outRect = new RectF(0, 0, scaledImageWidth, scaledImageHeight);
m.setRectToRect(inRect, outRect, Matrix.ScaleToFit.CENTER);
float[] values = new float[9];
m.getValues(values);
// create a scaled bitmap with required file size
Bitmap scaledBitmap = Bitmap.createScaledBitmap(imageBitmap, (int) (imageWidth*values[0]), (int) (imageHeight*values[4]), true);
// delete original image
new File(imageUri.getPath()).delete();
// write bitmap to file
File newImageFile = BaseResourceClass.makeTempResourceFile(Slide.ResourceType.IMAGE, context);
try {
newImageFile.createNewFile();
FileOutputStream fos = new FileOutputStream(newImageFile);
scaledBitmap.compress(Bitmap.CompressFormat.PNG, 1, fos);
fos.close();
} catch (IOException e) {
e.printStackTrace();
Toast.makeText(context, "Something went wrong", Toast.LENGTH_SHORT).show();
}
// recycle bitmaps to reallocate memory
Storage.recycleBitmap(imageBitmap);
Storage.recycleBitmap(scaledBitmap);
// scaling done, return new Image
return Uri.fromFile(newImageFile);
}
Lorsque cette méthode fonctionne, les dimensions de l'image se réduit à la taille exacte (comme dans ce que je pense que ce soit), mais la taille de l'image en Ko de ne sont pas revus à la baisse par le même facteur. Par exemple, après l'exécution de cette méthode, je reçois les numéros suivants ce
before resizing
imageWidth : 3120, imageHeight : 4160, fileSize : 2960 KB
after resizing
imageWidth : 1395, imageHeight : 1860, fileSize : 2491 KB
Je ne comprends pas après avoir enlevé tant de pixels de l'image, est-ce qui prend tant de place de façon à maintenir la taille du fichier image autant. Je ai essayé de regarder d'autres questions StackOverflow et la documentation des classes BitmapFactory et Bitmap Android, mais avec ce problème étant mentionné nulle part. Toute aide serait appréciée!