Loading only part of a file into an Image - java

[Java] I'm using Images / BufferedImages (I don't currently know a better way) to load external pictures unto the canvas.
Q: Is there a possibility of loading / displaying only a part of the picture? For example, using only a 60x60 area from a larger 500x300 picture file. (I believe this is called a Sprite) Loading the file using ImageIO.
Thanks in advance.

BufferedImage input = ImageIO.read(new File(inputFile));
BufferedImage output = new BufferedImage(60, 60, BufferedImage.TYPE_INT_ARGB)
Graphics g = output .getGraphics();
g.drawImage(input, 0, 0, null); //adjust 0, 0 to some x, y if necessary
ImageIO.write(output, "png", new File(outputFile));

Related

Using Java AWT to generate monochrome 1bitpp PNG with Ancillary Chunks

I am trying to generate PNG with the following ancillary chunks (header from a reference image)
The ancillary chunks in the reference image probably came from GIMP processing.
Whereas the Image I generate with Java AWT does not have those ancillary chunks.
Here is the header of the PNG I am generating. Please note the critical chunks are identical.
Here is the code fragment
{
:
// The color map contains the colors black and white
byte[] cMap = {0, 0, 0, (byte)255, (byte)255, (byte)255};
// Create an IndexColorModel setting white as the transparent color
IndexColorModel monochrome = new IndexColorModel(8, 2, cMap, 0, false, 0);
BufferedImage img = new BufferedImage(width_img, height_img,
BufferedImage.TYPE_BYTE_INDEXED,monochrome);
Graphics2D g2d = img.createGraphics();
:
g2d.setColor(Color.WHITE);
g2d.fillRect(0, 0, width_img, height_img);
Font font = new Font("Arial Bold", Font.PLAIN, 48);
g2d.setFont(font);
FontMetrics fm = g2d.getFontMetrics();
g2d.setColor(Color.BLACK);
:
:
g2d.dispose();
imgName = ".\\Panel"+width_img+"x"+height_img+".png";
ImageIO.write(img, "png", new File(imgName));
:
}
How do I add chunks (pHYs, tIME) using Java AWT?
Any pointers will be helpful too- please let me know.
Thank you
I concluded that AWT does not support - this questions identifies couple of ways to add chunks
How can I save a PNG with a tEXt or iTXt chunk from Java?
Here is what I propose to do -
Use AWT / Graphics 2D to generate the .PNG
Read PNG, refer to the link for details on how to do it
Add the Chunks you want to add
Write it(them) back to the .PNG

Writing on a premade Image

http://www.robinswebsitestudio.com/ButtonSamples/buttons.html
The following code does write to a premade image. The resulting image, though, has significant problems.
the original png file is a 3D button with Index Transparency and a matte so that the gif file would
blend in with the page background color
the resulting gif file is flat, the matte is gone, and the text doesn’t look smooth. The resulting
file is therefore is not something you would get from Adobe Photoshop or Fireworks and doesn’t look
professional.
If anyone has suggestions, I’m all ears. Is it impossible to get a high quality 3D button using Java?
String pathToWeb = getServletContext().getRealPath(File.separator);
File f = new File(pathToWeb + "activities.png");
BufferedImage bufferedImage = ImageIO.read(f);
// Create a graphics which can be used to draw into the buffered image
Graphics2D g2d = bufferedImage.createGraphics();
g2d.setFont(new Font( "Arial", Font.BOLD, 15 ));
//create a string with black
g2d.setColor(Color.black);
g2d.drawString("Activities", 40, 40);
// Disposes of this graphics context and releases any system resources that it is using.
g2d.dispose();
// Save as gif
File file = new File("myactivities.gif");
ImageIO.write(bufferedImage, "gif", file);

Java - Image Rotation

I am trying to rotate image. I am using this Java code:
BufferedImage oldImage = ImageIO.read(new FileInputStream("C:\\workspace\\test\\src\\10.JPG"));
BufferedImage newImage = new BufferedImage(oldImage.getHeight(), oldImage.getWidth(), oldImage.getType());
Graphics2D graphics = (Graphics2D) newImage.getGraphics();
graphics.rotate(Math.toRadians(90), newImage.getWidth() / 2, newImage.getHeight() / 2);
graphics.drawImage(oldImage, 0, 0, oldImage.getWidth(), oldImage.getHeight(), null);
ImageIO.write(newImage, "JPG", new FileOutputStream("C:\\workspace\\test\\src\\10_.JPG"));
But I see strange result:
Source:
Result:
Can you please help me with this problem?
It is not enough to switch the width and height of the image. You are rotating using the center of the image as the origin of rotation. Just try the same with a sheet of paper and you will see it works the same way. You must also move the paper a little bit, which means to apply a transform to fix this. So, immediately after the rotate call, do this:
graphics.translate((newImage.getWidth() - oldImage.getWidth()) / 2, (newImage.getHeight() - oldImage.getHeight()) / 2);
The new image has different sizes because of the rotate.
try this:
BufferedImage newImage = new BufferedImage( oldImage.getWidth(),oldImage.getHeight(),oldImage.getType());
Try getting bounds of your panel on which you do your drawing
Rectangle rect = this.getBounds();
And then do:
graphics.rotate(Math.toRadians(90), (rect.width - newImage.getWidth()) / 2, (rect.height - newImage.getHeight()) / 2);
Hope that could help
Cheers!
You can write like this it will be work.
BufferedImage newImage = new BufferedImage(oldImage.getWidth(), oldImage.getHeight(), oldImage.getType());
I think the place for width and height is wrong in your code.

need to separate words from an image

how can i manipulate pixel values of a loaded image then save portion of that image into a new image(1 image per word).i found several example regarding saving or loading image but i cant understand how can i save image portion???i am trying to do it with java
I didn't tried it for myself. But studying this and that page leads me to this code:
BufferedImage im = ImageIO.read(new File("in.jpg"));
// now manipulate image
...
// now get only a part of it
Raster raster = im.getData(new Rectangle(xOffset, yOffset, width, height));
BufferedImage im2 = new BufferedImage(width, height, BufferedImage.TYPE_INT_BGR);
im2.setData(raster);
ImageIO.write(im2, "jpg", new File("out.jpg"));

Converting transparent gif / png to jpeg using java

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

Categories