不知道为什么,网上对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 + ];
for (int i = ; 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 < ) return false;//如果只有一个文件,直接存成TIFF就好了,没有必要在这里处理
ImageCodecInfo codecInfo = ImageCodecInfo.GetImageEncoders()[];
if (codecInfo.FormatDescription != "TIFF") return false; for (int i = ; i < img.Length; i++)
{
if (img[i] == null)
break;
img[i] = (Image)ConvertToBitonal((Bitmap)img[i]); }
if (img.Length < ) 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();
EncoderParams.Param[] = CompressionEncodeParam;
EncoderParams.Param[] = SaveEncodeParam; if (File.Exists(dstFile)) File.Delete(dstFile); img[].Save(dstFile, codecInfo, EncoderParams);
for (int i = ; i < img.Length; i++)
{
SaveEncodeParam = new EncoderParameter(saveEncoder, (long)EncoderValue.FrameDimensionPage);
CompressionEncodeParam = new EncoderParameter(compressionEncoder, (long)EncoderValue.CompressionCCITT4);
EncoderParams.Param[] = CompressionEncodeParam;
EncoderParams.Param[] = SaveEncodeParam;
img[].SaveAdd(img[i], EncoderParams); } SaveEncodeParam = new EncoderParameter(saveEncoder, (long)EncoderValue.Flush);
EncoderParams.Param[] = SaveEncodeParam;
img[].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) / , (height - toheight) / , towidth, toheight),
, , 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, , );
}
}
else
{
source = original;
} // Lock source bitmap in memory
BitmapData sourceData = source.LockBits(new Rectangle(, , 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, , 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(, , destination.Width, destination.Height), ImageLockMode.WriteOnly, PixelFormat.Format1bppIndexed); // Create destination buffer
imageSize = destinationData.Stride * destinationData.Height;
byte[] destinationBuffer = new byte[imageSize]; int sourceIndex = ;
int destinationIndex = ;
int pixelTotal = ;
byte destinationValue = ;
int pixelValue = ;
int height = source.Height;
int width = source.Width;
int threshold = ; // Iterate lines
for (int y = ; y < height; y++)
{
sourceIndex = y * sourceData.Stride;
destinationIndex = y * destinationData.Stride;
destinationValue = ;
pixelValue = ; // Iterate pixels
for (int x = ; x < width; x++)
{
// Compute pixel brightness (i.e. total of Red, Green, and Blue values)
pixelTotal = sourceBuffer[sourceIndex + ] + sourceBuffer[sourceIndex + ] + sourceBuffer[sourceIndex + ];
if (pixelTotal > threshold)
{
destinationValue += (byte)pixelValue;
}
if (pixelValue == )
{
destinationBuffer[destinationIndex] = destinationValue;
destinationIndex++;
destinationValue = ;
pixelValue = ;
}
else
{
pixelValue >>= ;
}
sourceIndex += ;
}
if (pixelValue != )
{
destinationBuffer[destinationIndex] = destinationValue;
}
}
// Copy binary image data to destination bitmap
Marshal.Copy(destinationBuffer, , destinationData.Scan0, imageSize);
// Unlock destination bitmap
destination.UnlockBits(destinationData);
// Return
return destination;
} private int getPageNumber(Image img)
{
Guid objGuid = img.FrameDimensionsList[];
FrameDimension objDimension = new FrameDimension(objGuid);
//Gets the total number of frames in the .tiff file
int PageNumber = img.GetFrameCount(objDimension);
return PageNumber;
} }
}

将多个图片合并到一个TIF文件里(非 GDAL) 优化版的更多相关文章

  1. C# 将多个office文件转换及合并为一个PDF文件

    PDF文件介绍 PDF(Portable Document Format )文件源于20世纪90年代初期,如今早已成为了一种最流行的的文件格式之一.因为PDF文件有很多优点: 支持跨平台和跨设备共享 ...

  2. 多个.txt文件合并到一个.txt文件中

    如果想要将多个.txt文件合并到一个.txt文件中,可以先将所有.txt文件放到一个文件夹中,然后使用.bat文件完成任务. 例如,在一个文件夹下有1.txt, 2.txt, 3.txt三个文件,想把 ...

  3. 把当前文件夹的xlsx或xls文件合并到一个excel文件中的不同sheet中

    把当前文件夹的xlsx或xls文件合并到一个excel文件中的不同sheet中步骤如下: 把需要合并的文件放到同一个文件夹 在该文件夹中新建一个excel文件 打开新建的excel问价,把鼠标放到sh ...

  4. 常用代码之五:RequireJS, 一个Define需要且只能有一个返回值/对象,一个JS文件里只能放一个Define.

    RequireJS 介绍说一个JS文件里只能放一个Define,这个众所周知,不提. 关于Define,它需要有一个返回值/对象,且只能有一个返回值/对象,这一点却是好多帖子没有提到的,但又非常重要的 ...

  5. 查找一个Class到底在那一个jar文件里

    整理自己的一些笔记,发觉这个命令 ,看起来是用来找一个Class到底在那一个jar文件里的. 虽然没有再测一下,估计是好使的. 先在博客园里记下来,防止自己忘掉. findstr /S /M org. ...

  6. Facebook图片存储系统Haystack——存小文件,本质上是将多个小文件合并为一个大文件来降低io次数,meta data里存偏移量

    转自:http://yanyiwu.com/work/2015/01/04/Haystack.html 一篇14页的论文Facebook-Haystack, 看完之后我的印象里就四句话: 因为[传统文 ...

  7. 将STM32 iap hex文件与app hex文件合并为一个hex文件

    日前公司产品需要增加远程升级功能,boot loader程序写好后交予生产部门使用时他们反馈每个产品程序需要刷写两次(一个boot loader 一个app程序),生产进度变慢浪费时间,于是乎研究如何 ...

  8. 一条命令将windows下多个ts文件合并为一个ts文件

    首先在待合并的文件夹下创建concat.bat(名字随意啦),写入如下命令 copy /b "%~dp0"\*.ts "%~dp0"\new.ts 执行该命令后 ...

  9. python 读hdf4文件,再转写成一个tif文件

    1.安装pyhdf包 (1)通过此链接查找并下载pyhdf包:https://www.lfd.uci.edu/~gohlke/pythonlibs/#pygame(根据自己的系统及python版本选择 ...

随机推荐

  1. Gradle Build Tool

    转自知乎: nonesuccess 通俗的说:gradle是打包用的. 你觉得解决你的问题了吗?如果没解决,那是你的问题提得不够好.比如我猜你应该提:为什么要打包发布,打包发布有几种常见方法,为什么这 ...

  2. OpenCV 学习笔记 05 人脸检测和识别 AttributeError: module 'cv2' has no attribute 'face'

    1 环境设置: win10 python 3.6.8 opencv 4.0.1 2 尝试的方法 在学习人脸识别中,遇到了没有 cv2 中没有 face 属性.在网上找了几个方法,均没有成功解决掉该问题 ...

  3. 利用jsPDF有效减轻报表型应用服务器的IO负载

    1.利用jsPDF在客户端浏览器上生成pdf文档 使用这种方法可以有效减轻服务器的压力,但是对于国际化,此库任然存在的问题:该库不支持unicode,生成中文文档会乱码,官方也有描述这个问题,详情请参 ...

  4. Fraunhofer音频技术为MPEG未来高品质3D音频内容传输的标准依据

    OFweek电子工程网讯:世界着名的音频和多媒体技术研究机构Fraunhofer IIS的基于信道/对象的方案获选成为未来MPEG-H 3D音频标准的依据,此项标准旨在传输高品质的3D音频内容.MPE ...

  5. Spring Boot 2.0 返回JSP页面实战

    1. 模板引擎JSP的限制 在开始之前呢,我觉得我们有必要先去了解下 Spring Boot 2.0 官方文档中提到的如下内容: 模板引擎 除了REST Web服务之外,还可以使用Spring MVC ...

  6. Fluent动网格【5】:部件变形

    在动网格中关于部件运动除了指定刚体运动外,有时还需要指定某些边界的变形,这种情况经常会遇到,尤其是与运动部件存在相连接边界的情况下,如下图中边界1运动导致与之相连的边界2和边界3发生变形. Fluen ...

  7. 【iCore4 双核心板_ARM】例程十二:通用定时器实验——定时点亮LED

    实验原理: 通过STM32的三个GPIO口来驱动LED灯的三个通道,设定GPIO为推挽输出模式,采 用灌电流的方式与LED连接,输出高电平LED灭,输出低电平LED亮,通过通用定时器TIM3 实现50 ...

  8. 如何在Excel中提取小数点后面的数字?

    Excel中,如果某个单元格中包含一个带小数,要用公式提取该数值小数点后面的数字,例如A1单元格中包含一个数值“59178.68”,在B1单元格中输入下面的公式: =RIGHT(A1,LEN(A1)- ...

  9. Mysql系列九:使用zookeeper管理远程Mycat配置文件、Mycat监控、Mycat数据迁移(扩容)

    一.使用zookeeper管理远程Mycat配置文件 环境准备: 虚拟机192.168.152.130: zookeeper,具体参考前面文章 搭建dubbo+zookeeper+dubboadmin ...

  10. laravel数据库配置

    1.说明,查看laravel数据库配置 项目名/config/database.php     'default' => env('DB_CONNECTION', 'mysql') 2.数据开发 ...