Sunday 22 October 2017

java - Numbers of source Raster bands and source color space components do not match when i read image

Open the images with any image
viewer/editor, and save them in a "standard"
format




I wonder how
the images have been created in the first place. My guess would be that you have used
some fancy, sophisticated image manipulation program for the "cropping" that you
mentioned, and that this program allows storing images in some unusual formats, and that
you did (or did not) modify some options that have been available when saving the image,
not knowing wha exactly these options meant (apologies if I underestimate your
familiarity with image formats and color spaces
here...).



However, the reason for the problem is
that the images are stored with some strange form of an href="http://en.wikipedia.org/wiki/YPbPr" rel="nofollow">YPbPr or href="http://en.wikipedia.org/wiki/YCbCr" rel="nofollow">YCbCr color space
(I did not manage to figure out that one exactly, but they are both not supported in
ImageIO by default).



Neither of my attempts to
apply the standard rel="nofollow">color conversions for YPbPb->RGB or YCbCb->RGB seemed
to reproduce the exact original colors, but as you might notice
when skimming over the Wikipedia articles: Quite some academic steam was let off in the
world of color spaces....



Again: I'd
strongly recommend you to open the images with any image
viewer/editor, and save them in a "standard" format. And preferably as a PNG, because
JPG is not really suitable for these kinds of images. JPG is more intended for "natural"
images, like photos. For such "artificial" images, the compression must be very low to
avoid artifacts.



However, this program shows the
image with nearly correct colors, but the color conversion still
seems to be not entirely correct.




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 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
{
for
(int y=0; 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;

}
}


(Note:
This could be implemented much simpler, with a ColorConvertOp
that converts into the RGB color space from the color space that was used for the image.
But as mentioned above, I did not manage to figure out which color
space was used for saving the image, and even if I knew it, one would have to create an
appropriate ColorSpace implementation. The first websearch
results, like href="http://robocup.bowdoin.edu/public/docs/tool/d2/d97/YCbCrColorSpace_8java_source.html"
rel="nofollow">YCbCrColorSpace.java, did not work for the given input
images...)

No comments:

Post a Comment

php - file_get_contents shows unexpected output while reading a file

I want to output an inline jpg image as a base64 encoded string, however when I do this : $contents = file_get_contents($filename); print &q...