title: How do I convert an enormous TIFF image to PNG/JPEG without out of memory error?
body: <p>i have a tiff file 18000 * 18000 in Dimension and <strong>1.20 GB</strong> in size. the tiff has 72 DPI.</p>
  
  <p>I want to convert this TIFF to PNG/JPEG  using 400 DPI.</p>
  
  <p>I am using following code to do it </p>
  
  <pre><code>public static void ConvertTiffToJpg(String str_TiffUrl,
                  String str_JpgFileDestinationUrl) throws Exception {
              try {
                  FileSeekableStream obj_FileSeekableStream = new FileSeekableStream(
                          new File(str_TiffUrl));
                  ImageDecoder obj_ImageDecoder = ImageCodec.createImageDecoder(
                          "tiff", obj_FileSeekableStream, null);
                  RenderedImage obj_RenderedImage = obj_ImageDecoder
                          .decodeAsRenderedImage();
                  JAI.create("filestore", obj_RenderedImage,
                          str_JpgFileDestinationUrl, "jpeg");
                  obj_RenderedImage = null;
                  obj_ImageDecoder = null;
                  obj_FileSeekableStream.close();
              } catch (Exception ex) {
                  throw ex;
              }
  </code></pre>
  
  <p>the above code perfectly works for smaller images then the specified image for example tiff image less than 5000 * 5000 in Dimension can be easily converted to JPEG / PNG [though i need to change the PNG encoder] , </p>
  
  <p>but when i try to run the same code for above mentioned file it throws an following exception</p>
  
  <pre><code>Error: One factory fails for the operation "encode"
      Occurs in: javax.media.jai.ThreadSafeOperationRegistry
      java.lang.reflect.InvocationTargetException
          at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
          at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
          at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
          at java.lang.reflect.Method.invoke(Method.java:597)
          at javax.media.jai.FactoryCache.invoke(FactoryCache.java:122)
          at javax.media.jai.OperationRegistry.invokeFactory(OperationRegistry.java:1674)
          at javax.media.jai.ThreadSafeOperationRegistry.invokeFactory(ThreadSafeOperationRegistry.java:473)
          at javax.media.jai.registry.RIFRegistry.create(RIFRegistry.java:332)
          at com.sun.media.jai.opimage.FileStoreRIF.create(FileStoreRIF.java:138)
          at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
          at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
          at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
          at java.lang.reflect.Method.invoke(Method.java:597)
          at javax.media.jai.FactoryCache.invoke(FactoryCache.java:122)
          at javax.media.jai.OperationRegistry.invokeFactory(OperationRegistry.java:1674)
          at javax.media.jai.ThreadSafeOperationRegistry.invokeFactory(ThreadSafeOperationRegistry.java:473)
          at javax.media.jai.registry.RIFRegistry.create(RIFRegistry.java:332)
          at javax.media.jai.RenderedOp.createInstance(RenderedOp.java:819)
          at javax.media.jai.RenderedOp.createRendering(RenderedOp.java:867)
          at javax.media.jai.RenderedOp.getRendering(RenderedOp.java:888)
          at javax.media.jai.JAI.createNS(JAI.java:1099)
          at javax.media.jai.JAI.create(JAI.java:973)
          at javax.media.jai.JAI.create(JAI.java:1621)
          at com.vs.graphics.concepts.TiffToJpeg.ConvertTiffToJpg(TiffToJpeg.java:30)
          at com.vs.graphics.svg.SvgRefresh$1.actionPerformed(SvgRefresh.java:106)
          at javax.swing.AbstractButton.fireActionPerformed(AbstractButton.java:1995)
          at javax.swing.AbstractButton$Handler.actionPerformed(AbstractButton.java:2318)
          at javax.swing.DefaultButtonModel.fireActionPerformed(DefaultButtonModel.java:387)
          at javax.swing.DefaultButtonModel.setPressed(DefaultButtonModel.java:242)
          at javax.swing.plaf.basic.BasicButtonListener.mouseReleased(BasicButtonListener.java:236)
          at java.awt.Component.processMouseEvent(Component.java:6216)
          at javax.swing.JComponent.processMouseEvent(JComponent.java:3265)
          at java.awt.Component.processEvent(Component.java:5981)
          at java.awt.Container.processEvent(Container.java:2041)
          at java.awt.Component.dispatchEventImpl(Component.java:4583)
          at java.awt.Container.dispatchEventImpl(Container.java:2099)
          at java.awt.Component.dispatchEvent(Component.java:4413)
          at java.awt.LightweightDispatcher.retargetMouseEvent(Container.java:4556)
          at java.awt.LightweightDispatcher.processMouseEvent(Container.java:4220)
          at java.awt.LightweightDispatcher.dispatchEvent(Container.java:4150)
          at java.awt.Container.dispatchEventImpl(Container.java:2085)
          at java.awt.Window.dispatchEventImpl(Window.java:2475)
          at java.awt.Component.dispatchEvent(Component.java:4413)
          at java.awt.EventQueue.dispatchEvent(EventQueue.java:599)
          at java.awt.EventDispatchThread.pumpOneEventForFilters(EventDispatchThread.java:269)
          at java.awt.EventDispatchThread.pumpEventsForFilter(EventDispatchThread.java:184)
          at java.awt.EventDispatchThread.pumpEventsForHierarchy(EventDispatchThread.java:174)
          at java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:169)
          at java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:161)
          at java.awt.EventDispatchThread.run(EventDispatchThread.java:122)
      Caused by: java.lang.OutOfMemoryError: Java heap space
          at java.awt.image.DataBufferByte.&lt;init&gt;(DataBufferByte.java:42)
          at java.awt.image.Raster.createInterleavedRaster(Raster.java:253)
          at java.awt.image.Raster.createInterleavedRaster(Raster.java:194)
          at com.sun.media.jai.codecimpl.JPEGImageEncoder.encode(JPEGImageEncoder.java:182)
          at com.sun.media.jai.opimage.EncodeRIF.create(EncodeRIF.java:70)
          at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
          at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
          at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
          at java.lang.reflect.Method.invoke(Method.java:597)
          at javax.media.jai.FactoryCache.invoke(FactoryCache.java:122)
          at javax.media.jai.OperationRegistry.invokeFactory(OperationRegistry.java:1674)
          at javax.media.jai.ThreadSafeOperationRegistry.invokeFactory(ThreadSafeOperationRegistry.java:473)
          at javax.media.jai.registry.RIFRegistry.create(RIFRegistry.java:332)
          at com.sun.media.jai.opimage.FileStoreRIF.create(FileStoreRIF.java:138)
          at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
          at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
          at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
          at java.lang.reflect.Method.invoke(Method.java:597)
          at javax.media.jai.FactoryCache.invoke(FactoryCache.java:122)
          at javax.media.jai.OperationRegistry.invokeFactory(OperationRegistry.java:1674)
          at javax.media.jai.ThreadSafeOperationRegistry.invokeFactory(ThreadSafeOperationRegistry.java:473)
          at javax.media.jai.registry.RIFRegistry.create(RIFRegistry.java:332)
          at javax.media.jai.RenderedOp.createInstance(RenderedOp.java:819)
          at javax.media.jai.RenderedOp.createRendering(RenderedOp.java:867)
          at javax.media.jai.RenderedOp.getRendering(RenderedOp.java:888)
          at javax.media.jai.JAI.createNS(JAI.java:1099)
          at javax.media.jai.JAI.create(JAI.java:973)
          at javax.media.jai.JAI.create(JAI.java:1621)
          at com.vs.graphics.concepts.TiffToJpeg.ConvertTiffToJpg(TiffToJpeg.java:30)
          at com.vs.graphics.svg.SvgRefresh$1.actionPerformed(SvgRefresh.java:106)
          at javax.swing.AbstractButton.fireActionPerformed(AbstractButton.java:1995)
          at javax.swing.AbstractButton$Handler.actionPerformed(AbstractButton.java:2318)
      Error: One factory fails for the operation "filestore"
      Occurs in: javax.media.jai.ThreadSafeOperationRegistry
  </code></pre>
  
  <p>this is because of Out of memory error.</p>
  
  <p><strong>is there any Tiled Image Writer or Fragement Image Writer available using it we will just convert a portion of an image at a time , thus we can work with normal memory available 
  i think it might be called convert using image segmentation.</strong></p>
  
  <p><strong>EDIT</strong> </p>
  
  <p><em>Directly write png file using pngJ.</em></p>
  
  <p><strong>My purpose is to transcode SVG canvas to PNG with 400 DPI</strong></p>
  
  <p>if i use <a href="http://xmlgraphics.apache.org/batik/javadoc/org/apache/batik/transcoder/image/PNGTranscoder.html" rel="nofollow">PNGTranscoder</a> for that it throws an Out of memory exception for mentioned image size.</p>
  
  <p>so i have used <a href="http://svn.apache.org/repos/asf/xmlgraphics/batik/trunk/contrib/tiledTranscoder/TiledImageTranscoder.java" rel="nofollow">TiledImageTranscoder</a>  which uses following code to transcode SVG to Image.</p>
  
  <pre><code>protected void transcode(Document document, String uri,
              TranscoderOutput output) throws TranscoderException {
  
          // Sets up root, curTxf &amp; curAoi
          super.transcode(document, uri, output);
  
          Filter f = this.root.getGraphicsNodeRable(true);
  
          RenderContext rc = new RenderContext(curTxf, null, null);
          RenderedImage img = f.createRendering(rc);
  
          // prepare the image to be painted
          int w = img.getWidth();
          int h = img.getHeight();
  
          try {
              int bands = img.getSampleModel().getNumBands();
              int[] off = new int[bands];
              for (int i = 0; i &lt; bands; i++)
                  off[i] = i;
              SampleModel sm = new PixelInterleavedSampleModel(
                      DataBuffer.TYPE_BYTE, w, (100000 + w - 1) / w, bands, w
                              * bands, off);
  
              RenderedImage rimg = new FormatRed(GraphicsUtil.wrap(img), sm);
  
              TIFFImageEncoder enc = new TIFFImageEncoder(output
              .getOutputStream(), null);
                      enc.encode(rimg);
          } catch (IOException ioe) {
              ioe.printStackTrace();
          }
      }
  </code></pre>
  
  <p><strong>so as you can see here the above code uses finally TIFFImageEncoder to write progressively to disk and generates 1.30 GB of TIFF file in my case.</strong></p>
  
  <p>so that's why i need to convert this generated file to PNG file.</p>
  
  <p>my question here is specially for @leonbloy</p>
  
  <p><strong>can we use here PNGWriter from pngJ library to directly write the png file using 400 DPI without out of memory error , by this way we can save time as well and avoid unnecessary conversion.</strong></p>
  
  <p>or </p>
  
  <p><strong>can we Override <a href="http://xmlgraphics.apache.org/batik/javadoc/org/apache/batik/ext/awt/image/codec/png/PNGImageWriter.html" rel="nofollow">PngImageWriter</a>'s writeImage method with pngJ library so we can achieve our goal ?</strong></p>
  
  <p>Thank You
  Mihir Parekh</p>