title: GhostScript Rasterizer Out of Memory Exception
body: <p>I am working with a 32-bit Console Application that operates as a background processor. The part I am working on uses GhostScript to Perform OCR on PDFs. Each page of a PDF is rendered to a PNG image in a temp folder which the OCR Reader then reads. The OCR text is saved to a database and the files in the temp folder are then deleted.</p>
  <p>The problem is with the GhostScriptRasterizer object eating all of the memory the processor has available.  When I call the GhostScriptRasterizer.GetPage(dpi, dpi, pageNumber) method I get either get an OutOfMemory Exception or a System.ArgumentException with Message &quot;Parameter is not valid&quot;.  My research on the second exception tells me it is really a symptom of the first. The method call eats all of the avialable memory.</p>
  <p>The GetPage method is creating a System.Drawing.Bitmap image which requires contiguous unfragmented memory. The problem code begins here.</p>
  <pre><code>try
  {
      img = rasterizer.GetPage(dpi, dpi, pageNumber);
  }
  catch (OutOfMemoryException ex)
  {
                      
      img = GetImage(rasterizer, dpi, pageNumber, ms);
  }
  catch (System.ArgumentException ex)
  {                       
      img = GetImage(rasterizer, dpi, pageNumber, ms);
  }
  </code></pre>
  <p>The GetImage method I wrote looks like this.</p>
  <pre><code>public Image GetImage(GhostscriptRasterizer rasterizer, int dpi, int pageNumber, MemoryStream ms)
  {
      rasterizer.Close();
      rasterizer.Dispose();
      rasterizer = new GhostscriptRasterizer();
      rasterizer.Open(ms);
      dpi = dpi - 50;
      Image image = null;
      if (dpi &gt; 0)
      {
          try
          {
              image = rasterizer.GetPage(dpi, dpi, pageNumber);
          }
          catch (OutOfMemoryException ex)
          {                   
              image = GetImage(rasterizer, dpi, pageNumber, ms);
          }
          catch (System.ArgumentException ex)
          {                   
              image = GetImage(rasterizer, dpi, pageNumber, ms);
          }
      }
  
      return image;
  }
  </code></pre>
  <p>The dpi I start with is 300 and it has worked for 95% of the documents we have run through our first test of this system.  However for certain pages 300 dpi is clearly too high as I get the Outofmemory exception. It looks like some of the pages are about 35 X 59 inches. I have no control over this. The solution for me is to keep trying at a lower and lower dpi until I have something that doesn't eat all of the memory. However, all of that memory remains in the rasterizer object so I need to dispose of it somehow. Calling rasterizer.Close() gives me the following error.</p>
  <blockquote>
  <p>Managed Debugging Assistant 'FatalExecutionEngineError' has detected a problem in 'F:\Development\bin\Debug\Processor.Run.vshost.exe'.</p>
  <p>Additional information: The runtime has encountered a fatal error. The address of the error was at 0x7331e8c6, on thread 0x3e90. The error code is 0xc0000005. This error may be a bug in the CLR or in the unsafe or non-verifiable portions of user code. Common sources of this bug include user marshaling errors for COM-interop or PInvoke, which may corrupt the stack.</p>
  </blockquote>
  <p>Removing the Close() call and calling rasterizer.Dispose() gives me:</p>
  <blockquote>
  <p>An unhandled exception of type 'System.AccessViolationException' occurred in Ghostscript.NET.dll</p>
  <p>Additional information: Attempted to read or write protected memory. This is often an indication that other memory is corrupt.</p>
  </blockquote>
  <p>I even just tried to just break if I hit an exception and return the file list and this still required me to not use a using declaration for the rasterizer because I got the same exception at the end of the using because of course it is trying to Dispose of the object. It appears the garbage collector picked up that memory later down the line but that does not in any way solve my problem. I still have no way of rasterizing the page within the same job.</p>
  <p>The only solution I can think of is somehow resizing the pdf ahead of time but I'm hoping someone knows a way of disposing that memory and re-rasterizing at a new lower dpi.</p>