I'm trying to convert an RGB image to a CMYK image using Java.
I've looked at this code:
BufferedImage rgbImage = ImageIO.read(new File("d:\\Temp\\IMG_1748x2480.jpg"));
BufferedImage cmykImage = null;
ColorSpace cpace = new ICC_ColorSpace(ICC_Profile.getInstance(
TestConvertRGBToCMYK.class.getClassLoader().getResourceAsStream(
"CMYK_Profiles/USWebCoatedSWOP.icc")));
ColorConvertOp op = new ColorConvertOp(rgbImage.getColorModel().getColorSpace(), cpace, null);
cmykImage = op.filter(rgbImage, null);
ImageIO.write(cmykImage, "JPEG", new File("d:\\Temp\\CMYK_Sample_RGB_OUTPUT2.jpg"));
But the problem is that the result image appears black.
After reading the Google point of view (posts) I've read that this is normal, because the views aren't compatible with the CMYK images, but PDF views are. But the problem is if I put the image in the PDF, the image continues to appear black.
Does any one have any idea for what is going one? Or have any other converter that does a better conversion?
Just an update of my problem.
Use ImageMagick software and i get all my problems resolved.
Cheers,
Bigster
Related
My goal here is to read in a CMYK Tiff image, mess with the pixels and then write out a new CMYK Tiff image. I am having a tough time finding any kind of example for this and any help would be greatly appreciated. Originally, I was doing this with RGB JPEG images without a problem using code like this:
// read input image
BufferedImage in = ImageIO.read(inputJPGAsFile);
// made output image that is same size as input image
FinalImage = new BufferedImage(in.getWidth(), in.getHeight(), BufferedImage.TYPE_INT_ARGB);
// mess with pixels in output image
// write as JPG
ImageIO.write(FinalImage, "JPEG", outputJPGAsFile);
However, now I am trying to figure out how to change this to work with CMYK Tiffs. It doesn't seem like there is a type for BufferedImage that would be anything like "TYPE_INT_CMYK". So then I was trying to use the ColorModel of the input image, but this crashes with the following error Exception in thread "JavaFX Application Thread" java.lang.IllegalArgumentException: Unknown color space. Any help on this would be greatly appreciated.
// read input image
BufferedImage in = ImageIO.read(inputTiffAsFile);
// get the CMYK color space of input image
ColorModel colorModel = in.getColorModel();
BufferedImage FinalImage = new BufferedImage(colorModel, colorModel.createCompatibleWritableRaster(100, 100), colorModel.isAlphaPremultiplied(), null);
// Copy in to FinalImage with some pixel manipulation
// write final image
ImageIO.write(FinalImage, "TIFF", outputTiffAsFile);
Also, I put java 9 because that is what I have been using, but I can upgrade to a newer version if that makes things easier. Thanks!
I've to read barcode from an uploaded image file for a java based web application. I've tried Zxing and other similar libraries, but it will work only if we upload precise images. Could anyone suggest an api for reading barcode from an image? The image could be a randomly clicked one and it might contain other data also. From that, we have to identify the barcode and decode it.
As you did not provide a whole lot of information I will try to help you out with what I think what the problem is.
I think ZXing should be the right way to go. The barcode decoder searches for the barcode within an image per default. If you have an image wich only contains the barcode itself you can set the hint PURE_BARCODE to speed up decoding. There only could be problems if you have multiple barcodes within a single image.
Your problem seems to be the uploaded image not ZXing. I would suggest checking whether the image is uploaded correctly.
Here is an example of decoding a BufferedImage with any ZXing reader.
public void decodeCode() throws IOException, NotFoundException, FormatException, ChecksumException {
BufferedImage image = ImageIO.read(yourImage);
BinaryBitmap bitmap = convertImageToBinaryBitmap(image);
Result result = reader.decode(bitmap, hints);
assertNotNull("DecoderResult must not be null", result);
System.out.println(result.getText());
}
protected BinaryBitmap convertImageToBinaryBitmap(BufferedImage image) {
int[] pixels = image.getRGB(0, 0,
image.getWidth(), image.getHeight(),
null, 0, image.getWidth());
RGBLuminanceSource source = new RGBLuminanceSource(image.getWidth(),
image.getHeight(),
pixels);
return new BinaryBitmap(new HybridBinarizer(source));
}
Im trying to apply the code posted in this post:
How to convert from CMYK to RGB in Java correctly?
The Answer from the guy named Codo works for me so far, but my source is not a file, its an object that gets converted into a BufferedImage with
stream = (PRStream)object;
PdfImageObject image = new PdfImageObject(stream);
//this does not work
BufferedImage bi = image.getBufferedImage();
The guy has a method that returns a BufferedImage from a file like so
public BufferedImage readImage(File file) throws IOException, ImageReadException
but i want to use
BufferedImage bi = readImage(image.getBufferedImage());
instead of
File f = new File("/Users/adlib/Documents/projekte/pdf_compress/envirement/eclipse_luna/WORKSPACE/PDFCompression/src/Bild.jpg");
BufferedImage bi = readImage(f);
cause im ectracting all the images from a pdf file using iText.
I messed around with the code (changed file to BufferedImage and added streams) but a just dont get it to work. The File as Input image works fine, but not really what i need. What do i need to change to get This guys code to work with BufferedImage as input for the readImage() method?
Here is the complete code of this guy
https://stackoverflow.com/a/12132630/4944643
He uses Sanselan / Apache Commons Imaging
I'm not sure how iText extracts images, but chances are good it's using ImageIO. If so, you can just install (or depend on, using Maven) the TwelveMonkeys JPEG ImageIO plugin, and
BufferedImage bi = image.getBufferedImage();
...should just work.
The above mentioned plugin does support CMYK (and Adobe YCCK) JPEGs.
If iText doesn't use ImageIO, the above won't work (ie. when you already have a BufferedImage, it's too late to make the correct conversion). You will instead need to get to the bytes of the underlying PDF (using the getImageAsBytes() method), and use ImageIO (via the TwelveMonkeys JPEG plugin) to decode it:
byte[] imgBytes = image.getImageAsBytes();
BufferedImage bi = ImageIO.read(new ByteArrayInputStream(imgBytes));
I have multiple images with a custom profile embedded in them and want to convert the image to sRGB in order to serve it up to a browser. I have seen code like the following:
BufferedImage image = ImageIO.read(fileIn);
ColorSpace ics = ColorSpace.getInstance(ColorSpace.CS_sRGB);
ColorConvertOp cco = new ColorConvertOp(ics, null);
BufferedImage result = cco.filter(image, null);
ImageIO.write(result, "PNG", fileOut);
where fileIn and fileOut are File objects representing the input file and output file respectively. This works to an extent. The problem is that the resulting image is lighter than the original. If I was to convert the color space in photoshop the colors would appear the same. In fact if I pull up both images with photoshop and take a screen shot and sample the colors, they are the same. What is photoshop doing that the code above isn't and what can I do to correct the problem?
There are various types of images being converted, including JPEG, PNG, and TIFF. I have tried using TwelveMonkeys to read in JPEG and TIFF images and I still get the same effect, where the image is too light. The conversion process seems worst when applied to an image that didn't have an embedded profile in the first place.
Edit:
I've added some sample images to help explain the problem.
This image is the one with the color profile embedded in it. Viewed on some browsers there won't be a noticeable difference between this one and the next but viewed in Chrome on Mac OSX and Windows it currently appears darker than it should. This is where my problem originates in the first place. I need to convert the image to something that will show up correctly in Chrome.
This is an image converted with ImageMagick to the Adobe RGB 1998 color profile, which Chrome appears to be able to display correctly.
This is the image that I converted using the code above and it appears lighter than it should.
(Note that the images above are on imgur so to make them larger, simply remove the "t" from the end of the filename, before the file extension.)
This was my initial solution which worked but I didn't like having to use ImageMagick. I have created another answer based off of the solution I ended up sticking with.
I gave in and ended up using im4java, which is a wrapper around the command line tool of image magick. When I use the following code to get a BufferedImage, it works really well.
IMOperation op = new IMOperation();
op.addImage(fileIn.getAbsolutePath());
op.profile(colorFileIn.getAbsolutePath());
op.addImage("png:-");
ConvertCmd cmd = new ConvertCmd();
Stream2BufferedImage s2b = new Stream2BufferedImage();
cmd.setOutputConsumer(s2b);
cmd.run(op);
BufferedImage image = s2b.getImage();
I can also use the library to apply a CMYK profile for print when needed. It would be nice if ColorConvertOp did the conversion correctly but for now, at least, this is my solution. In order to reach parity with my question the im4java code to achieve the same effect in the question is:
ConvertCmd cmd = new ConvertCmd();
IMOperation op = new IMOperation();
op.addImage(fileIn.getAbsolutePath());
op.profile(colorFileIn.getAbsolutePath());
op.addImage(fileOut.getAbsolutePath());
cmd.run(op);
where colorFileIn.getAboslutePath() is the location of the sRGB color profile on the machine. Since im4java is using the command line it's not as straight forward how to perform operations but the library is explained in detail here. I originally had issues with image magick not working on my Mac as explained in the question. I installed it using brew but it turns out on a Mac you have to install it like brew install imagemagick --with-little-cms. After that image magick worked fine for me.
I found a solution that doesn't require ImageMagick. Basically Java doesn't respect the profile when loading the image so if there is one it needs to get loaded. Here is a code snippet of what I did to accomplish this:
private BufferedImage loadBufferedImage(InputStream inputStream) throws IOException, BadElementException {
byte[] imageBytes = IOUtils.toByteArray(inputStream);
BufferedImage incorrectImage = ImageIO.read(new ByteArrayInputStream(imageBytes));
if (incorrectImage.getColorModel() instanceof ComponentColorModel) {
// Java does not respect the color profile embedded in a component based image, so if there is a color
// profile, detected using iText, then create a buffered image with the correct profile.
Image iTextImage = Image.getInstance(imageBytes);
com.itextpdf.text.pdf.ICC_Profile iTextProfile = iTextImage.getICCProfile();
if (iTextProfile == null) {
// If no profile is present than the image should be processed as is.
return incorrectImage;
} else {
// If there is a profile present then create a buffered image with the profile embedded.
byte[] profileData = iTextProfile.getData();
ICC_Profile profile = ICC_Profile.getInstance(profileData);
ICC_ColorSpace ics = new ICC_ColorSpace(profile);
boolean hasAlpha = incorrectImage.getColorModel().hasAlpha();
boolean isAlphaPremultiplied = incorrectImage.isAlphaPremultiplied();
int transparency = incorrectImage.getTransparency();
int transferType = DataBuffer.TYPE_BYTE;
ComponentColorModel ccm = new ComponentColorModel(ics, hasAlpha, isAlphaPremultiplied, transparency, transferType);
return new BufferedImage(ccm, incorrectImage.copyData(null), isAlphaPremultiplied, null);
}
}
else if (incorrectImage.getColorModel() instanceof IndexColorModel) {
return incorrectImage;
}
else {
throw new UnsupportedEncodingException("Unsupported color model type.");
}
}
This answer does use iText, which is generally used for PDF creation and manipulation, but it happens to process the ICC profiles correctly and I'm already depending on it for my project so it happens to be a much better choice than ImageMagick.
The code in the question then ends up as follows:
BufferedImage image = loadBufferedImage(new FileInputStream(fileIn));
ColorSpace ics = ColorSpace.getInstance(ColorSpace.CS_sRGB);
ColorConvertOp cco = new ColorConvertOp(ics, null);
BufferedImage result = cco.filter(image, null);
ImageIO.write(result, "PNG", fileOut);
which works great.
I need to read image in java.
Then I should to convert it to 565RGB
In addition it would be good to resize this image to 320 x 240.
How should I do it? Help me please.
I know such information:
1)It is possible to read image by its URL.
ImageIcon imgThisImg = new ImageIcon(imageURL);
2) It is possible to create image instances that supports 565RGB.
BufferedImage bufImg = new BufferedImage(320, 240, BufferedImage.TYPE_USHORT_565_RGB);
3)BufferedImage inherits ImageIcon , so it is possible to perform such operation
Image imgPicture ...
BufferedImage bufImg = (BufferedImage) imgPicture;
But I haven't any idea, will bufImg in this case have BufferedImage.TYPE_USHORT_565_RGB format?
How to stretch, to squeeze or to cut this picture to get size 320 x 240?
The most convenient method to read image from any source (File,Stream,URL) is
BufferedImage bufImg = ImageIO.read( imageURL );
Then to answer your question you should check this post
How to scale a BufferedImage.