Почему 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, но цвета в нем тоже мягкие (так что предполагая информацию о цвете не читается должным образом).

5 ответов


Это может быть несколько причин.

  1. данные цвета JPEG часто хранятся как YCrCb вместо RGB, хотя преобразования должны быть в основном незаметны.
  2. JPEG часто имеет встроенный цветовой профиль, но многие приложения этого не понимают и просто игнорируют его (в этом случае в вашем выходном файле может отсутствовать цветовой профиль).
  3. значение гаммы может быть сброшено или отсутствует после того, как Java искалечит его.

Я на самом деле не попробовать свои образец... не могли бы вы опубликовать оба файла До и после? Не имея возможности изучить файл результатов, трудно сказать, есть ли эти дополнительные данные или нет.

Edit: Да, ясно, что ваши оригинальные и преобразованные изображения имеют разные цветовые профили. Java удалил цветовой профиль оригинала и вместо него использовал общий sRGB. Они выглядят одинаково для нас в Windows с Firefox и различными программами, потому что эти программы не используют цвет профиль при визуализации. Однако на вашем Mac Mac фактически поддерживает эти цветовые профили (cue debate over Macs for graphics и т. д.).) и поэтому они представляют по-разному. У меня нет Mac под рукой, но я подозреваю, что если вы откроете файлы в Photoshop на любой платформе, вы увидите разницу.


возможно, ваше исходное изображение имеет назначенный цветовой профиль с гаммой шире sRGB (например, Adobe RGB), и ваш цикл загрузки/сохранения не сохраняет информацию о цветовом пространстве? Без цветового профиля ваш зритель примет sRGB, а сжатая гамма заставит все выглядеть "бла". Если у вас есть exiftool,

exiftool -ProfileDescription filename.jpg

- это быстрый способ проверить цветовые профили на исходных и выходных изображениях.


JPEG-это формат с потерями. При чтении java сохраняет его как необработанный формат, похожий на BMP. Затем он снова записывается, вызывая потерю данных. Кроме того, нет большого контроля над качеством, как при использовании чего-то вроде GIMP.

возможно, посмотрите на использование других API, таких как Изображение Магии чтобы дать вам больше контроля над качеством.


в формате JPEG - это с потерями.

это означает, что если вы откроете файл и сохраните его снова, вы потеряете некоторую информацию, если не предпримете очень конкретные шаги, чтобы не потерять ее (в этом случае возможные манипуляции очень ограничены).

дополнительно ImageIO.write() вероятно, использует некоторые настройки качества по умолчанию для сохранения файлов JPEG, которые могут быть ниже оригинала, что приведет к дополнительной потере качество.

попробуйте сохранить в файл PNG, и вы увидите, что он будет выглядеть так же, как источник.


вот ссылка с исходным кодом, которая расширяется на интерфейсе ImageIO - вы можете изменить параметры качества и сжатия при записи изображения.... http://www.universalwebservices.net/web-programming-resources/java/adjust-jpeg-image-compression-quality-when-saving-images-in-java