The problem with the mentioned libtiff library is that it extracts the image and then saves it again, which means loss of quality in the case of jpg. However, I can do the same without even using a third-party lib, just by calling the GDI + .NET Framework methods.
The original author of this thread is trying to get the jpeg binary without having to compress it again, and that is exactly what I'm trying to do.
This is a possible solution if you can live with a loss of quality and do not want to use any classes of the .NET .NET library.
public static int SplitMultiPage(string sourceFileName, string targetPath) { using (Image multipageTIFF = Image.FromFile(sourceFileName)) { int pageCount = multipageTIFF.GetFrameCount(FrameDimension.Page); if (pageCount > 1) { string sFileName = Path.GetFileNameWithoutExtension (sourceFileName); for (int i = 0; i < pageCount; i++) { multipageTIFF.SelectActiveFrame(FrameDimension.Page, i); // ein einzelner Frame könnte auch ein anderes Format haben, zB JPG, PNG, BMP, etc. // Damit die Datei die korrekte Endung bekommt, holen wir uns eine Endung aus der Beschreibung des Codecs // Interessanterweise liefert uns das RawFormat im Fall TIFF (der einzige Multiframefall) immer den Codec für TIFF, // statt den des Frames ImageCodecInfo codec = Helpers.GetEncoder(multipageTIFF.RawFormat); string sExtension = codec.FilenameExtension.Split(new char[] { ';' })[0]; sExtension = sExtension.Substring(sExtension.IndexOf('.') + 1); string newFileName = Path.Combine(targetPath, string.Format("{0}_{1}.{2}", sFileName, i + 1, sExtension)); EncoderParameters encoderParams = new EncoderParameters(2); encoderParams.Param[0] = new EncoderParameter(System.Drawing.Imaging.Encoder.SaveFlag, (long)EncoderValue.LastFrame); // für TIF 1 Bit machen wir CompressionCCITT4 Kompression, da das die besten Ergebnisse liefert switch (GetCompressionType(multipageTIFF)) { case 1: // No compression -> BMP? encoderParams.Param[1] = new EncoderParameter(System.Drawing.Imaging.Encoder.Compression, (long)EncoderValue.CompressionNone); break; case 2: // CCITT modified Huffman RLE 32773 = PackBits compression, aka Macintosh RLE encoderParams.Param[1] = new EncoderParameter(System.Drawing.Imaging.Encoder.Compression, (long)EncoderValue.CompressionRle); break; case 3: // CCITT Group 3 fax encoding encoderParams.Param[1] = new EncoderParameter(System.Drawing.Imaging.Encoder.Compression, (long)EncoderValue.CompressionCCITT3); break; case 4: // CCITT Group 4 fax encoding encoderParams.Param[1] = new EncoderParameter(System.Drawing.Imaging.Encoder.Compression, (long)EncoderValue.CompressionCCITT4); break; case 5: // LZW encoderParams.Param[1] = new EncoderParameter(System.Drawing.Imaging.Encoder.Compression, (long)EncoderValue.CompressionLZW); break; case 6: //JPEG ('old-style' JPEG, later overriden in Technote2) case 7: // Technote2 overrides old-style JPEG compression, and defines 7 = JPEG ('new-style' JPEG) { codec = Helpers.GetEncoder(ImageFormat.Jpeg); encoderParams.Param[1] = new EncoderParameter(System.Drawing.Imaging.Encoder.Quality, 90); } break; } multipageTIFF.Save(newFileName, codec, encoderParams); } } return pageCount; } }
helper method used:
public static ImageCodecInfo GetEncoder(ImageFormat format) { ImageCodecInfo[] codecs = ImageCodecInfo.GetImageDecoders(); foreach (ImageCodecInfo codec in codecs) { if (codec.FormatID == format.Guid) { return codec; } } return null; }
Reading the compression flag:
public static int GetCompressionType(Image image) { /* TIFF Tag Compression IFD Image Code 259 (hex 0x0103) Name Compression LibTiff name TIFFTAG_COMPRESSION Type SHORT Count 1 Default 1 (No compression) Description Compression scheme used on the image data. The specification defines these values to be baseline: 1 = No compression 2 = CCITT modified Huffman RLE 32773 = PackBits compression, aka Macintosh RLE Additionally, the specification defines these values as part of the TIFF extensions: 3 = CCITT Group 3 fax encoding 4 = CCITT Group 4 fax encoding 5 = LZW 6 = JPEG ('old-style' JPEG, later overriden in Technote2) Technote2 overrides old-style JPEG compression, and defines: 7 = JPEG ('new-style' JPEG) Adobe later added the deflate compression scheme: 8 = Deflate ('Adobe-style') The TIFF-F specification (RFC 2301) defines: 9 = Defined by TIFF-F and TIFF-FX standard (RFC 2301) as ITU-T Rec. T.82 coding, using ITU-T Rec. T.85 (which boils down to JBIG on black and white). 10 = Defined by TIFF-F and TIFF-FX standard (RFC 2301) as ITU-T Rec. T.82 coding, using ITU-T Rec. T.43 (which boils down to JBIG on color). */ int compressionTagIndex = Array.IndexOf(image.PropertyIdList, 0x103); PropertyItem compressionTag = image.PropertyItems[compressionTagIndex]; return BitConverter.ToInt16(compressionTag.Value, 0); }