Android-réduire la taille du fichier image
j'ai un fichier image URI, et je veux réduire sa taille pour le télécharger. La taille initiale du fichier image dépend de mobile à mobile (peut être 2MB comme peut être 500KB), mais je veux la taille finale d'être environ 200KB, de sorte que je peux télécharger.
D'après ce que j'ai lu, j'ai (au moins) 2 choix:
- Utilisant BitmapFactory.Option.inSampleSize , à la sous-échantillon de l'image d'origine et obtenir une image plus petite;
- Utilisant Bitmap.compresser pour compresser l'image en spécifiant la qualité de compression.
Quel est le meilleur choix?
je pensais d'abord redimensionner l'image Largeur/Hauteur jusqu'à ce que la largeur ou la hauteur soit supérieure à 1000px (quelque chose comme 1024x768 ou d'autres), puis compresser l'image avec une qualité Décroissante jusqu'à ce que la taille du fichier soit supérieure à 200Ko. Voici un exemple:
int MAX_IMAGE_SIZE = 200 * 1024; // max final file size
Bitmap bmpPic = BitmapFactory.decodeFile(fileUri.getPath());
if ((bmpPic.getWidth() >= 1024) && (bmpPic.getHeight() >= 1024)) {
BitmapFactory.Options bmpOptions = new BitmapFactory.Options();
bmpOptions.inSampleSize = 1;
while ((bmpPic.getWidth() >= 1024) && (bmpPic.getHeight() >= 1024)) {
bmpOptions.inSampleSize++;
bmpPic = BitmapFactory.decodeFile(fileUri.getPath(), bmpOptions);
}
Log.d(TAG, "Resize: " + bmpOptions.inSampleSize);
}
int compressQuality = 104; // quality decreasing by 5 every loop. (start from 99)
int streamLength = MAX_IMAGE_SIZE;
while (streamLength >= MAX_IMAGE_SIZE) {
ByteArrayOutputStream bmpStream = new ByteArrayOutputStream();
compressQuality -= 5;
Log.d(TAG, "Quality: " + compressQuality);
bmpPic.compress(Bitmap.CompressFormat.JPEG, compressQuality, bmpStream);
byte[] bmpPicByteArray = bmpStream.toByteArray();
streamLength = bmpPicByteArray.length;
Log.d(TAG, "Size: " + streamLength);
}
try {
FileOutputStream bmpFile = new FileOutputStream(finalPath);
bmpPic.compress(Bitmap.CompressFormat.JPEG, compressQuality, bmpFile);
bmpFile.flush();
bmpFile.close();
} catch (Exception e) {
Log.e(TAG, "Error on saving file");
}
y a-t-il une meilleure façon de le faire? Dois-je essayer de continuer à utiliser les deux méthodes ou une seule? Merci
2 réponses
en utilisant Bitmap.compress()
vous spécifiez juste l'algorithme de compression et par la façon dont l'opération de compression prend assez grande quantité de temps. Si vous avez besoin de jouer avec des tailles pour réduire l'allocation de mémoire pour votre image, vous avez exactement besoin d'utiliser la mise à l'échelle de votre image en utilisant Bitmap.Options
, calcul des limites bitmap au début et ensuite le décodage à votre taille spécifiée.
le meilleur échantillon que j'ai trouvé sur StackOverflow est celui-ci .
la plupart des réponses que j'ai trouvées étaient juste des morceaux que j'ai dû mettre ensemble pour obtenir un code de travail, qui est affiché sous
public void compressBitmap(File file, int sampleSize, int quality) {
try {
BitmapFactory.Options options = new BitmapFactory.Options();
options.inSampleSize = sampleSize;
FileInputStream inputStream = new FileInputStream(file);
Bitmap selectedBitmap = BitmapFactory.decodeStream(inputStream, null, options);
inputStream.close();
FileOutputStream outputStream = new FileOutputStream("location to save");
selectedBitmap.compress(Bitmap.CompressFormat.JPEG, quality, outputStream);
outputStream.close();
long lengthInKb = photo.length() / 1024; //in kb
if (lengthInKb > SIZE_LIMIT) {
compressBitmap(file, (sampleSize*2), (quality/4));
}
selectedBitmap.recycle();
} catch (Exception e) {
e.printStackTrace();
}
}
2 paramètres échantillonner et la qualité joue un rôle important
sampleSize est utilisé pour sous-échantillon de l'image d'origine et de renvoyer une image plus petite , c'est à dire
SampleSize = = 4 retours une image qui est 1/4 de la largeur/hauteur de l'original.
est utilisée pour indiquer le compresseur , la plage d'entrée est comprise entre 0 et 100. 0 ce qui signifie compresse pour petite taille, 100 signifie compresse pour une qualité maximale