不知道为什么,网上对TIF的操作的资料少得可怜,包括CodeProject上都没有找到多少,在网上大多用GDAL,但这个东西,对只想做个合并图片的功能来说,实在是牛刀杀鸡,(9个DLL要带全,相当的恐怖)而且对完成的生成和读取TIF的描述也是相当的少,一般都是用来处理GIS。
版本为优化版,原版经常报内存不足
using System; using System.Collections.Generic; using System.Linq; using System.Drawing; using System.Drawing.Imaging; using System.IO; using System.Runtime.InteropServices; namespace Common { public class CreatTiff { #region 将图片列表合并到一个文件 /// <summary> /// 多张图片合并 /// </summary> /// <param name="img">图片列表</param> /// <param name="dstFile">合并图片名</param> /// <returns></returns> public bool CreateTiffFile(Image[] img, string dstFile) { return GetTiffFile(img, dstFile); } #endregion #region 将单个TIF添加到多页TIF中 /// <summary> /// 将单个TIF添加到多页TIF中 /// </summary> /// <param name="srcFile">单页TIFF地址</param> /// <param name="dstFile">需要添加到的多页TIFF地址</param> /// <returns></returns> public bool AddTiffFile(string srcFile, string dstFile, string RootPath, int tifNumber) { try { string thumbnailImagePath = RootPath + "thumbnailImagePath.tif"; Image i1 = null; //if (tifNumber > 9)//为解决内存不足想的拙劣解决方法 //{ // GetThumbnail(srcFile, thumbnailImagePath, 1150, 1850); // i1 = Image.FromFile(thumbnailImagePath); //} //else //{ // i1 = Image.FromFile(srcFile); //} i1 = Image.FromFile(srcFile); Image loadImage = new Bitmap(i1); Image origionalFile = Image.FromFile(dstFile); int PageNumber = getPageNumber(origionalFile); Image[] img = new Image[PageNumber + 1]; for (int i = 0; i < PageNumber; i++) { origionalFile.SelectActiveFrame(FrameDimension.Page, i); img[i] = new Bitmap(origionalFile); } img[PageNumber] = loadImage; origionalFile.Dispose(); i1.Dispose(); return GetTiffFile(img, dstFile); } catch (Exception ex) { Log.Writer(ex, "合并TIF文件AddTiffFile()异常"); throw new Exception("TIF文件:"+ srcFile + " 处理错误!请检查文件是否损坏!"); } } #endregion #region 合并 /// <summary> /// 合并 /// </summary> /// <param name="img">图片列表</param> /// <param name="dstFile">合并目的文件</param> /// <returns></returns> private bool GetTiffFile(Image[] img, string dstFile) { EncoderParameter SaveEncodeParam = null; EncoderParameter CompressionEncodeParam = null; EncoderParameters EncoderParams = null; try { if (img == null) return false; if (img.Length < 2) return false;//如果只有一个文件,直接存成TIFF就好了,没有必要在这里处理 ImageCodecInfo codecInfo = ImageCodecInfo.GetImageEncoders()[3]; if (codecInfo.FormatDescription != "TIFF") return false; for (int i = 0; i < img.Length; i++) { if (img[i] == null) break; img[i] = (Image)ConvertToBitonal((Bitmap)img[i]); } if (img.Length < 2) return false; Encoder saveEncoder = Encoder.SaveFlag; Encoder compressionEncoder = Encoder.Compression; SaveEncodeParam = new EncoderParameter(saveEncoder, (long)EncoderValue.MultiFrame); CompressionEncodeParam = new EncoderParameter(compressionEncoder, (long)EncoderValue.CompressionCCITT4); EncoderParams = new EncoderParameters(2); EncoderParams.Param[0] = CompressionEncodeParam; EncoderParams.Param[1] = SaveEncodeParam; if (File.Exists(dstFile)) File.Delete(dstFile); img[0].Save(dstFile, codecInfo, EncoderParams); for (int i = 1; i < img.Length; i++) { SaveEncodeParam = new EncoderParameter(saveEncoder, (long)EncoderValue.FrameDimensionPage); CompressionEncodeParam = new EncoderParameter(compressionEncoder, (long)EncoderValue.CompressionCCITT4); EncoderParams.Param[0] = CompressionEncodeParam; EncoderParams.Param[1] = SaveEncodeParam; img[0].SaveAdd(img[i], EncoderParams); } SaveEncodeParam = new EncoderParameter(saveEncoder, (long)EncoderValue.Flush); EncoderParams.Param[0] = SaveEncodeParam; img[0].SaveAdd(EncoderParams); } catch (Exception ex) { Log.Writer(ex, "合并TIF文件异常"); return false; } finally { SaveEncodeParam.Dispose(); CompressionEncodeParam.Dispose(); EncoderParams.Dispose(); foreach (var item in img) { item.Dispose(); } GC.Collect(); } return true; } #endregion /// <summary> /// 生成缩略图 /// </summary> /// <param name="serverImagePath">图片地址</param> /// <param name="thumbnailImagePath">缩略图地址</param> /// <param name="width">图片宽度</param> /// <param name="height">图片高度</param> /// <param name="p"></param> public static void GetThumbnail(string serverImagePath, string thumbnailImagePath, int width, int height) { System.Drawing.Image serverImage = System.Drawing.Image.FromFile(serverImagePath); //画板大小 int towidth = width; int toheight = height; //缩略图矩形框的像素点 //int x = 0; //int y = 0; int ow = serverImage.Width; int oh = serverImage.Height; if (ow > oh) { toheight = serverImage.Height * width / serverImage.Width; } else { towidth = serverImage.Width * height / serverImage.Height; } //新建一个bmp图片 System.Drawing.Image bm = new System.Drawing.Bitmap(width, height); //新建一个画板 System.Drawing.Graphics g = System.Drawing.Graphics.FromImage(bm); //设置高质量插值法 g.InterpolationMode = System.Drawing.Drawing2D.InterpolationMode.High; //设置高质量,低速度呈现平滑程度 g.SmoothingMode = System.Drawing.Drawing2D.SmoothingMode.HighQuality; //清空画布并以透明背景色填充 g.Clear(System.Drawing.Color.White); //在指定位置并且按指定大小绘制原图片的指定部分 g.DrawImage(serverImage, new System.Drawing.Rectangle((width - towidth) / 2, (height - toheight) / 2, towidth, toheight), 0, 0, ow, oh, System.Drawing.GraphicsUnit.Pixel); try { //以jpg格式保存缩略图 bm.Save(thumbnailImagePath, System.Drawing.Imaging.ImageFormat.Tiff); } catch (System.Exception e) { throw e; } finally { serverImage.Dispose(); bm.Dispose(); g.Dispose(); GC.Collect(); } } private Bitmap ConvertToBitonal(Bitmap original) { Bitmap source = null; // If original bitmap is not already in 32 BPP, ARGB format, then convert if (original.PixelFormat != PixelFormat.Format32bppArgb) { source = new Bitmap(original.Width, original.Height, PixelFormat.Format32bppArgb); source.SetResolution(original.HorizontalResolution, original.VerticalResolution); using (Graphics g = Graphics.FromImage(source)) { g.DrawImageUnscaled(original, 0, 0); } } else { source = original; } // Lock source bitmap in memory BitmapData sourceData = source.LockBits(new Rectangle(0, 0, source.Width, source.Height), ImageLockMode.ReadOnly, PixelFormat.Format32bppArgb); // Copy image data to binary array int imageSize = sourceData.Stride * sourceData.Height; byte[] sourceBuffer = new byte[imageSize]; Marshal.Copy(sourceData.Scan0, sourceBuffer, 0, imageSize); // Unlock source bitmap source.UnlockBits(sourceData); // Create destination bitmap Bitmap destination = new Bitmap(source.Width, source.Height, PixelFormat.Format1bppIndexed); // Lock destination bitmap in memory BitmapData destinationData = destination.LockBits(new Rectangle(0, 0, destination.Width, destination.Height), ImageLockMode.WriteOnly, PixelFormat.Format1bppIndexed); // Create destination buffer imageSize = destinationData.Stride * destinationData.Height; byte[] destinationBuffer = new byte[imageSize]; int sourceIndex = 0; int destinationIndex = 0; int pixelTotal = 0; byte destinationValue = 0; int pixelValue = 128; int height = source.Height; int width = source.Width; int threshold = 500; // Iterate lines for (int y = 0; y < height; y++) { sourceIndex = y * sourceData.Stride; destinationIndex = y * destinationData.Stride; destinationValue = 0; pixelValue = 128; // Iterate pixels for (int x = 0; x < width; x++) { // Compute pixel brightness (i.e. total of Red, Green, and Blue values) pixelTotal = sourceBuffer[sourceIndex + 1] + sourceBuffer[sourceIndex + 2] + sourceBuffer[sourceIndex + 3]; if (pixelTotal > threshold) { destinationValue += (byte)pixelValue; } if (pixelValue == 1) { destinationBuffer[destinationIndex] = destinationValue; destinationIndex++; destinationValue = 0; pixelValue = 128; } else { pixelValue >>= 1; } sourceIndex += 4; } if (pixelValue != 128) { destinationBuffer[destinationIndex] = destinationValue; } } // Copy binary image data to destination bitmap Marshal.Copy(destinationBuffer, 0, destinationData.Scan0, imageSize); // Unlock destination bitmap destination.UnlockBits(destinationData); // Return return destination; } private int getPageNumber(Image img) { Guid objGuid = img.FrameDimensionsList[0]; FrameDimension objDimension = new FrameDimension(objGuid); //Gets the total number of frames in the .tiff file int PageNumber = img.GetFrameCount(objDimension); return PageNumber; } } }