Почему Java ImageIO выравнивает цвета JPEG
Когда я читаю определенные файлы JPG, цвета сглаживаются. Вот простой пример, который читает jpg и просто записывает одно и то же изображение в другой файл.
import java.awt.image.BufferedImage;
import java.io.File;
import javax.imageio.ImageIO;
public class JPegReadTest {
public static void main(String[] args) {
if (args.length == 2) {
try {
BufferedImage src = ImageIO.read(new File(args[0]));
ImageIO.write(src, "jpg", new File(args[1]));
} catch (Exception e) {
e.printStackTrace();
}
} else {
System.err.println("Usage: java JPegReadTest src dest");
}
}
}
Если вы попробуете это, например, http://www.flickr.com/photos/visualpanic/233508614/sizes/l/, цвета целевого изображения отличаются от исходного файла. Почему это? Как это исправить?
Также попытался сохранить изображение как png, но цвета тоже мягкие (так что если информация о цвете не читается правильно).
Ответы
Ответ 1
Это может быть несколько причин.
- Данные цвета JPEG часто хранятся как YCrCb вместо RGB, хотя преобразования должны быть в основном незаметными.
- JPEG часто имеет встроенный цветовой профиль, но многие приложения не понимают этого и просто игнорируют его (в этом случае ваш выходной файл может отсутствовать в цветовом профиле).
- Значение Gamma может быть reset или отсутствует после того, как Java манипулирует им.
Я действительно не пробовал ваш пример... не могли бы вы разместить как до, так и после файлов? Не имея возможности проверить файл результатов, трудно определить, имеются ли эти дополнительные данные или нет.
Изменить: Да, ясно, что ваши оригинальные и конвертированные изображения имеют разные цветовые профили. Java разделила исходный цветной профиль и вместо него использовала общий sRGB. Они выглядят одинаково для нас в Windows с Firefox и различными программами, потому что эти программы не используют цветовой профиль при визуализации. Тем не менее, на вашем Mac Mac фактически поддерживает эти цветовые профили (обсуждение вопросов по Mac для графики и т.д.), И поэтому они визуализируются по-разному. У меня нет Mac, но я подозреваю, что если вы откроете файлы в Photoshop на любой платформе, вы увидите разницу.
Ответ 2
Возможно, ваше исходное изображение имеет назначенный цветовой профиль с шириной диапазона, чем sRGB (например, Adobe RGB), и ваш цикл загрузки/сохранения не сохраняет информацию о цветовом пространстве? Без цветового профиля ваш зритель будет считать sRGB, а сжатая гамма сделает все "blah". Если у вас есть exiftool,
exiftool -ProfileDescription filename.jpg
- это быстрый способ проверки цветовых профилей на вашем источнике и вывода изображений.
Ответ 3
jpeg - формат с потерями. Когда читается, java сохраняет его как необработанный формат, похожий на BMP. Затем он снова выписывается, что приводит к потере данных. Кроме того, не так много контроля над качеством, как при использовании чего-то вроде GIMP.
Возможно, посмотрите на использование других API, таких как Image Magick, чтобы дать вам больше контроля над качеством.
Ответ 4
JPEG является lossy.
Это означает, что если вы откроете файл и сохраните его снова, вы потеряете некоторую информацию, если только не предпримете очень конкретные шаги, чтобы не потерять (в этом случае возможные манипуляции очень ограничены).
Дополнительно ImageIO.write()
, возможно, использует некоторые параметры качества по умолчанию для сохранения файлов JPEG, которые могут быть ниже оригинала, что приведет к дополнительной потере качества.
Попробуйте сохранить файл PNG, и вы увидите, что он будет выглядеть так же, как источник.
Ответ 5
Вот ссылка на исходный код, который расширяется на интерфейсе ImageIO - вы можете изменить параметры качества и сжатия при записи изображения....
http://www.universalwebservices.net/web-programming-resources/java/adjust-jpeg-image-compression-quality-when-saving-images-in-java