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


    不知道为什么,网上对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;
            }
    
            
        }
    }
  • 相关阅读:
    mysql优化——语句优化小技巧
    mysql优化——索引与索引优化
    Mysql存储引擎
    Mysql优化技术
    数据库设计——三范式
    java多线程(二)——用到的设计模式
    java多线程(一)
    ubuntu下如何查看用户登录及用户操作相关信息
    hdu 2546
    hdu 2955
  • 原文地址:https://www.cnblogs.com/lee2011/p/6065830.html
Copyright © 2020-2023  润新知