将多个图片合并到一个TIF文件里(非 GDAL)

时间:2021-03-21 19:58:08

不知道为什么,网上对TIF的操作的资料少得可怜,包括CodeProject上都没有找到多少,在网上大多用GDAL,但这个东西,对只想做个合并图片的功能来说,实在是牛刀杀鸡,(9个DLL要带全,相当的恐怖)而且对完成的生成和读取TIF的描述也是相当的少,一般都是用来处理GIS。

 

原下载:http://download.csdn.net/detail/patizi/200992 但那个写得比较乱,我封装成了一个类!!!

using System;
using System.Collections.Generic;
using System.Drawing;
using System.Drawing.Imaging;
using System.IO;
using System.Runtime.InteropServices;
//using System.Text;

namespace SaveMultipageTiffArticle
{
    public class CreatTiff
    {
        public bool CreateTiffFile(Image[] img, string dstFile)
        {
            return GetTiffFile(img, dstFile);
        }
        public bool AddTiffFile(string srcFile, string dstFile)
        {
            Image i1 = Image.FromFile(srcFile);
            
            Image loadImage =new Bitmap(i1);
            //FileStream fr = File.Open(dstFile, FileMode.Open, FileAccess.ReadWrite);
            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 );
        }
        private  bool GetTiffFile(Image[] img, string dstFile)
        {
            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;
                EncoderParameter SaveEncodeParam = new EncoderParameter(saveEncoder, (long)EncoderValue.MultiFrame);
                EncoderParameter CompressionEncodeParam = new EncoderParameter(compressionEncoder, (long)EncoderValue.CompressionCCITT4);
                EncoderParameters 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)
            {
                return false;
            }
            return true; 
        }

        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;
        }
    }
}