Подтвердить что ты не робот

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

У меня возникли проблемы с чтением этого одного файла JPEG с помощью ImageIO.read(Файл файла) - он генерирует исключение с сообщением "Неподдерживаемый тип изображения".

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

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

Troublesome image

EDIT:

Добавлено результирующее изображение:

Strange colors

4b9b3361

Ответ 1

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

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

UPDATE

Прочтите изображение 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);

UPDATE - март 2015 г. - Добавление изображений моделирования

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

Первое изображение показывает, как выглядит обычное изображение RGB.

Image RGB

Второе изображение показывает, как будет выглядеть одно и то же изображение в цветовой модели CMYK.

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

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

Image CMYK read through Java RGB

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

Ответ 2

Старый пост, но для справок в будущем:

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

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

После того, как вы его установили, вы можете читать CMYK JPEG с помощью ImageIO.read(...) следующим образом:

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

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

Ответ 3

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

Для решения требуется 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).

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

Ответ 4

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();

Ответ 5

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

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

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;
}

Ответ 6

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

ImageIO.read(new URL("http://img3.tianyancha.com/api/9b80a61183787909e719c77fd0f78103.png"))