LibTiff.NET是libtiff library的.net实现,代码地址为:https://github.com/BitMiracle/libtiff.net
本示例所用的版本为
<?xml version="1.0" encoding="utf-8"?>
<packages>
<package id="BitMiracle.LibTiff.NET" version="2.4.639" targetFramework="net48" />
</packages>
示例代码如下(使用的测试文件为 https://github.com/BitMiracle/libtiff.net/blob/master/Samples/Sample Data/multipage.tif ):
using BitMiracle.LibTiff.Classic;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
namespace ConsoleAppLibTiff
{
class Program
{
static void Main(string[] args)
{
// read bytes of an image
byte[] buffer = File.ReadAllBytes(@"C:\Data\multipage.tif");
List<int> pageNumbers = new List<int>() { 3, 1 };
var fileBytes = CopySpecifyPagesToNewTiffFile(buffer, pageNumbers);
FileStream destFileStream = new FileStream(@"C:\Data\multipageNew.tif", FileMode.Create, FileAccess.ReadWrite);
destFileStream.Write(fileBytes, 0, fileBytes.Length);
destFileStream.Flush();
destFileStream.Close();
}
//https://github.com/BitMiracle/libtiff.net/blob/master/Samples/ConvertToSingleStripInMemory/C%23/ConvertToSingleStripInMemory.cs
private static byte[] CopySpecifyPagesToNewTiffFile(byte[] sourceTiffImage, List<int> pageNumbers)
{
if (pageNumbers == null || !pageNumbers.Any())
throw new ArgumentNullException("pageNumbers is null or empty");
pageNumbers.Sort();
if (pageNumbers.First() < 1)
throw new ArgumentException("the minum pageNumbers can't less than 0.");
// create a memory stream out of them
MemoryStream ms = new MemoryStream(sourceTiffImage);
// open a Tiff stored in the memory stream
using (Tiff image = Tiff.ClientOpen("in-memory", "r", ms, new TiffStream()))
{
var numberOfPages = image.NumberOfDirectories();
if (pageNumbers.Last() - 1 > numberOfPages)
throw new ArgumentException("the maxium pageNumbers can't great than max pageNumber");
using (MemoryStream msOutput = new MemoryStream())
{
using (Tiff output = Tiff.ClientOpen("in-memory", "w", msOutput, new TiffStream()))
{
int index = 0;
foreach (int pageNumber in pageNumbers)
{
var pageIndex = Convert.ToInt16(pageNumber - 1);
image.SetDirectory(pageIndex);
copyTags(image, output);
// specify that it's a page within the multipage file
output.SetField(TiffTag.SUBFILETYPE, FileType.PAGE);
// specify the page number
output.SetField(TiffTag.PAGENUMBER, index++, numberOfPages);
copyStrips(image, output);
output.WriteDirectory();
}
}
var bytes = msOutput.ToArray();
return bytes;
}
}
}
private static void copyTags(Tiff input, Tiff output)
{
for (ushort t = ushort.MinValue; t < ushort.MaxValue; ++t)
{
TiffTag tag = (TiffTag)t;
FieldValue[] tagValue = input.GetField(tag);
if (tagValue != null)
output.GetTagMethods().SetField(output, tag, tagValue);
}
int height = input.GetField(TiffTag.IMAGELENGTH)[0].ToInt();
output.SetField(TiffTag.ROWSPERSTRIP, height);
}
private static void copyStrips(Tiff input, Tiff output)
{
bool encoded = false;
FieldValue[] compressionTagValue = input.GetField(TiffTag.COMPRESSION);
if (compressionTagValue != null)
encoded = (compressionTagValue[0].ToInt() != (int)Compression.NONE);
int numberOfStrips = input.NumberOfStrips();
int offset = 0;
byte[] stripsData = new byte[numberOfStrips * input.StripSize()];
for (int i = 0; i < numberOfStrips; ++i)
{
int bytesRead = readStrip(input, i, stripsData, offset, encoded);
offset += bytesRead;
}
writeStrip(output, stripsData, offset, encoded);
}
private static int readStrip(Tiff image, int stripNumber, byte[] buffer, int offset, bool encoded)
{
if (encoded)
return image.ReadEncodedStrip(stripNumber, buffer, offset, buffer.Length - offset);
else
return image.ReadRawStrip(stripNumber, buffer, offset, buffer.Length - offset);
}
private static void writeStrip(Tiff image, byte[] stripsData, int count, bool encoded)
{
if (encoded)
image.WriteEncodedStrip(0, stripsData, count);
else
image.WriteRawStrip(0, stripsData, count);
}
}
}