Как повернуть изображение и сохранить его без повторного сжатия?

У меня есть файл изображения (jpg), и мне нужно его повернуть. Однако я бы хотел избежать повторного сжатия при сохранении на диск. Есть ли у них способ сделать это?

Сохраняю изображение вот так:

  matrix.setRotate(-90);
  Bitmap bitmap = BitmapFactory.decodeFile(imagePath, options);
  Bitmap bmRotated = Bitmap.createBitmap(bitmap, 0, 0, bitmap.getWidth(), bitmap.getHeight(), matrix, true);
  bitmap.recycle();

  FileOutputStream fileoutputstream = new FileOutputStream(imagePath);
  bmRotated.compress(CompressFormat.JPEG, 100, fileoutputstream);
  fileoutputstream.flush();
   fileoutputstream.close();
  bmRotated.recycle();

person noa    schedule 28.09.2017    source источник
comment
Вы что-нибудь пробовали   -  person UltimateDevil    schedule 28.09.2017
comment
Как вы сохраняете этот код, чтобы мы могли помочь вам лучше   -  person UltimateDevil    schedule 28.09.2017
comment
@VikasTiwari: готово, я обновил вопрос   -  person noa    schedule 28.09.2017
comment
Файлы JPEG без сжатия очень встречаются редко, я сомневаюсь, что ваш исходный файл относится к этой категории, поэтому повернутая версия также будет сжиматься.   -  person guidot    schedule 28.09.2017
comment
Что вы имеете в виду, что не хотите сжимать? JPEG - это сжатый формат. Или вы пытаетесь сохранить качество изображения после сжатия? В таком случае используйте формат PNG.   -  person Nabin Bhandari    schedule 28.09.2017
comment
да, я хочу повернуть изображение и не сжимать его ...   -  person noa    schedule 28.09.2017
comment
Вы уверены, что не можете просто установить поворот в данных EXIF ​​изображения? Будет казаться, что это поворачивает его без изменения данных вообще, но сработает ли это для вас, зависит от причины, по которой вы поворачиваете изображение, и от того, что затем будет отображать его.   -  person Matt Gibson    schedule 28.09.2017
comment
Если вы не хотите работать с exif и хотите сохранить изображения в формате jpeg, без повторного сжатия нет пути. JPEG - это формат со сжатием. Каждый раз, когда вы открываете его как растровое изображение в Android, он распаковывается в байтовый массив. Когда вы пытаетесь сохранить его как JPEG - вы используете сжатие jpeg encoder   -  person Beyka    schedule 28.09.2017
comment
(Обратите внимание, что это не такой уж странный вопрос, как некоторые думают: можно алгоритмически повернуть JPEG без повторного сжатия с потерями: stackoverflow.com/a/543729/300836, о чем, я думаю, мы и говорим.)   -  person Matt Gibson    schedule 28.09.2017


Ответы (2)


Может быть, вы можете попытаться извлечь данные из растрового изображения в массив байтов и сохранить этот массив. (Код не проверял, возможно не работает).

Bitmap bitmap = new Bitmap()...
int width = bitmap.getWidth();
int height = bitmap.getHeight();

int size = bitmap.getRowBytes() * bitmap.getHeight();
ByteBuffer byteBuffer = ByteBuffer.allocate(size);
bitmap.copyPixelsToBuffer(byteBuffer);
byte[] byteArray = byteBuffer.array();

FileOutputStream output = new FileOutputStream("filename");
output.write(byteArray);
output.close();
person Miguel Isla    schedule 28.09.2017

Используйте PNG вместо JPG. Формат PNG - это формат данных без потерь со сжатием. https://en.wikipedia.org/wiki/Portable_Network_Graphics

matrix.setRotate(-90);
Bitmap bitmap = BitmapFactory.decodeFile(imagePath, options);
Bitmap bmRotated = Bitmap.createBitmap(bitmap, 0, 0, 
bitmap.getWidth(), bitmap.getHeight(), matrix, true);
bitmap.recycle();

FileOutputStream fileoutputstream = new FileOutputStream(imagePath);
bmRotated.compress(CompressFormat.PNG, 100, fileoutputstream);
fileoutputstream.flush();
fileoutputstream.close();
bmRotated.recycle();


Или вы можете использовать библиотеку Compressor, чтобы использовать формат WEBP.
WEBP поддерживает как без потерь, так и с потерями. https://en.wikipedia.org/wiki/WebP

https://github.com/zetbaitsu/Compressor

compressedImage = new Compressor(this)
        .setMaxWidth(640)
        .setMaxHeight(480)
        .setQuality(100)
        .setCompressFormat(Bitmap.CompressFormat.WEBP)
        .setDestinationDirectoryPath(Environment.getExternalStoragePublicDirectory(
          Environment.DIRECTORY_PICTURES).getAbsolutePath())
        .compressToFile(actualImage);
person Stanley Ko    schedule 28.09.2017
comment
нет, png увеличится на 3 размера исходного файла + сохранение файла займет около 7 секунд :( WebP - хорошая альтернатива, но почему качество 75, а не 80? 90? 95? - person noa; 28.09.2017
comment
@noa качество WEBP, оно равно 100. Я просто скопировал и вставил пример с сайта github, и я просто поправил его. - person Stanley Ko; 28.09.2017
comment
@noa Кроме того, для использования WEBP вам потребуется API 14 или выше. stackoverflow.com/ вопросы / 19308831 / - person Stanley Ko; 28.09.2017
comment
@noa Зачем нужно поворачивать изображение? Если вам нужно повернуть изображение с камеры, вы можете установитьDisplayOrientation (90) и нет необходимости вращать самостоятельно. stackoverflow.com/questions/5309029/android-camera-rotate - person Stanley Ko; 28.09.2017