Android-уменьшить размер файла изображения
У меня есть файл изображения URI, и я хочу уменьшить его размер, чтобы загрузить его. Начальный размер файла изображения зависит от мобильного телефона (может быть 2MB, как может быть 500KB), но я хочу, чтобы окончательный размер был около 200KB, чтобы я мог загрузить его.
Из того, что я читал, у меня есть (по крайней мере) 2 варианта:
- используя BitmapFactory.Опции.inSampleSize, чтобы подмножество исходного изображения и получить меньшее изображение;
- используя точечный рисунок.сжать сжать изображение, задающее качество сжатия.
что самый лучший выбор?
Я думал сначала изменить ширину/высоту изображения, пока ширина или высота не превысит 1000px (что-то вроде 1024x768 или других), а затем сжимать изображение с уменьшающимся качеством, пока размер файла не превысит 200KB. Вот пример:
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");
}
есть ли лучший способ сделать это? Должен ли я пытаться использовать все 2 метода или только один? Спасибо
2 ответов
используя Bitmap.compress()
вы просто указываете алгоритм сжатия и, кстати, операция сжатия занимает довольно большое количество времени. Если вам нужно играть с размерами для уменьшения выделения памяти для вашего изображения, вам точно нужно использовать масштабирование изображения с помощью Bitmap.Options
, сначала вычисляя границы растрового изображения, а затем декодируя его до указанного размера.
лучший образец, который я нашел в StackOverflow, -этот.
большинство ответов, которые я нашел, были просто кусочками, которые я должен был собрать, чтобы получить рабочий код, который опубликован ниже
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 параметра sampleSize и качество играет важную роль
значениях samplesize= используется сложите исходное изображение и верните меньшее изображение, т. е.
SampleSize == 4 возвращает изображение, равное 1/4 ширины / высоты оригинала.
качество используется для подсказки компрессора, входной диапазон от 0 до 100. 0 смысл компресс для малый размер, 100 означает сжатие для максимального качества