C# 将多个图片合并成TIFF文件的两种方法

dotNET跨平台 今天

以下文章来源于WPF UI ,作者Gxy

WPF UIWPF UI 设计,WPF教程,MVVM,C#程序设计~

最近需要用到TIF格式的文件,研究了一段时间,终于有点结果了,

发现两种方式,第一种是使用BitMiracle.LibTiff.NET,直接在Nuget上安装即可

,第二种是使用RasterEdge.DocImageSDK,要从官网下载dll包

第一种免费,但是生成的tiff文件大小比原始图片大的多

第二种收费,但是有试用期一个月,效果很好,生成的tiff文件比原图小的多而且不失真。过期之后,只需要到官网下载最新dll,重新引用即可再来一个月试用。。。

先说第二种RasterEdge.DocImageSDK的使用方法:

官网地址:http://www.rasteredge.com/how-to/csharp-imaging/tiff-convert-bmp/
//过期后打开上面 这个网址,重新下载 dll包,重新引用即可 bin x64 4.0

新建一个cmd项目,测试代码如下:

    class Program    {        private static byte[] CompressionImage(Stream fileStream, long quality)        {            using (System.Drawing.Image img = System.Drawing.Image.FromStream(fileStream))            {                using (Bitmap bitmap = new Bitmap(img))                {                    ImageCodecInfo CodecInfo = GetEncoder(img.RawFormat);                    System.Drawing.Imaging.Encoder myEncoder = System.Drawing.Imaging.Encoder.Quality;                    EncoderParameters myEncoderParameters = new EncoderParameters(1);                    EncoderParameter myEncoderParameter = new EncoderParameter(myEncoder, quality);                    myEncoderParameters.Param[0] = myEncoderParameter;                    using (MemoryStream ms = new MemoryStream())                    {                        bitmap.Save(ms, CodecInfo, myEncoderParameters);                        myEncoderParameters.Dispose();                        myEncoderParameter.Dispose();                        return ms.ToArray();                    }                }            }        }        private static ImageCodecInfo GetEncoder(ImageFormat format)        {            ImageCodecInfo[] codecs = ImageCodecInfo.GetImageDecoders();            foreach (ImageCodecInfo codec in codecs)            {                if (codec.FormatID == format.Guid)                { return codec; }            }            return null;        }        static void Main(string[] args)        {            string[] imagePaths = System.IO.Directory.GetFiles(@"D:\images\","*.jpg");                        Bitmap[] bmps = new Bitmap[imagePaths.Count()];            for (int i = 0; i < imagePaths.Length; i++)            {                var stream = new FileStream(imagePaths[i], FileMode.Open);                var by = CompressionImage(stream, 100);                stream.Close();                Bitmap tmpBmp = new Bitmap(new MemoryStream(by));                if (tmpBmp != null)                    bmps[i] = tmpBmp;            }            ImageOutputOption option = new ImageOutputOption() { Color = ColorType.Color, Compression = ImageCompress.CCITT };            TIFFDocument tifDoc = new TIFFDocument(bmps, option);            if (tifDoc == null)                throw new Exception("Fail to construct TIFF Document");            tifDoc.Save(@"D:\images\test.tif");        }        }

    下面说说第二种免费的方式:

    新建一个TiffHelper帮助类:

      using BitMiracle.LibTiff.Classic;using System;using System.Drawing;using System.Drawing.Imaging;using System.IO;namespace JpgToTiff{    public class UserErrorHandler : TiffErrorHandler    {        public override void WarningHandler(Tiff tif, string method, string format, params object[] args)        {            //base.WarningHandler(tif, method, format, args);        }        public override void WarningHandlerExt(Tiff tif, object clientData, string method, string format, params object[] args)        {            //base.WarningHandlerExt(tif, clientData, method, format, args);        }    }    public class TiffHelper    {        public static UserErrorHandler m_errorHandler = new UserErrorHandler();        static TiffHelper()        {            Tiff.SetErrorHandler(m_errorHandler);        }        /// <summary>        /// 合并jpg        /// </summary>        /// <param name="bmps">bitmap数组</param>        /// <param name="tiffSavePath">保存路径</param>        /// <param name="quality">图片质量,1-100</param>        /// <returns></returns>        public static bool Jpegs2Tiff(Bitmap[] bmps, string tiffSavePath, int quality = 15)        {            try            {                MemoryStream ms = new MemoryStream();                using (Tiff tif = Tiff.ClientOpen(@"in-memory", "w", ms, new TiffStream()))                {                    foreach (var bmp in bmps)//                    {                        byte[] raster = GetImageRasterBytes(bmp, PixelFormat.Format24bppRgb);                        tif.SetField(TiffTag.IMAGEWIDTH, bmp.Width);                        tif.SetField(TiffTag.IMAGELENGTH, bmp.Height);                        tif.SetField(TiffTag.COMPRESSION, Compression.JPEG);                        tif.SetField(TiffTag.PHOTOMETRIC, Photometric.RGB);                        tif.SetField(TiffTag.JPEGQUALITY, quality);                        tif.SetField(TiffTag.ROWSPERSTRIP, bmp.Height);                        tif.SetField(TiffTag.XRESOLUTION, 90);                        tif.SetField(TiffTag.YRESOLUTION, 90);                        tif.SetField(TiffTag.BITSPERSAMPLE, 8);                        tif.SetField(TiffTag.SAMPLESPERPIXEL, 3);                        tif.SetField(TiffTag.PLANARCONFIG, PlanarConfig.CONTIG);                        int stride = raster.Length / bmp.Height;                        ConvertSamples(raster, bmp.Width, bmp.Height);                        for (int i = 0, offset = 0; i < bmp.Height; i++)                        {                            tif.WriteScanline(raster, offset, i, 0);                            offset += stride;                        }                        tif.WriteDirectory();                    }                    System.IO.FileStream fs = new FileStream(tiffSavePath, FileMode.Create);                                        ms.Seek(0, SeekOrigin.Begin);                    fs.Write(ms.ToArray(), 0, (int)ms.Length);                    fs.Close();                    return true;                }            }            catch (Exception ex)            {                return false;            }        }        private static byte[] GetImageRasterBytes(Bitmap bmp, PixelFormat format)        {            Rectangle rect = new Rectangle(0, 0, bmp.Width, bmp.Height);            byte[] bits = null;            try            {                BitmapData bmpdata = bmp.LockBits(rect, ImageLockMode.ReadWrite, format);                bits = new byte[bmpdata.Stride * bmpdata.Height];                System.Runtime.InteropServices.Marshal.Copy(bmpdata.Scan0, bits, 0, bits.Length);                bmp.UnlockBits(bmpdata);            }            catch            {                return null;            }            return bits;        }        private static void ConvertSamples(byte[] data, int width, int height)        {            int stride = data.Length / height;            const int samplesPerPixel = 3;            for (int y = 0; y < height; y++)            {                int offset = stride * y;                int strideEnd = offset + width * samplesPerPixel;                for (int i = offset; i < strideEnd; i += samplesPerPixel)                {                    byte temp = data[i + 2];                    data[i + 2] = data[i];                    data[i] = temp;                }            }        }    }}

      下面是测试代码:

        class Program    {        private static byte[] CompressionImage(Stream fileStream, long quality)        {            using (System.Drawing.Image img = System.Drawing.Image.FromStream(fileStream))            {                using (Bitmap bitmap = new Bitmap(img))                {                    ImageCodecInfo CodecInfo = GetEncoder(img.RawFormat);                    System.Drawing.Imaging.Encoder myEncoder = System.Drawing.Imaging.Encoder.Quality;                    EncoderParameters myEncoderParameters = new EncoderParameters(1);                    EncoderParameter myEncoderParameter = new EncoderParameter(myEncoder, quality);                    myEncoderParameters.Param[0] = myEncoderParameter;                    using (MemoryStream ms = new MemoryStream())                    {                        bitmap.Save(ms, CodecInfo, myEncoderParameters);                        myEncoderParameters.Dispose();                        myEncoderParameter.Dispose();                        return ms.ToArray();                    }                }            }        }        private static ImageCodecInfo GetEncoder(ImageFormat format)        {            ImageCodecInfo[] codecs = ImageCodecInfo.GetImageDecoders();            foreach (ImageCodecInfo codec in codecs)            {                if (codec.FormatID == format.Guid)                { return codec; }            }            return null;        }        static void Main(string[] args)        {            string[] imagePaths = System.IO.Directory.GetFiles(@"D:\images\","*.jpg");                        Bitmap[] bmps = new Bitmap[imagePaths.Count()];            for (int i = 0; i < imagePaths.Length; i++)            {                var stream = new FileStream(imagePaths[i], FileMode.Open);                var by = CompressionImage(stream, 100);                stream.Close();                Bitmap tmpBmp = new Bitmap(new MemoryStream(by));                if (tmpBmp != null)                    bmps[i] = tmpBmp;            }            TiffHelper.Jpegs2Tiff(bmps, @"D:\images\test.tif", 100);        }       }

        可以看到,两个方式生成的tif文件大小简直天壤之别。。。

        7个原图大小4.8M,第一种1.36M,

        第二种直接23.5M…

        也可能是我没有弄好压缩方式。。。。

        那我就不晓得了。

        如果喜欢,点个赞呗

        (0)

        相关推荐

        • 使用Graphics合成带二维码和头像的分享图(小程序分享、App分享)

          适用于微信小程序分享图.app分享图 //分享的海报背景图片 使用本地图片文件 string path = Server.MapPath("/Content/images/backimg.j ...

        • pdf怎么转换成jpg图片?分享两种方法给你

          pdf文件怎么转换成jpg图片呢?小编以前用的是PDF转换工具,但是今天想要给大家分享我新发现的迅捷图片转换器.不过,想到很多朋友没有看过以前小编的分享,所以今天我会将两种方法都告诉大家,大家可以认真 ...

        • 请问多个pdf文件怎么合并成同一个文件呢?

          在职场办公中pdf格式的文件所应用的场景真的是海了去了,主要是因为这种格式有几个优点就是,内容排版以及文件内容不会在传输过程中被更改,而且体积小,非常便于大家工作之间的内容交接,内容传输.因此这种格式 ...

        • 怎样把图片转换成pdf文件?这有个简单方法

          平日里,大家接触的文件格式不算少了吧,就好比有pdf.jpg.word.excel.ppt等,其中,pdf文件与图片比较相同,就是用一般的office工具是很难编辑它们内容的.此外,pdf文件还有传阅 ...

        • 多个pdf文件怎么合并成同一个文件呢?

          在职场办公中pdf格式的文件所应用的场景真的是海了去了,主要是因为这种格式有几个优点就是,内容排版以及文件内容不会在传输过程中被更改,而且体积小,非常便于大家工作之间的内容交接,内容传输.因此这种格式 ...

        • 如何将图片转换成pdf文件?简单方法这里有,一学就会

          大家好,我是一名大二学生,专业课不是很忙,就报名加入了学生会.最近负责整理一个活动的照片,需要进行调色.p图等操作.我花费了半天时间整理好,批量压缩再转发给对应的负责人后,她叫我同时再传送一份pdf文 ...

        • 用这两种方法识别AAAABB型手机号,我成了同事眼中的Excel大神~

          发送[礼包] 本文作者:农夫.小爽 本文编辑:竺兰 小伙伴们,大家好,我是农夫,专治疑难「数」的农夫:她是小爽,注定要站在 Excel 顶端的大佬~ 今天,同事小李在处理一份包含两万条手机号的数据. ...

        • Excel二维表转换成一维表(2种方法)

          今天大年初四,春节假期还剩三天了,每逢佳节胖三斤,亲们可要注意控制饮食了,要不然春节后无脸见人哟.闲话少说,今日分享如下. 在做数据处理的时候,有的时候为了处理方便我们需要将二维的数据表处理成一维的数 ...

        • 难倒95%会计考生的长投和合并报表,教你一种方法,很简单

          中级会计职称三科中,中级会计实务可以说是既费时间又费脑子的一科了. 而中级会计实务中最难的莫过于长投.合并报表--每年都有很多考生哭诉 ↓ ↓ ↓ 那么如何理解中级会计实务合并报表.长投等内容呢? 1 ...

        • PDF如何转图片?这里有两种方法,自行选择

          相较于PDF转word的操作,pdf转图片的操作知道的朋友会没有那么多.但其实这种pdf转图片的操作在生活中还蛮常用到的,像网上很多学习资料是pdf格式的文件,而为了便于更好的使用文件中的内容,也是有 ...