But I left one point not very clear. This came to me after I saw a question from Jennifer Slusher in the universal thread forums (thread id #1153672), asking how to create multiPage TIFFs in Compression 4 (ccitt4). in that article, I showed how to create common Multiframe TIFFs and also how to create a single frame TIFF using Compression, but forgot to show or comment about creating Multiframe TIFFs with Compression.
Multiframe TIFFs with Compression
Gdi+ by default uses the 'lzw lossless' Compression whenever asked to save as TIFF. According to Wayne Fulton, from www.scantips.com, "lossless means there is no quality loss due to Compression. lossless guarantees that you can always read back exactly what you thought you saved, bit-for-bit identical, without data corruption". so, unless we specify, gdi+ will always use lzw Compression on TIFFs.
To create a Multiframe TIFF with Compression different from lzw, we need to send some additional Encoder Parameters to gdi+, even if the original picture is already a TIFF with another Compression. The methods "save" and "saveadd" permit us to send more than one Encoder Parameter at a time. Then, all we need to do is to create another Encoder object based on the guid for the Compression Parameter category, and set its EncoderValue to the desired Compression, eg Compressionccitt4.
The sample below will ask for any three images. To ensure that it will be able to save using Compression ccitt4, it will first convert all the selected images to monochrome. Then it will create a Multiframe TIFF image file containing all selected images in the Compression ccitt4.
** The following example loads three Bitmap objects ** converts all Bitmaps to monochrome to be compatible with rle, ccitt3/4 Compression ** the code saves all three images in a single, multiple-frame TIFF ** file, using Compression format CCITT4 DO LOCFILE("System.app") WITH _SCREEN.SYSTEM.Drawing LOCAL loBmp AS xfcBitmap LOCAL loMultif AS xfcBitmap LOCAL loPage2 AS xfcBitmap LOCAL loPage3 AS xfcBitmap LOCAL myEncoder AS xfcEncoder LOCAL myCompEncoder AS xfcEncoder LOCAL myEncoderParameter AS xfcEncoderParameter LOCAL myCompEncoderParameter AS xfcEncoderParameter LOCAL myEncoderParameters AS xfcEncoderParameters *!* create three Bitmap objects. *!* 1st we load the original Bitmap, *!* and then get its monochrome version m.loBmp = .BITMAP.New(GETPICT()) m.loMultif = m.loBmp.getMonochrome() m.loBmp = .BITMAP.New(GETPICT()) m.loPage2 = m.loBmp.getMonochrome() m.loBmp = .BITMAP.New(GETPICT()) m.loPage3 = m.loBmp.getMonochrome() *!* release the original Bitmap because we'll not use it any more m.loBmp = NULL *!* create Encoder object based on the guid for the saveflag Parameter category. m.myEncoder = .Imaging.Encoder.saveflag *!* create Encoder object based on the guid for the Compression Parameter category. m.mycompEncoder = .Imaging.Encoder.Compression && create an EncoderParameters object. && EncoderParameters object has an array of EncoderParameter objects && in this case, there'll be 2 EncoderParameter objects in the array. m.myEncoderParameters = .Imaging.EncoderParameters.New(2) *!* save the first Page (frame). m.myEncoderParameter = .Imaging.EncoderParameter.New(m.myEncoder, ; .Imaging.EncoderValue.Multiframe) m.mycompEncoderParameter = .Imaging.EncoderParameter.New(m.mycompEncoder, ; .Imaging.EncoderValue.Compressionccitt4) m.myEncoderParameters.PARAM[1] = m.myEncoderParameter m.myEncoderParameters.PARAM[2] = m.mycompEncoderParameter m.loMultif.SAVE("c:\NewMultiframeCompress.tif", ; .Imaging.imageformat.TIFF, m.myEncoderParameters) *!* save the second Page (frame). *!* this time we will only change the 1st Parameter to "framedimensionPage" *!* the 2nd Parameter that sets the Compression will remain the same m.myEncoderParameter = .Imaging.EncoderParameter.New(m.myEncoder, ; .Imaging.EncoderValue.framedimensionPage) m.myEncoderParameters.PARAM[1] = m.myEncoderParameter m.loMultif.saveadd(m.loPage2, m.myEncoderParameters) *!* save the third Page (frame). *!* this time we don't need to make any change to the Encoder paramenters *!* we'll keep using the same Parameters used when we added the 2nd frame m.loMultif.saveadd(m.loPage3, m.myEncoderParameters) *!* close the multiple-frame file. *!* this time we call the "flush" Parameter to close the file. *!* we don't need the 2nd Parameter any more, so change it to null m.myEncoderParameter = .Imaging.EncoderParameter.New(m.myEncoder, ; .Imaging.EncoderValue.FLUSH) m.myEncoderParameters.PARAM[1] = m.myEncoderParameter m.myEncoderParameters.PARAM[2] = NULL m.loMultif.saveadd(m.myEncoderParameters) ENDWITH RETURN
Notice that the object myEncoderParameters contains a property "params" that is an array of Parameters.
Other related links:
TIFF, tag image file format
A few scanning tips
I have done it as you instructured but the problem is when i tried to change the compression with EncoderValueCompressionRle (packbits), the gdi+ returns invalid parameter error?
ReplyDeletewhy?