Количество исходных растровых полос и компонентов цветового пространства источника не совпадают, когда я читаю изображение

Когда я пытаюсь прочитать изображение, используя следующий код

myPicture = ImageIO.read(new File("./src/javaassignment1b/Deck/Ace_Diamond_1.jpg"));

Я получаю следующую ошибку

 Numbers of source Raster bands and source color space components do not match

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

ПРИМЕЧАНИЕ. Сначала я попытался использовать ImageIcon для добавления в JPanel, но он не смог работать, поэтому я нашел это решение, которое привело к моему текущая проблема. Я только начинаю программировать на Java.

EDIT: вот ссылка на изображения, и я делаю приложение Java

Мне нужна альтернатива для добавления изображения в JPanel.

Ответ 1

Откройте изображения с помощью любого средства просмотра/редактирования изображений и сохраните их в стандартном формате

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

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

Ни одна из моих попыток применить стандартные преобразования цвета для YPbPb- > RGB или YCbCb- > RGB, казалось, воспроизводила точные исходные цвета, но, как вы могли заметить, когда просматриваете статьи в Википедии: В мире цветовых пространств был выпущен некоторый академический пар.

Снова: я сильно рекомендую вам открывать изображения с помощью любого средства просмотра/редактирования изображений и сохранять их в стандартном формате. И желательно как PNG, потому что JPG не подходит для этих изображений. JPG больше предназначен для "естественных" изображений, таких как фотографии. Для таких "искусственных" изображений сжатие должно быть очень низким, чтобы избежать артефактов.

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

import java.awt.image.BufferedImage;
import java.awt.image.Raster;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.Iterator;

import javax.imageio.ImageIO;
import javax.imageio.ImageReader;
import javax.imageio.stream.ImageInputStream;
import javax.swing.ImageIcon;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.SwingUtilities;

public class StrangeImageTest
{
    public static void main(String[] args) throws IOException
    {
        final BufferedImage image = readImage(new File("Ace_Diamond_1.jpg"));

        SwingUtilities.invokeLater(new Runnable()
        {
            @Override
            public void run()
            {
                JFrame f = new JFrame();
                f.getContentPane().add(new JLabel(new ImageIcon(image)));
                f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
                f.pack();
                f.setLocationRelativeTo(null);
                f.setVisible(true);
            }
        });
    }

    static BufferedImage readImage(File file) throws IOException
    {
        return readImage(new FileInputStream(file));
    }

    static BufferedImage readImage(InputStream stream) throws IOException
    {
        Iterator<ImageReader> imageReaders = 
            ImageIO.getImageReadersBySuffix("jpg");
        ImageReader imageReader = imageReaders.next();
        ImageInputStream iis = 
            ImageIO.createImageInputStream(stream);
        imageReader.setInput(iis, true, true);
        Raster raster = imageReader.readRaster(0, null);
        int w = raster.getWidth();
        int h = raster.getHeight();

        BufferedImage result = 
            new BufferedImage(w, h, BufferedImage.TYPE_INT_RGB);
        int rgb[] = new int[3];
        int pixel[] = new int[3];
        for (int x=0; x<w; x++)
        {
            for (int y=0; y<h; y++)
            {
                raster.getPixel(x, y, pixel);
                int Y = pixel[0];
                int CR = pixel[1];
                int CB = pixel[2];
                toRGB(Y, CB, CR, rgb);
                int r = rgb[0];
                int g = rgb[1];
                int b = rgb[2];
                int bgr = 
                    ((b & 0xFF) << 16) | 
                    ((g & 0xFF) <<  8) | 
                     (r & 0xFF);
                result.setRGB(x, y, bgr);
            }
        }
        return result;
    }

    // Based on http://www.equasys.de/colorconversion.html
    private static void toRGB(int y, int cb, int cr, int rgb[])
    {
        float Y = y / 255.0f;
        float Cb = (cb-128) / 255.0f;
        float Cr = (cr-128) / 255.0f;

        float R = Y + 1.4f * Cr;
        float G = Y -0.343f * Cb - 0.711f * Cr;
        float B = Y + 1.765f * Cb;

        R = Math.min(1.0f, Math.max(0.0f, R));
        G = Math.min(1.0f, Math.max(0.0f, G));
        B = Math.min(1.0f, Math.max(0.0f, B));

        int r = (int)(R * 255);
        int g = (int)(G * 255);
        int b = (int)(B * 255);

        rgb[0] = r;
        rgb[1] = g;
        rgb[2] = b;
    }
}

(Примечание. Это может быть реализовано намного проще, с ColorConvertOp, который преобразуется в цветовое пространство RGB из цветового пространства, которое использовалось для изображения. Но, как упоминалось выше, мне не удалось выяснить, какой цвет пространство было использовано для сохранения изображения, и даже если бы я это знал, нужно было бы создать соответствующую реализацию ColorSpace. Первые результаты веб-поиска, такие как YCbCrColorSpace. java, не работал для заданных входных изображений...)

Ответ 2

На этот вопрос уже был дан ответ: fooobar.com/info/546802/..., и это очень элегантное решение проблемы. Решение включает использование плагина для ImageIO с реализованной поддержкой нескольких форматов, которые не поддерживаются реализацией по умолчанию ImageIo. Подробные сведения о том, как использовать плагин в обычных Java-приложениях и контейнерах сервлетов, можно найти: https://github.com/haraldk/TwelveMonkeys