TiffUtity
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using System.Drawing;
using System.Drawing.Imaging;
using System.IO;
using System.Collections;
using Emgu.CV;
namespace TestWinform
{
public class TiffUtity
{
/// <summary>
/// 获取图像页数
/// </summary>
/// <param name="imagePath"></param>
/// <returns></returns>
public static int GetPageNumber(string imagePath)
{
using (Image image = Bitmap.FromFile(imagePath))
{
Guid objGuid = image.FrameDimensionsList[0];
FrameDimension objDimension = new FrameDimension(objGuid);
return image.GetFrameCount(objDimension);
}
}
/// <summary>
/// 将给定的文件 拼接输出到指定的tif文件路径
/// </summary>
/// <param name="imageFiles">文件路径列表</param>
/// <param name="outFile">拼接后保存的 tif文件路径</param>
/// <param name="compressEncoder">压缩方式,建议CompressionCCITT4</param>
public static void JoinTiffImages(ArrayList imageFiles, string outFile, EncoderValue compressEncoder)
{
//如果只有一个文件,直接复制到目标
if (imageFiles.Count == 1)
{
File.Copy((string)imageFiles[0], outFile, true);
return;
}
Encoder enc = Encoder.SaveFlag;
EncoderParameters ep = new EncoderParameters(2);
ep.Param[0] = new EncoderParameter(enc, (long)EncoderValue.MultiFrame);
Bitmap pages = null;
int frame = 0;
ImageCodecInfo info = GetEncoderInfo("image/tiff");
foreach (string strImageFile in imageFiles)
{
var currentImage = Image.FromFile(strImageFile);
int compressionTagIndex = Array.IndexOf(currentImage.PropertyIdList, 0x103);
PropertyItem compressionTag = currentImage.PropertyItems[compressionTagIndex];
int test = BitConverter.ToInt16(compressionTag.Value, 0);
currentImage.Dispose();
//ep.Param[2] = new EncoderParameter(Encoder.ColorDepth, test);
//if (test > 1)
//{
// ep.Param[1] = new EncoderParameter(Encoder.Compression, (long)EncoderValue.CompressionLZW);
//}
//else
//{
ep.Param[1] = new EncoderParameter(Encoder.Compression, (long)compressEncoder);
//}
if (frame == 0)
{
pages = (Bitmap)Image.FromFile(strImageFile);
//保存第一个tif文件 到目标处
pages.Save(outFile, info, ep);
//Save the second frame if any
int frameCount1 = pages.GetFrameCount(FrameDimension.Page);
if (frameCount1 > 1)
{
for (int i = 1; i < frameCount1; i++)
{
ep.Param[0] = new EncoderParameter(enc, (long)EncoderValue.FrameDimensionPage);
pages.SelectActiveFrame(FrameDimension.Page, i);
pages.SaveAdd(pages, ep);
}
}
}
else
{
//保存好第一个tif文件后,其余 设置为添加一帧到 图像中
ep.Param[0] = new EncoderParameter(enc, (long)EncoderValue.FrameDimensionPage);
Bitmap bm = (Bitmap)Image.FromFile(strImageFile);
int frameCount = bm.GetFrameCount(FrameDimension.Page);
for (int i = 0; i < frameCount; i++)
{
bm.SelectActiveFrame(FrameDimension.Page, i);
pages.SaveAdd(bm, ep);
}
//pages.SaveAdd(bm, ep);
bm.Dispose();
}
if (frame == imageFiles.Count - 1)
{
//flush and close.
ep.Param[0] = new EncoderParameter(enc, (long)EncoderValue.Flush);
pages.SaveAdd(ep);
}
frame++;
}
pages.Dispose(); //释放资源
return;
}
/// <summary>
/// 拼接两个tif文件 保存到文件2中
/// </summary>
/// <param name="filePath">tif文件1</param>
/// <param name="targetFile">tif文件2</param>
public static void AppendToTiff(string filePath, string targetFile)
{
ArrayList list = new ArrayList(); //保存所有 tif文件路径
#region 分割tif文件1
string tempDirectory1 = string.Empty;
list.AddRange(SplitTif(filePath, out tempDirectory1));
#endregion
#region 分割tif文件2
string tempDirectory2 = string.Empty;
list.AddRange(SplitTif(targetFile, out tempDirectory2));
#endregion
//2. 拼接所有tif页
//2.1 删除原目标文件
File.Delete(targetFile);
//2.2 拼接 并按原路径生成tif文件
JoinTiffImages(list, targetFile, EncoderValue.CompressionCCITT3);
//3. 删除临时目录
DirectoryInfo di2 = new DirectoryInfo(tempDirectory2);
di2.Delete(true);
DirectoryInfo di1 = new DirectoryInfo(tempDirectory1);
di1.Delete(true);
}
/// <summary>
/// 将给定文件 分割成多个tif文件 到临时目录下
/// </summary>
/// <param name="targetFile">目标文件</param>
/// <param name="tempDirectory">临时目录路径,删除用</param>
/// <returns>分割后多个文件路径集合</returns>
public static ArrayList SplitTif(string targetFile, out string tempDirectory)
{
ArrayList list = new ArrayList();
using (Image img = Image.FromFile(targetFile))
{
Guid guid = img.FrameDimensionsList[0];
System.Drawing.Imaging.FrameDimension dimension = new System.Drawing.Imaging.FrameDimension(guid);
int nTotFrame = img.GetFrameCount(dimension); //tif总页数
int nLoop = 0; //索引
//生成临时目录 存放 单tif页
tempDirectory = Path.Combine(Path.GetDirectoryName(targetFile), Guid.NewGuid().ToString());
if (!Directory.Exists(tempDirectory))
{
Directory.CreateDirectory(tempDirectory);
}
EncoderParameters ep = new EncoderParameters(2);
ep.Param[0] = new EncoderParameter(Encoder.SaveFlag, (long)EncoderValue.MultiFrame);
ep.Param[1] = new EncoderParameter(Encoder.Compression, (long)EncoderValue.CompressionNone);//压缩方式 CompressionCCITT3主要用于传真
ImageCodecInfo info = GetEncoderInfo("image/tiff");
for (nLoop = 0; nLoop < nTotFrame; nLoop++)
{
img.SelectActiveFrame(dimension, nLoop);
//保存 单tif页
string newfilePath = Path.Combine(tempDirectory, nLoop.ToString() + ".tif");
img.Save(newfilePath, info, ep);
//将路径存入 list中
list.Add(newfilePath);
}
}
return list;
}
public static string SplitTif(string[] sourceFiles)
{
ArrayList list = new ArrayList();
string tempDirectory = string.Empty;
int i = 1;
foreach (var sourceFile in sourceFiles)
{
using (Image img = Image.FromFile(sourceFile))
{
Guid guid = img.FrameDimensionsList[0];
System.Drawing.Imaging.FrameDimension dimension = new System.Drawing.Imaging.FrameDimension(guid);
int nTotFrame = img.GetFrameCount(dimension); //tif总页数
int nLoop = 0; //索引
//生成临时目录 存放 单tif页
if (string.IsNullOrEmpty(tempDirectory))
{
tempDirectory = Path.Combine(Path.GetDirectoryName(sourceFile), Guid.NewGuid().ToString());
}
if (!Directory.Exists(tempDirectory))
{
Directory.CreateDirectory(tempDirectory);
}
EncoderParameters ep = new EncoderParameters(2);
ep.Param[0] = new EncoderParameter(Encoder.SaveFlag, (long)EncoderValue.MultiFrame);
ep.Param[1] = new EncoderParameter(Encoder.Compression, (long)EncoderValue.CompressionLZW);//压缩方式 CompressionCCITT3主要用于传真
ImageCodecInfo info = GetEncoderInfo("image/tiff");
for (nLoop = 0; nLoop < nTotFrame; nLoop++)
{
img.SelectActiveFrame(dimension, nLoop);
//保存 单tif页
string newfilePath = Path.Combine(tempDirectory, i.ToString() + ".tif");
img.Save(newfilePath, info, ep);
//将路径存入 list中
list.Add(newfilePath);
i++;
}
}
}
return tempDirectory;
}
/// <summary>
/// 获取支持的编码信息
/// </summary>
/// <param name="mimeType">协议描述</param>
/// <returns>图像编码信息</returns>
private static ImageCodecInfo GetEncoderInfo(string mimeType)
{
ImageCodecInfo[] encoders = ImageCodecInfo.GetImageEncoders();
for (int j = 0; j < encoders.Length; j++)
{
if (encoders[j].MimeType == mimeType)
return encoders[j];
}
throw new Exception(mimeType + " mime type not found in ImageCodecInfo");
}
public static void Convert8BitTo1Bit(string inputFilePath, string outputFile)
{
// 加载原始8位TIF图像
using (Bitmap srcBitmap = (Bitmap)Image.FromFile(inputFilePath))
{
// 创建一个与原始图像相同大小的1位图像
Bitmap newBitmap = new Bitmap(srcBitmap.Width, srcBitmap.Height, PixelFormat.Format1bppIndexed);
// 锁定源和目标位图的像素位
BitmapData srcData = srcBitmap.LockBits(new Rectangle(0, 0, srcBitmap.Width, srcBitmap.Height), ImageLockMode.ReadOnly, PixelFormat.Format8bppIndexed);
BitmapData dstData = newBitmap.LockBits(new Rectangle(0, 0, newBitmap.Width, newBitmap.Height), ImageLockMode.WriteOnly, PixelFormat.Format1bppIndexed);
// 获取源和目标位图的像素数据
int srcStride = srcData.Stride;
int dstStride = dstData.Stride;
IntPtr srcPtr = srcData.Scan0;
IntPtr dstPtr = dstData.Scan0;
unsafe
{
byte* src = (byte*)srcPtr.ToPointer();
byte* dst = (byte*)dstPtr.ToPointer();
// 遍历像素行
for (int y = 0; y < srcData.Height; y++)
{
// 遍历每行的像素列
for (int x = 0; x < srcData.Width; x++)
{
// 如果像素值大于127,设置为白色(1),否则设置为黑色(0)
byte value = src[y * srcStride + x];
dst[y * dstStride + x / 8] |= (byte)((value > 127 ? 1 : 0) << (7 - (x % 8)));
}
}
}
// 解锁位图
newBitmap.UnlockBits(dstData);
srcBitmap.UnlockBits(srcData);
newBitmap.Save(outputFile);
//return newBitmap;
}
}
public static void VaryQualityLevel(string sourceFile, string outFile)
{
// Get a bitmap. The using statement ensures objects
// are automatically disposed from memory after use.
using (Bitmap bmp1 = new Bitmap(sourceFile))
{
ImageCodecInfo jpgEncoder = GetEncoder(ImageFormat.Jpeg);
// Create an Encoder object based on the GUID
// for the Quality parameter category.
System.Drawing.Imaging.Encoder myEncoder =
System.Drawing.Imaging.Encoder.Quality;
// Create an EncoderParameters object.
// An EncoderParameters object has an array of EncoderParameter
// objects. In this case, there is only one
// EncoderParameter object in the array.
EncoderParameters myEncoderParameters = new EncoderParameters(1);
EncoderParameter myEncoderParameter = new EncoderParameter(myEncoder, 20L);
myEncoderParameters.Param[0] = myEncoderParameter;
//myEncoderParameters.Param[1] = new EncoderParameter(Encoder.Compression, (long)EncoderValue.CompressionLZW);
//myEncoderParameters.Param[2] = new EncoderParameter(Encoder.ColorDepth, 8);
bmp1.Save(outFile, jpgEncoder, myEncoderParameters);
//EncoderParameter myEncoderParameter = new EncoderParameter(myEncoder, 100L);
//myEncoderParameters.Param[0] = myEncoderParameter;
//bmp1.Save(outFile, jpgEncoder, myEncoderParameters);
//// Save the bitmap as a JPG file with zero quality level compression.
//EncoderParameter myEncoderParameter = new EncoderParameter(myEncoder, 0L);
//myEncoderParameters.Param[0] = myEncoderParameter;
//bmp1.Save(outFile, jpgEncoder, myEncoderParameters);
}
}
public static void VaryQualityLevel2(string[] sourceFiles, string outPath)
{
// Get a bitmap. The using statement ensures objects
// are automatically disposed from memory after use.
foreach (var sourceFile in sourceFiles)
{
using (Bitmap bmp1 = new Bitmap(sourceFile))
{
ImageCodecInfo jpgEncoder = GetEncoder(ImageFormat.Jpeg);
// Create an Encoder object based on the GUID
// for the Quality parameter category.
System.Drawing.Imaging.Encoder myEncoder =
System.Drawing.Imaging.Encoder.Quality;
// Create an EncoderParameters object.
// An EncoderParameters object has an array of EncoderParameter
// objects. In this case, there is only one
// EncoderParameter object in the array.
EncoderParameters myEncoderParameters = new EncoderParameters(1);
EncoderParameter myEncoderParameter = new EncoderParameter(myEncoder, 20L);
myEncoderParameters.Param[0] = myEncoderParameter;
string targetFile = Path.Combine(outPath, Path.GetFileName(sourceFile));
bmp1.Save(targetFile, jpgEncoder, myEncoderParameters);
}
}
}
private static ImageCodecInfo GetEncoder(ImageFormat format)
{
ImageCodecInfo[] codecs = ImageCodecInfo.GetImageEncoders();
foreach (ImageCodecInfo codec in codecs)
{
if (codec.FormatID == format.Guid)
{
return codec;
}
}
return null;
}
public static void MergeTiffs(string[] inputFilePaths, string outputFilePath)
{
using (Image firstImage = Image.FromFile(inputFilePaths[0]))
{
using (Graphics graphics = Graphics.FromImage(firstImage))
{
for (int i = 1; i < inputFilePaths.Length; i++)
{
using (Image currentImage = Image.FromFile(inputFilePaths[i]))
{
// 计算合并后的位置
int x = firstImage.Width * (i - 1);
int y = 0;
// 绘制当前图像到第一个图像上
graphics.DrawImage(currentImage, new Point(x, y));
// 更新第一个图像的宽度
//firstImage.Width += currentImage.Width;
}
}
// 保存合并后的图像
firstImage.Save(outputFilePath, ImageFormat.Tiff);
}
}
}
public static bool IsTrueTifFile(string filePath)
{
try
{
using (FileStream fileStream = new FileStream(filePath, FileMode.Open, FileAccess.Read))
{
using (BinaryReader binaryReader = new BinaryReader(fileStream))
{
// TIF文件通常以字节"49 49 2A 00"开头,这代表"II*",这是TIFF文件的标准头部
byte[] header = binaryReader.ReadBytes(4);
if (header[0] == 73 && header[1] == 73 && header[2] == 42 && header[3] == 0)
{
return true;
}
}
}
}
catch
{
// 如果文件不存在或无法读取,则认为它不是TIF文件
return false;
}
return false;
}
public static void MergeImagesAndSaveAsTiff(string[] imageFiles, string outputFile)
{
using (Image firstImage = Image.FromFile(imageFiles[0]))
{
using (Bitmap bitmap = new Bitmap(firstImage.Width, firstImage.Height, PixelFormat.Format32bppArgb))
{
using (Graphics graphics = Graphics.FromImage(bitmap))
{
foreach (string imageFile in imageFiles)
{
using (Image image = Image.FromFile(imageFile))
{
graphics.DrawImage(image, Point.Empty);
}
}
}
// Save the bitmap as TIFF
bitmap.Save(outputFile, ImageFormat.Tiff);
}
}
}
}
}