I create this image with g2d:
Here is the code:
BufferedImage bufferedImage = new BufferedImage(408, 408, BufferedImage.TYPE_INT_RGB);
Graphics2D g2d = bufferedImage.createGraphics();
List<Pixel> pixels = cacheRepo.findAll();
pixels.stream().forEach(pixel -> {
g2d.setColor(getColorFromPixel(pixel));
g2d.fillRect(getPos(pixel.getPosition().x), getPos(pixel.getPosition().y), 20, 20);
});
Now I am trying to rotate it 90° anticlok so that the bleu square appear on the lower left:
So I add this:
g2d.rotate(Math.toRadians(90));
g2d.drawRenderedImage(bufferedImage, null);
But the rotation doesn't occur (I still have the same image).
Here is the complete piece of code, with the part that save image:
// Constructs a BufferedImage of one of the predefined image types.
BufferedImage bufferedImage = new BufferedImage(408, 408, BufferedImage.TYPE_INT_RGB);
// Create a graphics which can be used to draw into the buffered image
Graphics2D g2d = bufferedImage.createGraphics();
List<Pixel> pixels = cacheRepo.findAll();
pixels.stream().forEach(pixel -> {
g2d.setColor(getColorFromPixel(pixel));
g2d.fillRect(getPos(pixel.getPosition().x), getPos(pixel.getPosition().y), 20, 20);
});
g2d.rotate(Math.toRadians(90));
g2d.drawRenderedImage(bufferedImage, null);
g2d.dispose();
// Save as PNG
File file = new File("myimage.png");
try {
ImageIO.write(bufferedImage, "png", file);
} catch (IOException e) {
e.printStackTrace();
}
Transformations should be applied BEFORE any operations you want to be effected by them, transformations won't affect anything that was done before it...
BufferedImage bufferedImage = new BufferedImage(408, 408, BufferedImage.TYPE_INT_RGB);
// Create a graphics which can be used to draw into the buffered image
Graphics2D g2d = bufferedImage.createGraphics();
g2d.rotate(Math.toRadians(90));
List<Pixel> pixels = cacheRepo.findAll();
pixels.stream().forEach(pixel -> {
g2d.setColor(getColorFromPixel(pixel));
g2d.fillRect(getPos(pixel.getPosition().x), getPos(pixel.getPosition().y), 20, 20);
});
//g2d.rotate(Math.toRadians(90));
// Not sure what you're hoping to achieve here
//g2d.drawRenderedImage(bufferedImage, null);
g2d.dispose();
If you prefer, use two BufferedImages. Render the "normal" content to the first, then use the second to paint the first, but with a rotation transformation ... because transformations do my head in 😝
using your code draw a black image
You probably need to supply a anchor point around which the image can be rotated, otherwise it will be rated about the top/left corner
And you'll forgive me, but it's not like this kind of think hasn't been asked before
Java rotate image turns part of background black
Rotate a buffered image in Java
Rotating Image with AffineTransform
Rotating an Image object
I'm rotating image in java but want to save rotated image
How to save rotated buffered image in another buffered image?
BufferedImage rotated, change resulting background
Related
by using Canvas and JS I can draw a shape like this and have the x,y of each point :
Tha area can be choosen by more than 4 points, look at this link to have an idea.
I need to save and crop the image of the selected area by using the points. I can not use BufferedImage as it is just rectangular. Which lib in java I can use?
Okay, so starting with...
I used...
BufferedImage source = ImageIO.read(new File("Example.jpg"));
GeneralPath clip = new GeneralPath();
clip.moveTo(65, 123);
clip.lineTo(241, 178);
clip.lineTo(268, 405);
clip.lineTo(145, 512);
clip.closePath();
Rectangle bounds = clip.getBounds();
BufferedImage img = new BufferedImage(bounds.width, bounds.height, BufferedImage.TYPE_INT_ARGB);
Graphics2D g2d = img.createGraphics();
clip.transform(AffineTransform.getTranslateInstance(-65, -123));
g2d.setClip(clip);
g2d.translate(-65, -123);
g2d.drawImage(source, 0, 0, null);
g2d.dispose();
ImageIO.write(img, "png", new File("Clipped.png"));
to generate...
Now, the image is rectangular, that's just the way it works
Now, setClip is quite rough and isn't effect by any RenderingHints, you could make use of "soft clipping" instead, which is more involved, but generates a nicer results. See this example and this exmaple for more details
I'm using an ImageIcon in order to display an image in a JPanel. I need to implement zoom in / zoom out functions over that image.
If I use the following code it does the zoom out/in work, but the quality of the image reduces significantly due to the transparency.
BufferedImage resizedImage = new BufferedImage(newImageWidth, newImageHeight, BufferedImage.TYPE_INT_ARGB);
Graphics2D g = resizedImage.createGraphics();
g.drawImage(image, 0, 0, newImageWidth , newImageHeight , null);
g.dispose();
return resizedImage;
I have read that this other following code is a solution but it gives me the same result as above.
AffineTransform af = new AffineTransform();
af.scale(zoomLevel, zoomLevel);
AffineTransformOp operation = new AffineTransformOp(af, AffineTransformOp.TYPE_NEAREST_NEIGHBOR);
BufferedImage result = operation.filter((BufferedImage) image, null);
return result;
Any suggestion? Thanks in advance guys.
Im using the code
BufferedImage imgIn = ImageIO.read(is);
BufferedImage image;
if (imgIn.getType() != BufferedImage.TYPE_BYTE_INDEXED) {
image = new BufferedImage(imgIn.getWidth(), imgIn.getHeight(), BufferedImage.TYPE_4BYTE_ABGR);
ColorConvertOp cco = new ColorConvertOp(imgIn.getColorModel()
.getColorSpace(), image.getColorModel().getColorSpace(), null);
cco.filter(imgIn, image);
} else {
image = imgIn;
}
When I'm pulling in an image with a Bit Depth of 4 it makes the imgIn a Type_Byte_Binary. When It gets converted to Type_4Byte_ABGR anything with partial transparency changes color and loses all alpha. Fully transparent pixels and Fully Opaque pixels remained unchanged.
Is there anything I can do to keep the partially transparent pixels from changing?
Thanks.
Most likely ColorConvertOp isn't what you are after here, because the images are all in RGB (sRGB) color space (IndexColorModel doesn't support other color spaces).
Instead, just paint your TYPE_BYTE_INDEXED or TYPE_BYTE_BINARY onto a TYPE_4BYTE_ABGR image, and any transparency should be preserved.
BufferedImage image = new BufferedImage(imgIn.getWidth(), imgIn.getHeight(), BufferedImage.TYPE_4BYTE_ABGR);
Grphics2D g = image.createGraphics();
try {
g.drawImage(imgIn, 0, 0, null);
}
finally {
g.dispose();
}
I know this is something to do with compositing but I can't work out what. In an earlier section of code, a particular list of pixels in a BufferedImage are set to be transparent black:
for(Pixel p : closed){
Color c = new Color(image.getRGB(p.x, p.y));
Color newC = new Color(0,0,0, 0);
image.setRGB(p.x, p.y, newC.getRGB() & 0x00000000);
}
if(andCrop){
image = image.getSubimage(left, top, right-left, bottom-top);
}
return image;
Then I attempt to write the image out:
try {
BufferedImage out = new BufferedImage(image.getWidth(), image.getHeight(), java.awt.Transparency.TRANSLUCENT);
Graphics2D g2d = out.createGraphics();
g2d.setComposite(AlphaComposite.Clear);
g2d.fillRect(0, 0, image.getWidth(), image.getHeight());
g2d.setComposite(AlphaComposite.Src);
g2d.drawImage(image, 0, 0, image.getWidth(), image.getHeight(), null);
g2d.dispose();
File outputfile = new File(file);
ImageIO.write(out, "png", outputfile);
} catch (IOException e) {
}
Now, I know that 'out' is clear before I attempt to draw the image onto it. What I'm not getting is what's wrong with my compositing. Instead of coming out as transparent, I'm getting full-black.
All bufferedimages used are INT_ARGB.
EDIT - This has been solved. The image source was from ImageIO.read and the BufferedImage returned did not support alpha. A quick post-read conversion let the rest of the code run smoothly.
Things that comes to my mind... (thanks to Andrew):
java.awt.Transparency.TRANSLUCENT = 3
TYPE_INT_ARGB = 2
TYPE_INT_ARGB_PRE = 3
public BufferedImage(int width,
int height,
int imageType)
Constructs a BufferedImage of one of the predefined image types. (TYPE_...)
http://docs.oracle.com/javase/1.4.2/docs/api/java/awt/image/BufferedImage.html
so it seems as basically it's a mixup.
Besides, what is the effect you want to achieve? you clear an empty image, then draw fully transparent pixels to it... I just don't get it.
Whelp, this has been downvoted now so I'm not sure this will be relevant, but the issue was that the original BufferedImage was being read in by ImageIO, and this image was not supporting ARGB. A quick post-read conversion allowed the rest of the code to work.
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