title: Write dpi metadata to a jpeg image in Java
body: <p>I am trying to programatically set the dpi metadata of an jpeg image in Java. The source of the image is a scanner, so I get the horizontal/vertical resolution from TWAIN, along with the image raw data. I'd like to save this info for better print results.</p>
  
  <p>Here's the code I have so far. It saves the raw image (byteArray) to a JPEG file, but it ignores the X/Ydensity information I specify via IIOMetadata. Any advice what I'm doing wrong? </p>
  
  <p>Any other solution (third-party library, etc) would be welcome too. </p>
  
  <pre><code>import java.awt.image.BufferedImage;
  import java.awt.image.WritableRaster;
  import java.io.File;
  
  import javax.imageio.IIOImage;
  import javax.imageio.ImageIO;
  import javax.imageio.ImageTypeSpecifier;
  import javax.imageio.metadata.IIOMetadata;
  import javax.imageio.plugins.jpeg.JPEGImageWriteParam;
  import javax.imageio.stream.ImageOutputStream    
  
  import org.w3c.dom.Element;    
  import com.sun.imageio.plugins.jpeg.JPEGImageWriter;
  
  public boolean saveJpeg(int[] byteArray, int width, int height, int dpi, String file)
  {
      BufferedImage bufferedImage = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB);
  
      WritableRaster wr = bufferedImage.getRaster();
      wr.setPixels(0, 0, width, height, byteArray);
  
      try
      {           
          // Image writer 
          JPEGImageWriter imageWriter = (JPEGImageWriter) ImageIO.getImageWritersBySuffix("jpeg").next();
          ImageOutputStream ios = ImageIO.createImageOutputStream(new File(file));
          imageWriter.setOutput(ios);
  
          // Compression
          JPEGImageWriteParam jpegParams = (JPEGImageWriteParam) imageWriter.getDefaultWriteParam();
          jpegParams.setCompressionMode(JPEGImageWriteParam.MODE_EXPLICIT);
          jpegParams.setCompressionQuality(0.85f);
  
          // Metadata (dpi)
          IIOMetadata data = imageWriter.getDefaultImageMetadata(new ImageTypeSpecifier(bufferedImage), jpegParams);
          Element tree = (Element)data.getAsTree("javax_imageio_jpeg_image_1.0");
          Element jfif = (Element)tree.getElementsByTagName("app0JFIF").item(0);
          jfif.setAttribute("Xdensity", Integer.toString(dpi));
          jfif.setAttribute("Ydensity", Integer.toString(dpi));
          jfif.setAttribute("resUnits", "1"); // density is dots per inch         
  
          // Write and clean up
          imageWriter.write(data, new IIOImage(bufferedImage, null, null), jpegParams);
          ios.close();
          imageWriter.dispose();
      }
      catch (Exception e)
      {
         return false;
      }
  
      return true;
  }
  </code></pre>
  
  <p>Thanks!</p>