LibTiff.NET: 从tiff文件中复制指定的页面到一个新的tiff文件

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);
        }
    }
}

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


下一篇:Photoshop为情侣图片增加柔和的暖色效果