问题 当我读取图像时,源光栅带和源颜色空间组件的数量不匹配[重复]


这个问题在这里已有答案:


8968
2018-04-20 11:04


起源

你能提供你想要加载的确切JPG文件吗?可以在这里使用“简单”,具体的解决方法,例如使用任何图像查看器程序加载图像,然后再次保存(然后,可能采用可以无问题地读取的格式)? - Marco13
@ Marco13完成!! - Computernerd


答案:


这个问题已在这里得到解答: https://stackoverflow.com/a/18400559/1042999 这是一个非常优雅的解决方案。该解决方案涉及使用ImageIO插件,实现对默认ImageIo实现不支持的多种格式的支持。可以找到有关如何在常规Java应用程序和servlet容器中使用该插件的详细信息: https://github.com/haraldk/TwelveMonkeys


5
2018-01-05 14:58



Maven依赖: <dependency><groupId>com.twelvemonkeys.imageio</groupId><artifactId>imageio-jpeg</artifactId><version>3.3.1</version></dependency> - Edd


使用任何图像查看器/编辑器打开图像,并以“标准”格式保存

我想知道图像是如何创建的。我的猜测是你已经使用了一些花哨的,复杂的图像处理程序来进行你提到的“裁剪”,而且这个程序允许以一些不寻常的格式存储图像,并且你做了(或没有)修改了一些选项。在保存图像时可用,不知道这些选项的确切含义(如果我低估了您对图像格式和色彩空间的熟悉程度,请道歉......)。

然而,问题的原因是图像以一些奇怪的形式存储 的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,对于给定的输入图像不起作用...)


4
2018-04-20 16:56



MS Paint似乎吐出了有这个问题的文件,至少对我而言。什么是一个很好的免费应用程序或(甚至更好)网站来解决这个问题? - ArtOfWarfare
@ArtOfWarfare我不知道(并且几乎没有预料到)MS Paint可以创建这样的文件。 (在这里吞下关于“微软和标准”的咆哮)。关于应用程序:基本上任何程序都应该能够创建“正确的”PNG文件,我很满意 irfanview.com ,但你可以选择你喜欢的,或(如果你不关心潜在的隐私/版权问题),网络搜索的任何结果,如“在线png转换器”...... - Marco13
我特别需要将文件保留为jpeg - 这是客户的要求(我同意png在各方面都会更好,但是他们会写支票,所以我按照他们的意思行事)。无论如何,我找到了一个解决方案 - 我在gimp中打开文件然后导出为具有所有默认设置的jpeg。 - ArtOfWarfare