☰
ImageSharp TIFF 编解码器深度解析:压缩格式、光度解释与标签支持全览
2026/10/15 16:59:15 网站建设 项目流程
  • 图像处理
  • 图形学

【免费下载链接】ImageSharp

A modern, cross-platform, 2D Graphics library for .NET

项目地址:https://gitcode.com/gh_mirrors/im/ImageSharp
点击查看免费下载

TIFF 是一个极具包容性的图像容器格式:同一个.tif文件内部可能使用十几种不同的压缩算法、七八种不同的色彩解释方式,以及数百个不同的 IFD 标签。ImageSharp 仓库中的 TIFF codec 实现文档 以能力矩阵的形式,逐项列出了编码器(Encoder)与解码器(Decoder)对各种压缩格式、光度解释和标签的支持现状。本文将以此为骨架,结合src/ImageSharp/Formats/Tiff/目录下的源码实现与tests/ImageSharp.Tests/Formats/Tiff/下的测试用例,讲清 ImageSharp TIFF 编解码器“支持什么、不支持什么、底层如何实现、代码中如何配置”,帮助你在实际项目中避开兼容性陷阱。

一、TIFF 编解码器架构总览

在深入矩阵之前,先建立整体认知。ImageSharp 的 TIFF 模块遵循标准格式插件架构:

  • TiffFormat.cs 定义格式本体:Name为"TIFF",默认 MIME 为image/tiff,支持image/tiff、image/tiff-fx两种 MIME 与tiff、tif两种扩展名;
  • TiffConfigurationModule.cs 负责向ImageFormatsManager注册TiffEncoder、TiffDecoder.Instance和TiffImageFormatDetector;
  • TiffImageFormatDetector.cs 通过前 8 字节识别文件:0x49 0x49(小端)/0x4D 0x4D(大端)字节序标记,配合魔数42(经典 TIFF)或43(BigTIFF)。也就是说,ImageSharp 的 TIFF 检测器同时支持经典 TIFF 与 BigTIFF;
  • TiffEncoder.cs 与 TiffDecoder.cs 分别是编解码入口,最终由内部TiffEncoderCore/TiffDecoderCore完成实际工作。

值得注意的一点是,TIFF 的 IFD(Image File Directory)结构天然支持多帧,ImageSharp 将每个 IFD 映射为ImageFrame,因此多帧 TIFF 的读写与 GIF 类似,都是通过image.Frames集合来操作。README 明确指出:解码器当前仅支持“所有帧尺寸相同”的多帧图像,任何帧尺寸大于根帧的多帧文件会直接抛出NotSupported(详见 TiffDecoderCore.cs 中DecodeFrame的尺寸校验逻辑)。

二、压缩格式支持矩阵与实现原理

README 的压缩能力表是选择 TIFF 编码参数时最重要的参考,完整继承如下:

压缩格式EncoderDecoder说明
None(无压缩)YY原样存储像素数据
Ccitt1DYY1 维 Modified Huffman RLE(T.4 一维)
PackBitsYYTIFF 6.0 第 9 节的游程压缩
CcittGroup3FaxYYCCITT T.4 二值编码(Group 3)
CcittGroup4FaxYYCCITT T.6 二值编码(Group 4)
LzwYY基于 ImageSharp GIF LZW 实现,可进一步共享或按场景优化
Old JpegY仅支持 chunky(连续)配置
Jpeg(Technote 2)YY新式 JPEG 压缩
Deflate(Technote 2)YY基于 PNG Deflate 实现
Old Deflate(Technote 2)Y兼容旧式 Deflate(tag 32946)
WebpY解码 WebP 压缩的 TIFF 像素数据

2.1 源码中的实现分布

压缩相关的全部实现集中在 Compression 目录:

  • 压缩器(Compressors):NoCompressor、PackBitsCompressor、LzwCompressor+TiffLzwEncoder、T4BitCompressor、T6BitCompressor、TiffCcittCompressor、DeflateCompressor、TiffJpegCompressor;
  • 解压器(Decompressors):NoneTiffCompression、PackBitsTiffCompression、LzwTiffCompression、ModifiedHuffmanTiffCompression(CCITT 1D)、T4TiffCompression、T6TiffCompression、DeflateTiffCompression、JpegTiffCompression、OldJpegTiffCompression、WebpTiffCompression;
  • 选择逻辑由 TiffCompressorFactory.cs 与 TiffDecompressorsFactory.cs 承担。

从 TiffDecompressorsFactory.cs 可以看到两类重要约束:

  1. Predictor 只允许配合 LZW 与 Deflate——其余压缩路径中若出现 predictor 会触发DebugGuard断言失败;
  2. Fax 类压缩(T4/T6/HuffmanRLE)逐行解码,在平铺(tiled)场景下必须使用 tile 行宽计算缓冲,这也是工厂单独传入tileWidth/tileHeight的原因。

2.2 底层依赖关系

README 特别注明了两处代码复用关系,这在源码中可以交叉印证:

  • LZW 基于 ImageSharp GIF LZW 实现——TIFF 的 LZW 编码/解码器与 GIF 的 LZW 属于同一算法家族,ImageSharp 在TiffLzwEncoder/TiffLzwDecoder中按 TIFF 规范做了适配(如 code size 与 early change 处理差异),README 也诚实指出该代码“可以被修改为(i)共享,或(ii)各自优化”;
  • Deflate 基于 PNG Deflate——TIFF Technote 2 的 Deflate 使用 zlib 数据格式,实现位于DeflateCompressor/DeflateTiffCompression,与 PNG 解码路径共用底层的 zlib 读写基础设施(SixLabors.ImageSharp.Compression.Zlib)。

2.3 编码时的自动降级策略

你可能会好奇:如果编码时选择了“未实现”的压缩怎么办?TiffEncoderCore.cs 的SanitizeAndSetEncoderOptions给出了完整的兜底规则:

  • 1-bit CCITT 压缩(Ccitt1D/Group3/Group4)只能用于 1 bpp 图像:若 bpp 不是 1,自动降级——< 8 bpp时改为None,否则改为Deflate;
  • JPEG 压缩不支持 48/64/96/128 bpp 高精度整数样本:自动降级为Deflate;
  • 浮点样本下,Fax 与 JPEG 压缩无法写入:自动降级为Deflate。

这意味着编码器选项在“不合理”时会被静默修正,最终写入文件的参数以修正后的值为准(可以通过解码后的TiffFrameMetadata.Compression验证)。

三、高精度样本支持:16/32 位整数与 32 位浮点

README 中关于高精度样本的段落是本模块的一大亮点,原文要点如下:

对于高精度样本,编码器和解码器支持无符号 16 位与 32 位 RGB/RGBA 样本(48、64、96 或 128 bits per pixel)。同时支持 32 位浮点灰度、RGB、RGBA 样本(32、96 或 128 bits per pixel)。浮点编码支持 None、PackBits、Lzw 与 Deflate 压缩。浮点 predictor 不支持。

3.1 位深枚举完整梳理

TiffBitsPerPixel.cs 定义了从 1 到 128 的全部位深枚举,逐一说明:

枚举值位深语义与编码器行为
Bit11双色图(bilevel)
Bit44调色板图像
Bit6/10/12/146/10/12/14编码器暂不支持,请求后自动降级为 24 bpp RGB
Bit88灰度或调色板图像
Bit1616灰度(L16)
Bit2424每通道 1 字节的 RGB
Bit30/36/4230/36/42每通道 10/12/14 位;编码器按48 bpp写入
Bit3232四个 8 位整数样本,或一个 32 位浮点样本
Bit4848三个 16 位整数样本
Bit6464三个 16 位样本 + 16 位 alpha
Bit9696三个 32 位样本(整数或浮点)
Bit128128四个 32 位样本(整数或浮点)

3.2 浮点样本的编码规则

从 TiffEncoderCore.cs 的浮点分支可以提炼出几条硬性规则:

  1. 浮点模式只接受Bit32 / Bit96 / Bit128三种位深,其他值会被重新计算;
  2. Bit32一律按灰度写入(BlackIsZero或WhiteIsZero),Bit96/Bit128一律按Rgb写入;
  3. 浮点压缩仅限None / PackBits / Deflate / Lzw,其余压缩自动降级为Deflate;
  4. 浮点 predictor(TiffPredictor.FloatingPoint)不支持——编码端强制写入TiffPredictor.None,解码端在 TiffDecoderOptionsParser.cs 中遇到FloatingPointpredictor 直接抛出NotSupported。

对应地,TiffDecoder.cs 在解码时会根据元数据自动选择像素类型:浮点样本解码为RgbaVector(或带预乘 alpha 的RgbaVectorP);整数 RGB 样本则按位深匹配Rgb48/Rgba64/Rgb96/Rgba128,其余默认Rgba32。测试 TiffEncoderTests.cs 中的FloatSingleComponent_RoundTripsWithoutChangingIntensity、Rgb48_RoundTrips16BitSamples等用例专门验证了这些高精度路径的往返无损性。

四、光度解释(Photometric Interpretation)支持矩阵

光度解释决定像素数值如何映射为颜色,是 TIFF 兼容性的核心。README 的能力表完整继承如下:

光度解释EncoderDecoder说明
WhiteIsZeroYY通用实现 + 1/4/8 位优化实现
BlackIsZeroYY通用实现 + 1/4/8 位优化实现
Rgb(Chunky 连续)YY通用实现 + Rgb888 优化实现
Rgb(Planar 平面)Y仅通用实现
PaletteColorYY仅通用实现
TransparencyMask不支持
Separated(TIFF 扩展)Y通常是 CMYK
YCbCr(TIFF 扩展)Y解码支持
CieLab(TIFF 扩展)Y解码支持
IccLab(TechNote 1)不支持
CMYKY解码支持
Tiled ImagesY平铺图像解码支持

4.1 编码端的光度解释自动映射

编码时若不显式指定PhotometricInterpretation,TiffEncoderCore.cs 会按位深自动选择最合适的解释方式:

  • Bit1:使用 CCITT 压缩时强制WhiteIsZero(二值 CCITT 数据的标准解释),否则BlackIsZero;
  • Bit4 / Bit8:PaletteColor(允许显式指定为 BlackIsZero/WhiteIsZero);
  • Bit16:BlackIsZero(等价于 L16 灰度);
  • Bit48 / Bit64 及以上:Rgb。

4.2 解码端的色彩类型派发

解码端 TiffDecoderOptionsParser.cs 的ParseColorType是最复杂的派发逻辑,它会根据PhotometricInterpretation + BitsPerSample + PlanarConfiguration + SampleFormat组合出TiffColorType:

  • WhiteIsZero / BlackIsZero:仅接受单通道,支持 1/4/8/16/24/32 位及 32 位浮点等细分类型;
  • Rgb:仅接受 3 或 4 通道且各通道位深相等,Chunky 下支持 2~32 位(含浮点)十余种细分类型,Planar 下支持 8/16/24/32 位;
  • PaletteColor:需要ColorMap标签,缺失则抛异常;
  • YCbCr:仅 8 位/通道,需YCbCrCoefficients、YCbCrSubsampling、ReferenceBlackWhite等参数配合,Chunky 与 Planar 各有独立类型;
  • Separated(CMYK):仅 8 位/通道、4 通道,且不支持自定义InkNames;
  • CieLab:3 通道,Chunky/Planar 均可。

从源码结构看(如PhotometricInterpretation目录下的解码器文件),README 所述“1/4/8 位优化实现”与“Rgb888 优化实现”对应着WhiteIsZero1Bit、WhiteIsZero4Bit、WhiteIsZero8Bit、BlackIsZero*、Rgb888等专用解码器,通用实现则覆盖 16/24/32 位等高精度场景。

五、Baseline TIFF 标签支持矩阵

TIFF 6.0 基线标签共 28 个,README 的能力表完整继承如下(Y 表示支持,空表示不支持,-表示“不适用/特殊处理”):

基线标签EncoderDecoder说明
NewSubfileType
SubfileType
ImageWidthYY
ImageLengthYY
BitsPerSampleYY
CompressionYY
PhotometricInterpretationYY
Thresholding
CellWidth
CellLength
FillOrderY
ImageDescriptionYY
MakeYY
ModelYY
StripOffsetsYY
Orientation-忽略。许多读取器都忽略此标签
SamplesPerPixelY-当前被忽略,因为可从 BitsPerSample 数量推断
RowsPerStripYY
StripByteCountsYY
MinSampleValue
MaxSampleValue
XResolutionYY
YResolutionYY
PlanarConfigurationYY编码器只写 chunky;解码器同时支持 chunky 与 planar
FreeOffsets
FreeByteCounts
GrayResponseUnit
GrayResponseCurve
ResolutionUnitYY
SoftwareYY
DateTimeYY
ArtistYY
HostComputerYY
ColorMapYY
ExtraSamplesYY编码器写入未关联整数 alpha 或关联/未关联浮点 alpha;未指定的 alpha 数据不支持
CopyrightYY

5.1 几个值得展开的“特殊”标签

  • Orientation 被“忽略”:README 注明“许多读取器都忽略此标签”,ImageSharp 解码器同样不处理旋转语义,这是与主流读取器保持一致的做法;
  • SamplesPerSample 被忽略:通道数完全由BitsPerSample数组的长度推断(见 TiffBitsPerSample.cs,其Channels属性统计非零通道数),因此无需再读SamplesPerPixel;
  • PlanarConfiguration 的不对称:编码器固定输出 chunky(连续)布局;解码器两条路径都实现——DecodeStripsChunky/DecodeTilesChunky与DecodeStripsPlanar/DecodeTilesPlanar并存于 TiffDecoderCore.cs;
  • ExtraSamples 的 alpha 语义:解码端 TiffDecoderOptionsParser.cs 只消费第一个样本:0(未关联 alpha)与1(关联 alpha)会被保留,其他值直接丢弃;同时专门兼容了 CorelDRAW 产生的非标准2(CorelDrawUnassociatedAlphaData),按 libtiff 的处理方式映射为未关联 alpha。

5.2 编码端 IFD 写入细节

编码器在 TiffEncoderCore.cs 的WriteIfd中按 tag 升序写入条目,长度小于等于 4 字节的值直接内联,否则写入独立数据块并在 IFD 中记录偏移;TiffEncoderEntriesCollector负责把图像元数据、帧元数据、格式信息(位深、压缩、光度解释、predictor 等)收集成 IFD 条目。IFD 偏移需要对齐到 2 字节边界,编码器在必要处会补写一个填充字节。

六、扩展 TIFF 标签支持矩阵

扩展标签覆盖 TIFF 6.0 之后的规范增补(Supplement 1/2、RFC 2301 等),完整继承如下:

扩展标签EncoderDecoder说明
NewSubfileType
DocumentNameYY
PageName
XPosition
YPosition
T4OptionsY
T6Options
PageNumber
TransferFunction
PredictorYY仅 Horizontal;不用于浮点样本
WhitePoint
PrimaryChromaticities
HalftoneHints
TileWidth-
TileLength-
TileOffsets-
TileByteCounts-
BadFaxLines
CleanFaxData
ConsecutiveBadFaxLines
SubIFDs-
InkSetYCMYK
InkNames-
NumberOfInks-
DotRange
TargetPrinter
SampleFormatYY编码器写入 IEEE 浮点;默认无符号整数。有符号与复数样本不支持
SMinSampleValue
SMaxSampleValue
TransferRange
ClipPath
XClipPathUnits
YClipPathUnits
Indexed
JPEGTables
OPIProxy
GlobalParametersIFD
ProfileType
FaxProfile
CodingMethods
VersionYear
ModeNumber
Decode
DefaultImageColor
JPEGProc
JPEGInterchangeFormat
JPEGInterchangeFormatLength
JPEGRestartInterval
JPEGLosslessPredictors
JPEGPointTransforms
JPEGQTables
JPEGDCTables
JPEGACTables
YCbCrCoefficientsY
YCbCrSubSamplingY
YCbCrPositioning
ReferenceBlackWhiteY
StripRowCounts--见 RFC 2301(Internet Fax 文件格式)
XMPYY
ImageID
ImageLayer

6.1 Predictor 的实际约束

Predictor是扩展标签中最常用也最易误用的一个。README 明确:仅支持 Horizontal(水平差分),且不用于浮点样本。源码进一步印证:

  • TiffPredictor.cs 定义None=1、Horizontal=2、FloatingPoint=3,其中 FloatingPoint 注释为“编码器不支持,若选择将回退为 None”;
  • TiffEncoderCore.cs 的HasPredictor方法限定只有 Deflate 与 Lzw 压缩才允许启用 predictor,其余压缩一律强制None;
  • 解码端 TiffDecoderOptionsParser.cs 遇到FloatingPointpredictor 直接抛NotSupported。

6.2 SampleFormat 与 StripRowCounts 的细节

  • SampleFormat:解码端只接受UnsignedInteger(1)与Float(3)两种样本格式,出现有符号整数或复数格式直接抛异常;编码端写入 IEEE 浮点或默认无符号整数(TiffSampleFormat.cs);
  • StripRowCounts(RFC 2301 引入的可变长 strip 计数):README 两列均为-;源码中 TiffDecoderOptionsParser.cs 检测到该标签存在时直接抛出NotSupported(“不支持可变大小 strip”);
  • Tile 系列标签:README 表格中 Decoder 列为-,但从源码看,解码器实际上通过 TiffDecoderCore.cs 的DecodeImageWithTiles/DecodeTilesChunky/DecodeTilesPlanar完整消费了TileWidth、TileLength、TileOffsets、TileByteCounts。README 的-更应理解为“这些标签由解码流程内部消费、不对外暴露”;并且VerifyRequiredFieldsArePresent会强制校验 tile 场景下这些字段的完整性(对 planar 配置还要求TileOffsets必须存在,缺失即抛异常)。

七、私有 TIFF 标签支持矩阵

私有标签由厂商与行业组织定义(如 Adobe DNG、GeoTIFF、Photoshop、GPS 等),ImageSharp 的支持非常克制,完整继承如下:

私有标签EncoderDecoder说明
Wang Annotation
MD FileTag
MD ScalePixel
MD ColorTable
MD LabName
MD SampleInfo
MD PrepDate
MD PrepTime
MD FileUnits
ModelPixelScaleTag
IPTCYY
INGR Packet Data Tag
INGR Flag Registers
IrasB Transformation Matrix
ModelTiepointTag
ModelTransformationTag
Photoshop
Exif IFD-0x8769 SubExif
ICC ProfileYY
GeoKeyDirectoryTag
GeoDoubleParamsTag
GeoAsciiParamsTag
GPS IFD
HylaFAX FaxRecvParams
HylaFAX FaxSubAddress
HylaFAX FaxRecvTime
ImageSourceData
Interoperability IFD
GDAL_METADATA
GDAL_NODATA
Oce Scanjob Description
Oce Application Selector
Oce Identification Number
Oce ImageLogic Characteristics
DNGVersion
DNGBackwardVersion
UniqueCameraModel
LocalizedCameraModel
CFAPlaneColor
CFALayout
LinearizationTable
BlackLevelRepeatDim
BlackLevel
BlackLevelDeltaH
BlackLevelDeltaV
WhiteLevel
DefaultScale
DefaultCropOrigin
DefaultCropSize
ColorMatrix1
ColorMatrix2
CameraCalibration1
CameraCalibration2
ReductionMatrix1
ReductionMatrix2
AnalogBalance
AsShotNeutral
AsShotWhiteXY
BaselineExposure
BaselineNoise
BaselineSharpness
BayerGreenSplit
LinearResponseLimit
CameraSerialNumber
LensInfo
ChromaBlurRadius
AntiAliasStrength
DNGPrivateData
MakerNoteSafety
CalibrationIlluminant1
CalibrationIlluminant2
BestQualityScale
Alias Layer Metadata

从矩阵可以看出,私有标签中 ImageSharp 仅实现了IPTC与ICC Profile的读写,以及Exif IFD的部分解码(-表示有内部处理但非完整支持)。大量 DNG 相机原始数据标签(DNGVersion、ColorMatrix、BlackLevel 等)均不支持,这一点对处理数码相机 RAW/DNG 文件的开发者尤其重要——DNG 的完整解析不在 ImageSharp TIFF 编解码器的能力范围内。

八、编码实战:TiffEncoder 选项与使用示例

编码入口是SaveAsTiff系列扩展方法(由 ImageExtensions.Save.cs 生成),支持路径与流两种目标、同步与异步两种调用方式:

using SixLabors.ImageSharp; using SixLabors.ImageSharp.Formats.Tiff; using SixLabors.ImageSharp.Formats.Tiff.Constants; using SixLabors.ImageSharp.PixelFormats; using Image<Rgba32> image = Image.Load<Rgba32>("input.png"); // 基础用法:使用默认 TiffEncoder image.SaveAsTiff("output.tif"); // 高级用法:显式配置编码参数 TiffEncoder encoder = new() { BitsPerPixel = TiffBitsPerPixel.Bit24, // 24 bpp RGB,默认值 Compression = TiffCompression.Deflate, // 压缩算法 CompressionLevel = DeflateCompressionLevel.DefaultCompression, // Deflate 级别 1-9 PhotometricInterpretation = TiffPhotometricInterpretation.Rgb, HorizontalPredictor = TiffPredictor.Horizontal, // 仅 Deflate/Lzw 时生效 }; image.SaveAsTiff("output-deflate.tif", encoder);

8.1 编码器选项全解

TiffEncoder.cs 继承自QuantizingImageEncoder,构造时默认使用KnownQuantizers.Hexadecatree量化器(用于调色板类输出),其公开选项包括:

选项类型说明
BitsPerPixelTiffBitsPerPixel?输出位深,不指定时取自帧元数据,再回退到默认Bit24
SampleFormatTiffSampleFormat?样本格式;浮点样本固定 32 位/分量
CompressionTiffCompression?压缩算法,默认None
CompressionLevelDeflateCompressionLevel?Deflate 压缩级别 1-9,默认DefaultCompression
PhotometricInterpretationTiffPhotometricInterpretation?RGB、调色板、灰度或双色;不指定或编码器不支持时用 RGB
HorizontalPredictorTiffPredictor?水平预测,可提升 Deflate/Lzw 的压缩比

选项优先级遵循“EncoderOptions > 帧元数据 > 默认值”的规则(见 TiffEncoderCore.cs 中Encode方法),而SanitizeAndSetEncoderOptions会在写入前对组合做一致性修正(详见 2.3 与 4.1 节)。

8.2 多帧 TIFF 编码

由于每个ImageFrame会写成一个 IFD,多帧编码就是把多个帧放进同一个Image再保存:

using Image<Rgba32> image = new(100, 100); // 追加帧(尺寸必须与根帧一致) image.Frames.AddFrame(image.Frames.RootFrame.Clone()); image.Frames.AddFrame(image.Frames.RootFrame.Clone()); image.SaveAsTiff("multiframe.tif", new TiffEncoder { Compression = TiffCompression.Lzw });

对应测试 TiffEncoderMultiframeTests.cs 覆盖了多帧编码、添加/移除帧后重编码、以及“不同尺寸变体多帧”不支持等场景。

九、解码实战:流程、校验与限制

解码入口为Image.Load/Image.LoadAsync/Image.Identify。TIFF 解码的核心链路在 TiffDecoderCore.cs:

  1. DirectoryReader读取文件头与全部 IFD 目录(Ifd 目录),解析字节序与 BigTIFF 标记;
  2. 每个 IFD 由TiffFrameMetadata.Parse解析出位深、样本格式、压缩、光度解释、predictor、ink set 等字段(TiffFrameMetadata.cs);
  3. VerifyAndParse对压缩与色彩类型做合法性校验与派发(TiffDecoderOptionsParser.cs):
    • FillOrder为LeastSignificantBitFirst时,只允许 1 bpp 双色 TIFF;
    • 浮点 predictor 不支持;
    • SampleFormat仅允许无符号整数与浮点;
    • YCbCrSubsampling必须恰有 2 个值且垂直子采样不超过水平子采样;
    • StripRowCounts(可变长 strip)不支持;
  4. 校验 tile/strip 必需字段(StripOffsets/StripByteCounts或TileOffsets/TileWidth/TileLength等)是否齐全;
  5. 依据PhotometricInterpretation + BitsPerSample + PlanarConfiguration + SampleFormat派发颜色解码器(ParseColorType),依据压缩标签派发解压器(ParseCompression);
  6. 按 chunky/planar × strip/tile 四种组合之一逐块解压、逐块解码;
  7. RGB 兼容类型(PaletteColor到Rgba32323232Planar区间)在帧级执行 ICC Profile 颜色转换;YCbCr、CMYK、Lab 等类型不做 ICC 转换(TiffDecoderCore.csDecodeFrame中有明确注释说明)。

9.1 几个值得注意的解码限制

  • 多帧尺寸限制:所有帧必须与根帧等宽等高,否则抛NotSupported;
  • 超大 strip 限制:未压缩 strip 超过Int32.MaxValue字节时,NoneTiffCompression路径会退化为逐行读取解码;压缩 strip 超过该阈值则直接抛NotSupported;
  • Old Jpeg 兼容细节:需要JPEGInterchangeFormat提供 SOI 标记偏移,且不支持 planar 配置;YCbCr 光度解释的 Old Jpeg 会被改写为 RGB 交给 JPEG 解码器处理;
  • Jpeg 压缩细节:无论文件中YCbCrSubsampling写什么,解码时统一重置为[1, 1](JPEG 解码器自行处理子采样);缺少JPEGTables的 YCbCr JPEG 同样改写为 RGB 路径(源码注释关联了对应 issue)。

十、测试验证与进一步阅读

TIFF 模块的测试集中在 tests/ImageSharp.Tests/Formats/Tiff:

  • TiffDecoderTests.cs:多帧解码、压缩格式往返、tile 图像解码等;
  • TiffEncoderTests.cs:高精度 16 位(Rgb48/Rgba64)、浮点(FloatSingleComponent)、各种压缩与 predictor 组合的往返测试;
  • TiffEncoderMultiframeTests.cs:多帧编码与限制验证;
  • Compression 子目录:None/PackBits/Lzw/Deflate/CCITT 各解压器的单元测试;
  • PhotometricInterpretation 子目录:WhiteIsZero/BlackIsZero/Palette/RGB/RGBA/Planar 颜色解码器测试;
  • BigTiffDecoderTests.cs与BigTiffMetadataTests.cs:BigTIFF(魔数 43)解码验证。

如需深入底层,建议按此顺序阅读源码:TiffEncoder.cs → TiffEncoderCore.cs → TiffDecoder.cs → TiffDecoderCore.cs → TiffDecoderOptionsParser.cs → Compression 目录。README 中引用的 TIFF 6.0 规范、Supplement 1/2/3、TIFF-F/FX(RFC 2301)、CCITT T.4/T.6、EXIF 2.3、XMP 等参考资料原文,可在本仓库的 TIFF 模块目录 中查阅对应规范文档(仓库附带 TIFF-v6.pdf 等 PDF 原文与 T-REC-T.4/T.6 标准文本)。

十一、总结:选择 TIFF 参数时的决策要点

综合 README 能力矩阵与源码实现,在实际项目中可以按以下清单快速决策:

  1. 通用彩色照片/图形:Rgb+Bit24,压缩可选None(最快)、PackBits(中等)、Lzw或Deflate(高压缩比,可配HorizontalPredictor);
  2. 传真/文档扫描(二值):WhiteIsZero+Bit1+CcittGroup3Fax/CcittGroup4Fax/Ccitt1D;
  3. 高精度影像(医学、遥感):整数走Bit48/64/96/128,浮点走SampleFormat.Float+Bit32/96/128,压缩限None/PackBits/Lzw/Deflate,且不要启用 predictor;
  4. 兼容性红线:解码可放宽(支持 planar、tile、CMYK、YCbCr、CieLab、WebP 压缩、Old Jpeg 等),编码保守(仅 chunky、仅 WhiteIsZero/BlackIsZero/Rgb/PaletteColor、不支持 tiled 输出、DNG 系列私有标签全部不支持);
  5. 多帧:所有帧必须同尺寸,写多帧用Frames.AddFrame,读多帧按Frames索引访问。

掌握这张“支持矩阵”与背后的降级规则,就能在 ImageSharp 生态中安全、高效地处理绝大多数 TIFF 场景。

  • 图像处理
  • 图形学

【免费下载链接】ImageSharp

A modern, cross-platform, 2D Graphics library for .NET

项目地址:https://gitcode.com/gh_mirrors/im/ImageSharp
点击查看免费下载

相关推荐

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询