Link to home
Start Free TrialLog in
Avatar of ja928
ja928

asked on

How to add pages to an existing Tiff with TiffBitmapEncoder

I've been working with the Bob Powell example for Adding pages to a multipage TIFF and ran into some speed issues performing the add within a loop. Basically, I have a loop that is:

While ChecksArePresent
  Scan Images
    add to tiff
    Store data in DB
Loop

I experience increasingly slow processing as I add pages to the tiff, and I understand that that is because I am re-encoding the pages again and again with each pass.  I had "Parameter is Not Valid" when I collected the images into an ArrayList or List(Of Image).

When I work with the TiffBitmapEncoder I am getting "Handle is Invalid" errors with the streams for outputting the file. This attempt basically fills up a temporary directory with the scanned images, then loops through these like so:
    Private Function AddPagesToMaster() As Boolean
        Dim bRetVal As Boolean = False
        If Directory.GetFiles(sTempFilePath).Length > 0 Then
            Try
                If File.Exists(TEMP_FILE_NAME) Then File.Delete(TEMP_FILE_NAME)
                File.Move(g_sMasterTif, TEMP_FILE_NAME)
                Dim encoder As New System.Windows.Media.Imaging.TiffBitmapEncoder
                encoder.Compression = Windows.Media.Imaging.TiffCompressOption.Ccitt4
                Dim fsIn As New FileStream(TEMP_FILE_NAME, FileMode.Open, FileAccess.Read, FileShare.Read)
                Dim fsOut As New FileStream(g_sMasterTif, FileMode.Create, FileAccess.ReadWrite, FileShare.None)
                Dim decoder As New System.Windows.Media.Imaging.TiffBitmapDecoder(fsIn, Windows.Media.Imaging.BitmapCreateOptions.PreservePixelFormat, Windows.Media.Imaging.BitmapCacheOption.Default)

                For Each frm As System.Windows.Media.Imaging.BitmapSource In decoder.Frames
                    encoder.Frames.Add(frm)
                Next
                Dim aImg() As String = Directory.GetFiles(sTempFilePath)
                Array.Sort(aImg) 'I am naming the files so that they come back sequentially and I can figure the Page number in another proc.
                For Each sPath As String In aImg
                    Dim strBmp As Stream = File.OpenRead(sPath)
                    encoder.Frames.Add(Windows.Media.Imaging.BitmapFrame.Create(strBmp))
                    strBmp.Close()
                Next

                encoder.Save(fsOut) 'Gives me a "Handle is invalid error
                fsIn.Flush()
                fsIn.Close()
                fsOut.Flush()
                fsOut.Close()

                bRetVal = True
            Catch ex As Exception
                MessageBox.Show(ex.Message, "Exception in AddPagesToMaster", MessageBoxButtons.OK, MessageBoxIcon.Error)
            Finally

            End Try
        End If

        Return bRetVal
    End Function

Open in new window


I have tried wrapping up the fsIn and fsOut variables in "Using" statements with the same effect.  I tried deleting the output file and changed the error line to
 encoder.Save(File.Create("myNewTiff.tif"))

Open in new window

That yielded an error that I had bad metadata.

I'm using VB.net 2010 on Windows 7, 64bit.  I've found a few articles that indicate changes under the hood for CCITT4 on Windows 7, but I have also changed to LZW and None for the compression to no avail.  I've seen Libtiff.Net but want to keep my number of DLLs down if I can simply code this directly.  I checked MSDN, but can't quite work out the errors described above.

Any help would be greatly appreciated.
Avatar of Nasir Razzaq
Nasir Razzaq
Flag of United Kingdom of Great Britain and Northern Ireland image

You are adding frames in two separate loops. Why is that?
Avatar of ja928
ja928

ASKER

Thanks for your comment.  The project is a check scanning application which captures the front and back image of a check, adds the images to an existing TIFF, and updates the database so we can retrieve the frames later.  The reason for the master TIFF is that we scan 500,000 checks annually and wanted to decrease the number of files in any given folder for maintenance and backup.  The psuedo-coded loop is an existing state that works in VB6 with Advanced Imagery Library and FreeImage3.dll. We are updating the application to .Net and I wanted to slim down the number of references.  The Framework 4 TiffBitmapEncoder object looked ideal for this, but I can't seem to get it to work.  I'd prefer to go with this if I can reduce my dependencies and get a fast enough processing time.

The Bob Powell example worked for me, but got progressively slower with each scan since the sub routines loop through each frame of the (growing) Master Tiff with each pass.  Correct me if I'm wrong, but I was under the impression that you can't just open a TIFF and append the frames at the end.  The Bob Powell example is viable if I can queue up the images in some kind of array, but when I try that I get "Parameter is not Valid" errors trying to pull the images from my in-memory array.  I've seen other sources that store them as backgrounds for Panels, but again it looks like the TiffBitmapEncoder should do the trick.
ASKER CERTIFIED SOLUTION
Avatar of ja928
ja928

Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial
Avatar of ja928

ASKER

This shows how to perform the task looping through files in a folder.  It can be tailored to your specific application