Java.ImageIO.write is completely damaged PNG and / or BMP with incorrect data

Any help that most appreciate is driving me crazy. I am doing exactly what I can find on Google etc., and it does not work.

I find it difficult to create and write BMP or PNG images in java. Either way, I was going to go with BMP, but I get the image that is right at the bottom for what I want, but the top is just a black block a lot of time (not always).

In any other file format, including PNG, the resulting file is completely corrupted. Java says that PNG, BMP and others are supported on my system according to the filetypessupported method.

If you're wondering what this is for, I'm trying to make a representation of an area based on robot sensors.

And if you're wondering why I'm not using Graphics2d to draw a rectangle, and not pixel by pixel, Graphics2d seems to draw rectangles that are larger than what I ask.

Here is my code if I wrote PNG (with a lot of cuts) and commented on bmp:

private BufferedImage bufImage = null; private ImageIO imageIO = null; private int blobSize = 5; private String pngPath = f.getAbsolutePath() + "test.png"; private java.io.File f = new java.io.File(""); private String bmpPath = f.getAbsolutePath() + "test.bmp"; Map(int sizeX, int sizeY){ bufImage = new BufferedImage(sizeX, sizeY, BufferedImage.TYPE_INT_RGB); //set all pixels of bufImage to white for (int x = 0; x < sizeX; x++){ for (int y = 0; y < sizeY; y++){ bufImage.setRGB(x, y, Color.WHITE.getRGB()); } } saveBMP(); } public void addObstacle(int x, int y, int fiducial){ //invert y (y == 0 is upper left on bitmap) y = 1674 - y; //10*10 pixels for (int w = x; w < x + blobSize && w < sizeX && w >= 0 ; w++){ for (int h = y; h < y + blobSize && h < sizeY && h >= 0; h++){ try{ bufImage.setRGB(w, h, Color.BLACK.getRGB()); //System.out.println(h); } catch (ArrayIndexOutOfBoundsException e){ System.out.println("x: " + w + " y: " + h); } //System.out.println(h); } } //bufImage.setRGB(x, y, Color.BLACK.getRGB()); saveBMP(); } public void saveBMP(){ try { RenderedImage rendImage = bufImage; //ImageIO.write(rendImage, "bmp", new File(bmpPath)); ImageIO.write(rendImage, "PNG", new File(pngPath)); //ImageIO.write(rendImage, "jpeg", new File(jpegPath)); } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); } } 
0
source share
2 answers

Perhaps you could start with what works and works from there?

Note that to improve performance, you must create a "compatible" BufferedImage:

 GraphicsEnvironment.getLocalGraphicsEnvironment().getDefaultScreenDevice().getDefaultConfiguration().createCompatibleImage(width,height,Transparency.TRANSLUCENT) 

whose "ARGB" will depend on your OS.

Here is the code that creates the 320x160 whole white .png file based on your code.

 import javax.imageio.ImageIO; import java.awt.*; import java.awt.image.BufferedImage; import java.awt.image.RenderedImage; import java.io.File; import java.io.IOException; public class SO { public static void main( final String[] args ) { final BufferedImage img = map( 320, 160 ); savePNG( img, "/tmp/test.png" ); } private static BufferedImage map( int sizeX, int sizeY ){ final BufferedImage res = new BufferedImage( sizeX, sizeY, BufferedImage.TYPE_INT_RGB ); //set all pixels of bufImage to white for (int x = 0; x < sizeX; x++){ for (int y = 0; y < sizeY; y++){ res.setRGB(x, y, Color.WHITE.getRGB() ); } } return res; } private static void savePNG( final BufferedImage bi, final String path ){ try { RenderedImage rendImage = bi; //ImageIO.write(rendImage, "bmp", new File(bmpPath)); ImageIO.write(rendImage, "PNG", new File(path)); //ImageIO.write(rendImage, "jpeg", new File(jpegPath)); } catch ( IOException e) { // TODO Auto-generated catch block e.printStackTrace(); } } } 

Note that setRGB (...) always works in ARGB, so:

  res.setRGB(x, y, Color.WHITE.getRGB() ); 

and

  res.setRGB(x, y, 0xFFFFFFFF ); 

are equivalent.

There is a more efficient way to fill a solid background, but knowing how to manipulate the components of ARGB pixels directly can come in handy when speed is needed.

+1
source

I do not see a problem with your approach, although I guess about your calling code. Please note that instead of directly setting pixels, you can draw into a buffered image. Here is the call to get(100, 100) :

alt text

 private BufferedImage get(int sizeX, int sizeY) { BufferedImage bufImage = new BufferedImage( sizeX, sizeY, BufferedImage.TYPE_INT_RGB); for (int x = 0; x < sizeX; x++) { for (int y = 0; y < sizeY; y++) { bufImage.setRGB(x, y, Color.RED.getRGB()); } } Graphics2D g2d = bufImage.createGraphics(); g2d.setColor(Color.green); g2d.fillRect(0, 0, sizeX / 2, sizeY / 2); g2d.fillRect(sizeX / 2, sizeY / 2, sizeX, sizeY); g2d.dispose(); try { ImageIO.write(bufImage, "PNG", new File("test.png")); } catch (IOException ex) { ex.printStackTrace(); } return bufImage; } 

Application: ImageIO.write(bufImage, "BMP", new File("test.bmp")); also works

+1
source

All Articles