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:
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
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.
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
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"))
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.
You are adding frames in two separate loops. Why is that?
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.
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
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
ASKER
This shows how to perform the task looping through files in a folder. It can be tailored to your specific application