Solved

How to add pages to an existing Tiff with TiffBitmapEncoder

Posted on 2011-02-14
4
3,383 Views
Last Modified: 2012-05-11
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.
0
Comment
Question by:ja928
  • 3
4 Comments
 
LVL 83

Expert Comment

by:CodeCruiser
ID: 34895484
You are adding frames in two separate loops. Why is that?
0
 

Author Comment

by:ja928
ID: 34896091
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.
0
 

Accepted Solution

by:
ja928 earned 0 total points
ID: 34921912
After a lot of struggles with contention, I was able to get it working this way:
    Public Function AddToMaster(ByVal sFolder As String) As Boolean
        Dim bRetval As Boolean = False

        Dim decoder As BitmapDecoder = Nothing

        Try
            Using appendToOutput As Stream = File.Open(g_sMasterTif, FileMode.Open, FileAccess.Read, FileShare.Read)
                decoder = BitmapDecoder.Create(appendToOutput, BitmapCreateOptions.PreservePixelFormat, BitmapCacheOption.OnLoad)
            End Using

            Using output As Stream = File.Open(g_sMasterTif, FileMode.Open, FileAccess.Write)
                Dim tiffEncoder As TiffBitmapEncoder = New TiffBitmapEncoder()
                For Each frm As BitmapFrame In decoder.Frames
                    tiffEncoder.Frames.Add(frm)
                Next
                tiffEncoder.Compression = TiffCompressOption.Ccitt4

                Dim aImg() As String = Directory.GetFiles(sFolder)
                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 sFile As String In aImg
                    Dim bmp As BitmapFrame = Nothing

                    Using original As Stream = File.Open(sFile, FileMode.Open, FileAccess.Read)
                        bmp = BitmapFrame.Create(original, BitmapCreateOptions.PreservePixelFormat, BitmapCacheOption.OnLoad)
                        tiffEncoder.Frames.Add(bmp)
                    End Using
                Next

                tiffEncoder.Save(output)

            End Using
            bRetval = True
        Catch ex As Exception
            'Handle problems
            Dim sDebug As String = ex.Message
        End Try

        Return bRetval
    End Function

Open in new window

This uses the Framework 4 features and required no third party dependencies.
0
 

Author Closing Comment

by:ja928
ID: 34949882
This shows how to perform the task looping through files in a folder.  It can be tailored to your specific application
0

Featured Post

What is SQL Server and how does it work?

The purpose of this paper is to provide you background on SQL Server. It’s your self-study guide for learning fundamentals. It includes both the history of SQL and its technical basics. Concepts and definitions will form the solid foundation of your future DBA expertise.

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

I. Introduction In a previous article (http://www.experts-exchange.com/Web_Development/Document_Imaging/A_6537-PaperPort-Upgrade-How-to-download-and-install-updated-versions-of-PaperPort-11-and-12.html) (now deprecated), I discussed how to upgrad…
PaperPort 14.5 Patch 1 update is often not detected or downloaded automatically. This article provides direct download links to solve the problem for retail (non-bundled) versions of the Standard and Professional editions, as well as the Professiona…
In this first video of the three-part Xpdf series, we introduce and describe Xpdf, a library containing nine command line utilities that perform various functions on PDF files. We show where the library is located and how to download it, discuss its…
In an interesting question (https://www.experts-exchange.com/questions/29008360/) here at Experts Exchange, a member asked how to split a single image into multiple images. The primary usage for this is to place many photographs on a flatbed scanner…

839 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question