I am trying to attach different images into a image. This is happening but after attaching the color of the image changes. Here is my existing code
BufferedImage baseImg = getBaseImage(src);
Graphics2D g = baseImg.createGraphics();
BufferedImage bmg = getBufferedImageFromSrc(path);
String[] coords = coord.split(",");
g.drawImage((Image)bmg,(int) Double.parseDouble(coords[0]),(int) Double.parseDouble(coords[1]), 60,60,Color.white,null);
g.dispose();
String path = "C://resources/temp.jpeg";
ImageIO.write(bimg, "jpeg", new File(path));
i am able to add the image to the base image at the specified co-ordinates but the base image colour is getting changed.
Here is a sample image
Thanks in advance
i need to write a program which takes an image, resizes and rotates it and then saves it out. The first 2 point are done, but now I have a problem. Every time I convert a grayscale image it becomes a monochrome image.
I load the target image with the following command:
BufferedImage sourceimg = ImageIO.read(input);
And after I scaled and rotated it I save it out with the following command:
BufferedImage newimg = new BufferedImage(sourceimg.getHeight(), sourceimg.getWidth(), sourceimg.getType());
op.filter(sourceimg, newimg);
sourceimg = newimg;
ImageIO.write(sourceimg, "png", outputFile);
This works fine for every image except grayscale images. I have already tried a workaround by setting the type of every image to ARGB but there has to be another way. Is there a way to get the IndexColorModel of an given image?
The problem ist now solved, i just had to change:
BufferedImage newimg = new BufferedImage(sourceimg.getHeight(), sourceimg.getWidth(), sourceimg.getType());
to:
BufferedImage newimg = new BufferedImage(sourceimg.getWidth(), sourceimg.getHeight(), BufferedImage.TYPE_INT_ARGB);
There are other solutions, especially if you like to keep the original image type (ie. keep palette of IndexColorModel images etc.).
In fact, the easiest is to just do (assuming op is a standard BufferedImageOp):
BufferedImage newimg = op.filter(sourceimg, null);
Here a new, compatible image will be created for you, and will be of correct size to keep the result of the operation.
Another option, which will preserve the image type and color model, is slightly more verbose:
ColorModel sourceCM = sourceimg.getColorModel(); // Will be the IndexColorModel in your case
// I'm assuming you are deliberately switching width/height to rotate 90 deg
WritableRaster raster = sourceCM.createCompatibleWritableRaster(sourceimg.getHeight(), sourceimg.getWidth());
BufferedImage newimg = new BufferedImage(sourceCM, raster, sourceCM.isAlphaPremultiplied(), null);
op.filter(sourceimg, newimg);
I am trying to convert an image to gray scale image using Java. The problem here is, when I am trying to save that image after converting into gray scale it is showing a black image. I am little unaware of this image conversions. I would like to know why it is not working, and your answers will help me in my project. Thank you.
BufferedImage image = ImageIO.read(fileContent);
File outputFile = new File(date1);
ImageIO.write(image1, "png", outputFile);
(This is the color image obtained from html page, and it is working properly. And when I am trying to display/save this image, color image is visible. But the problem arises when the below code is used to convert color image to gray scale image.)
BufferedImage image1 = new BufferedImage(width, height,BufferedImage.TYPE_BYTE_GRAY);
Graphics graphics = image1.getGraphics();
graphics.drawImage(image, 0, 0, null);
graphics.dispose();
File outputFile = new File(date1);
ImageIO.write(image1, "png", outputFile);
There are color space conversion issues. You can manually convert each pixel of the output image to grayscale and set the pixels of the output image this way:
int gray = red * 0.299 + green * 0.587 + blue * 0.114
or use the ColorConvertOp class to do the conversion for you:
BufferedImage in = ImageIO.read(inputFile);
BufferedImage out = new BufferedImage(in.getWidth(), in.getHeight(), BufferedImage.TYPE_INT_ARGB);
ColorConvertOp op = new ColorConvertOp(in.getColorModel().getColorSpace(), ColorSpace.getInstance(ColorSpace.CS_GRAY), null);
op.filter(in, out);
ImageIO.write(out, "png", outputFile);
I have to take screenshot of some area on the desktop.
I am doing it this way:
BufferedImage image = new Robot().createScreenCapture(area.areaRect);
ImageIO.write(image, "jpg", new File(current));
//then I paint in on JPanel
and every screenshot saved to .jpg looks like this one:
It doesn't happen for pngs and gifs.
I googled about this problem and found a solution, creating image by the Toolkit class:
Image toolkitImage = Toolkit.getDefaultToolkit().createImage(imageUrl);
but I have no idea how can I take screenshot with it.
The JPEG writer in ImageIO doesn't take the ColorModel into account when writing the file, as JPEG does not have an alpha channel. The Alpha channel is the A part of ARGB that specifies the transparency value for each pixel. Most image clients will assume that JPEG don't have alpha values as that is the standard behavior.
The writer in ImageIO will write a file with the colors shifted, like the lovely shade of salmon as background in the picture. This is because the writer will write down the values wrong when it really should be writing them in RBG.
The workaround is to paint the image to a BufferedImage with RBG as ColorModel. Here is some sample code:
// argbBuffer is the ARGB Image that should be written as JPEG:
WritableRaster raster = argbBuffer.getRaster();
WritableRaster newRaster = raster.createWritableChild(0, 0, width, height, 0, 0, new int[] {0, 1, 2});
// create a ColorModel that represents the one of the ARGB except the alpha channel:
DirectColorModel cm = (DirectColorModel)argbBuffer.getColorModel();
DirectColorModel newCM = new DirectColorModel(cm.getPixelSize(),
cm.getRedMask(), cm.getGreenMask(), cm.getBlueMask());
// now create the new buffer that is used ot write the image:
BufferedImage rgbBuffer = new BufferedImage(newCM, newRaster, false, null);
I'd like to convert gif images to jpeg using Java. It works great for most images, but I have a simple transparent gif image:
Input gif image http://img292.imageshack.us/img292/2103/indexedtestal7.gif
[In case the image is missing: it's a blue circle with transparent pixels around it]
When I convert this image using the following code:
File file = new File("indexed_test.gif");
BufferedImage image = ImageIO.read(file);
File f = new File("indexed_test.jpg");
ImageIO.write(image, "jpg", f);
This code works without throwing an Exception, but results an invalid jpeg image:
[In case the image is missing: IE cannot show the jpeg, Firefox shows the image with invalid colors.]
I'm using Java 1.5.
I also tried converting the sample gif to png with gimp and using the png as an input for the Java code. The result is the same.
Is it a bug in the JDK? How can I convert images correctly preferably without 3rd party libraries?
UPDATE:
Answers indicate that jpeg conversion cannot handle transparency correctly (I still think that this is a bug) and suggest a workaround for replacing transparent pixels with predefined color. Both of the suggested methods are quite complex, so I've implemented a simpler one (will post as an answer). I accept the first published answer with this workaround (by Markus). I don't know which implementation is the better. I go for the simplest one still I found a gif where it's not working.
For Java 6 (and 5 too, I think):
BufferedImage bufferedImage = new BufferedImage(image.getWidth(null), image.getHeight(null), BufferedImage.TYPE_INT_RGB);
g = bufferedImage.createGraphics();
//Color.WHITE estes the background to white. You can use any other color
g.drawImage(image, 0, 0, bufferedImage.getWidth(), bufferedImage.getHeight(), Color.WHITE, null);
As already mentioned in the UPDATE of the question I've implemented a simpler way of replacing transparent pixels with predefined color:
public static BufferedImage fillTransparentPixels( BufferedImage image,
Color fillColor ) {
int w = image.getWidth();
int h = image.getHeight();
BufferedImage image2 = new BufferedImage(w, h,
BufferedImage.TYPE_INT_RGB);
Graphics2D g = image2.createGraphics();
g.setColor(fillColor);
g.fillRect(0,0,w,h);
g.drawRenderedImage(image, null);
g.dispose();
return image2;
}
and I call this method before jpeg conversion in this way:
if( inputImage.getColorModel().getTransparency() != Transparency.OPAQUE) {
inputImage = fillTransparentPixels(inputImage, Color.WHITE);
}
The problem (at least with png to jpg conversion) is that the color scheme isn't the same, because jpg doesn't support transparency.
What we've done successfully is something along these lines (this is pulled from various bits of code - so please forgive the crudeness of the formatting):
File file = new File("indexed_test.gif");
BufferedImage image = ImageIO.read(file);
int width = image.getWidth();
int height = image.getHeight();
BufferedImage jpgImage;
//you can probably do this without the headless check if you just use the first block
if (GraphicsEnvironment.isHeadless()) {
if (image.getType() == BufferedImage.TYPE_CUSTOM) {
//coerce it to TYPE_INT_ARGB and cross fingers -- PNGs give a TYPE_CUSTOM and that doesn't work with
//trying to create a new BufferedImage
jpgImage = new BufferedImage(width,height,BufferedImage.TYPE_INT_ARGB);
} else {
jpgImage = new BufferedImage(width, height, image.getType());
}
} else {
jgpImage = GraphicsEnvironment.getLocalGraphicsEnvironment().
getDefaultScreenDevice().getDefaultConfiguration().
createCompatibleImage(width, height, image.getTransparency());
}
//copy the original to the new image
Graphics2D g2 = null;
try {
g2 = jpg.createGraphics();
g2.setRenderingHint(RenderingHints.KEY_INTERPOLATION,
RenderingHints.VALUE_INTERPOLATION_BICUBIC);
g2.drawImage(image, 0, 0, width, height, null);
}
finally {
if (g2 != null) {
g2.dispose();
}
}
File f = new File("indexed_test.jpg");
ImageIO.write(jpgImage, "jpg", f);
This works for png to jpg and gif to jpg. And you will have a white background where the transparent bits were. You can change this by having g2 fill the image with another color before the drawImage call.
3 months late, but I am having a very similar problem (although not even loading a gif, but simply generating a transparent image - say, no background, a colored shape - where when saving to jpeg, all colors are messed up, not only the background)
Found this bit of code in this rather old thread of the java2d-interest list, thought I'd share, because after a quick test, it is much more performant than your solution:
final WritableRaster raster = img.getRaster();
final WritableRaster newRaster = raster.createWritableChild(0, 0, img.getWidth(), img.getHeight(), 0, 0, new int[]{0, 1, 2});
// create a ColorModel that represents the one of the ARGB except the alpha channel
final DirectColorModel cm = (DirectColorModel) img.getColorModel();
final DirectColorModel newCM = new DirectColorModel(cm.getPixelSize(), cm.getRedMask(), cm.getGreenMask(), cm.getBlueMask());
// now create the new buffer that we'll use to write the image
return new BufferedImage(newCM, newRaster, false, null);
Unfortunately, I can't say I understand exactly what it does ;)
If you create a BufferedImage of type BufferedImage.TYPE_INT_ARGB and save to JPEG weird things will result. In my case the colors are scewed into orange. In other cases the produced image might be invalid and other readers will refuse loading it.
But if you create an image of type BufferedImage.TYPE_INT_RGB then saving it to JPEG works fine.
I think this is therefore a bug in Java JPEG image writer - it should write only what it can without transparency (like what .NET GDI+ does). Or in the worst case thrown an exception with a meaningful message e.g. "cannot write an image that has transparency".
JPEG has no support for transparency. So even when you get the circle color correctly you will still have a black or white background, depending on your encoder and/or renderer.
BufferedImage originalImage = ImageIO.read(getContent());
BufferedImage newImage = new BufferedImage(originalImage.getWidth(), originalImage.getHeight(), BufferedImage.TYPE_3BYTE_BGR);
for (int x = 0; x < originalImage.getWidth(); x++) {
for (int y = 0; y < originalImage.getHeight(); y++) {
newImage.setRGB(x, y, originalImage.getRGB(x, y));
}
}
ImageIO.write(newImage, "jpg", f);
7/9/2020 Edit: added imageIO.write