Невозможно прочитать изображение JPEG с использованием ImageIO.read(файл файла)

У меня проблемы с чтением этого файла JPEG с использованием ImageIO.read(File file) - выдается исключение с сообщением "Unsupported Image Type".

Я пробовал другие изображения JPEG, и они, кажется, работают нормально.

Единственное отличие, которое мне удалось заметить, заключается в том, что этот файл содержит миниатюру. Известно ли, что это вызывает проблемы с ImageIO.read()?

Проблемное изображение

РЕДАКТИРОВАТЬ:

Добавил получившееся изображение:

Странные цвета

6 ответов

Решение

Ваше изображение "Цветовая модель" CMYK, JPEGImageReader (внутренний класс, который читает ваш файл) только для чтения RGB Color Model.

Если вы настаиваете на чтении изображений CMYK, то вам нужно будет их конвертировать, попробуйте этот код.

ОБНОВИТЬ

Считайте изображение CMYK в RGB BufferedImage.

    File f = new File("/path/imagefile.jpg");

    //Find a suitable ImageReader
    Iterator readers = ImageIO.getImageReadersByFormatName("JPEG");
    ImageReader reader = null;
    while(readers.hasNext()) {
        reader = (ImageReader)readers.next();
        if(reader.canReadRaster()) {
            break;
        }
    }

    //Stream the image file (the original CMYK image)
    ImageInputStream input =   ImageIO.createImageInputStream(f); 
    reader.setInput(input); 

    //Read the image raster
    Raster raster = reader.readRaster(0, null); 

    //Create a new RGB image
    BufferedImage bi = new BufferedImage(raster.getWidth(), raster.getHeight(), 
    BufferedImage.TYPE_4BYTE_ABGR); 

    //Fill the new image with the old raster
    bi.getRaster().setRect(raster);

ОБНОВЛЕНИЕ - март 2015 - Добавление изображений симуляции

Исходные изображения были удалены из выпадающего списка OP. Поэтому я добавляю новые изображения (не оригиналы), которые имитируют проблему, которая происходила с ними.

Первое изображение - это то, как выглядит нормальное изображение RGB.

Изображение RGB

Второе изображение - это то же самое изображение в цветовой модели CMYK.

На самом деле вы не можете видеть, как это выглядит в Интернете, потому что хост будет конвертировать его в RGB. Чтобы увидеть, как он выглядит, возьмите изображение RGB и запустите его через конвертер RGB в CMYK.

Третье изображение - это то, как будет выглядеть изображение CMYK при чтении и записи с использованием Java ImageIO.

Изображение CMYK читается через Java RGB

Проблема, которая имела место с OP, состоит в том, что у них было что-то вроде изображения 2, которое выдает исключение, когда вы пытаетесь прочитать его.

Старый пост, но для дальнейшего использования:

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

Это простая Java и не требует JAI. Исходный код и двоичные дистрибутивы свободно доступны по адресу https://github.com/haraldk/TwelveMonkeys и защищены лицензией в стиле BSD.

После того, как он установлен, он позволяет читать файлы CMYK JPEG с помощью ImageIO.read(...) как это:

File cmykJPEGFile = new File(/*path*/);
BufferedImage image = ImageIO.read(cmykJPEGFile);

Т.е. в большинстве случаев нет необходимости изменять ваш код.

Я немного опоздал на вечеринку. Но, вероятно, все же стоит опубликовать свой ответ, так как ни один из ответов на самом деле не решает проблему.

Для решения требуется Sanselan (или Apache Commons Imaging, как его сейчас называют) и разумный цветовой профиль CMYK (файл.icc). Вы можете получить более позднюю версию из Adobe или eci.org.

Основная проблема заключается в том, что Java - из коробки - может читать файлы JPEG только в RGB. Если у вас есть файл CMYK, вам необходимо различать обычный CMYK, Adobe CMYK (с инвертированными значениями, т.е. 255 для отсутствия чернил и 0 для максимального объема чернил) и Adobe CYYK (в некоторых вариантах также с инвертированными цветами).

public class JpegReader {

    public static final int COLOR_TYPE_RGB = 1;
    public static final int COLOR_TYPE_CMYK = 2;
    public static final int COLOR_TYPE_YCCK = 3;

    private int colorType = COLOR_TYPE_RGB;
    private boolean hasAdobeMarker = false;

    public BufferedImage readImage(File file) throws IOException, ImageReadException {
        colorType = COLOR_TYPE_RGB;
        hasAdobeMarker = false;

        ImageInputStream stream = ImageIO.createImageInputStream(file);
        Iterator<ImageReader> iter = ImageIO.getImageReaders(stream);
        while (iter.hasNext()) {
            ImageReader reader = iter.next();
            reader.setInput(stream);

            BufferedImage image;
            ICC_Profile profile = null;
            try {
                image = reader.read(0);
            } catch (IIOException e) {
                colorType = COLOR_TYPE_CMYK;
                checkAdobeMarker(file);
                profile = Sanselan.getICCProfile(file);
                WritableRaster raster = (WritableRaster) reader.readRaster(0, null);
                if (colorType == COLOR_TYPE_YCCK)
                    convertYcckToCmyk(raster);
                if (hasAdobeMarker)
                    convertInvertedColors(raster);
                image = convertCmykToRgb(raster, profile);
            }

            return image;
        }

        return null;
    }

    public void checkAdobeMarker(File file) throws IOException, ImageReadException {
        JpegImageParser parser = new JpegImageParser();
        ByteSource byteSource = new ByteSourceFile(file);
        @SuppressWarnings("rawtypes")
        ArrayList segments = parser.readSegments(byteSource, new int[] { 0xffee }, true);
        if (segments != null && segments.size() >= 1) {
            UnknownSegment app14Segment = (UnknownSegment) segments.get(0);
            byte[] data = app14Segment.bytes;
            if (data.length >= 12 && data[0] == 'A' && data[1] == 'd' && data[2] == 'o' && data[3] == 'b' && data[4] == 'e')
            {
                hasAdobeMarker = true;
                int transform = app14Segment.bytes[11] & 0xff;
                if (transform == 2)
                    colorType = COLOR_TYPE_YCCK;
            }
        }
    }

    public static void convertYcckToCmyk(WritableRaster raster) {
        int height = raster.getHeight();
        int width = raster.getWidth();
        int stride = width * 4;
        int[] pixelRow = new int[stride];
        for (int h = 0; h < height; h++) {
            raster.getPixels(0, h, width, 1, pixelRow);

            for (int x = 0; x < stride; x += 4) {
                int y = pixelRow[x];
                int cb = pixelRow[x + 1];
                int cr = pixelRow[x + 2];

                int c = (int) (y + 1.402 * cr - 178.956);
                int m = (int) (y - 0.34414 * cb - 0.71414 * cr + 135.95984);
                y = (int) (y + 1.772 * cb - 226.316);

                if (c < 0) c = 0; else if (c > 255) c = 255;
                if (m < 0) m = 0; else if (m > 255) m = 255;
                if (y < 0) y = 0; else if (y > 255) y = 255;

                pixelRow[x] = 255 - c;
                pixelRow[x + 1] = 255 - m;
                pixelRow[x + 2] = 255 - y;
            }

            raster.setPixels(0, h, width, 1, pixelRow);
        }
    }

    public static void convertInvertedColors(WritableRaster raster) {
        int height = raster.getHeight();
        int width = raster.getWidth();
        int stride = width * 4;
        int[] pixelRow = new int[stride];
        for (int h = 0; h < height; h++) {
            raster.getPixels(0, h, width, 1, pixelRow);
            for (int x = 0; x < stride; x++)
                pixelRow[x] = 255 - pixelRow[x];
            raster.setPixels(0, h, width, 1, pixelRow);
        }
    }

    public static BufferedImage convertCmykToRgb(Raster cmykRaster, ICC_Profile cmykProfile) throws IOException {
        if (cmykProfile == null)
            cmykProfile = ICC_Profile.getInstance(JpegReader.class.getResourceAsStream("/ISOcoated_v2_300_eci.icc"));
        ICC_ColorSpace cmykCS = new ICC_ColorSpace(cmykProfile);
        BufferedImage rgbImage = new BufferedImage(cmykRaster.getWidth(), cmykRaster.getHeight(), BufferedImage.TYPE_INT_RGB);
        WritableRaster rgbRaster = rgbImage.getRaster();
        ColorSpace rgbCS = rgbImage.getColorModel().getColorSpace();
        ColorConvertOp cmykToRgb = new ColorConvertOp(cmykCS, rgbCS, null);
        cmykToRgb.filter(cmykRaster, rgbRaster);
        return rgbImage;
    }
}

Сначала код пытается прочитать файл, используя обычный метод, который работает для файлов RGB. Если это не удается, он считывает детали цветовой модели (профиль, маркер Adobe, вариант Adobe). Затем он считывает необработанные данные пикселей (растр) и выполняет все необходимые преобразования (YCCK в CMYK, инвертированные цвета, CMYK в RGB).

Я не совсем доволен своим решением. В то время как цвета в основном хорошие, темные области немного слишком яркие, в частности черный не полностью черный. Если кто-нибудь знает, что я могу улучшить, я был бы рад услышать это.

ImageIO.read() ->

File filePath = new File("C:\\Users\\chang\\Desktop\\05036877.jpg");
com.sun.image.codec.jpeg.JPEGImageDecoder jpegDecoder =  JPEGCodec.createJPEGDecoder (new FileInputStream(filePath));

BufferedImage image = jpegDecoder.decodeAsBufferedImage();

Я нашел https://stackru.com/questions/22409... и здесь, этот делает отличное преобразование цветов

И объединены оба, чтобы получить это:

private BufferedImage convertCMYK2RGB(BufferedImage image) throws IOException{
    log.info("Converting a CYMK image to RGB");
    //Create a new RGB image
    BufferedImage rgbImage = new BufferedImage(image.getWidth(), image.getHeight(),
    BufferedImage.TYPE_3BYTE_BGR);
    // then do a funky color convert
    ColorConvertOp op = new ColorConvertOp(null);
    op.filter(image, rgbImage);
    return rgbImage;
}

Я исправлю это. Нужно только добавить эту зависимость. я могу прочитать изображение CMYK ImageIO. TwelveMonkeys

ImageIO.read(new URL("http://img3.tianyancha.com/api/9b80a61183787909e719c77fd0f78103.png"))
Другие вопросы по тегам