TIFF图像:16bits-RGBA图像像素是如何隔行扫描的?

我试图通过C语言处理每通道16位RGBA TIFF图像,我在规范中找不到关于16位图像的大量信息。

在每通道8位RGBA图像的情况下,我理解像素存储为uint32,并且可以通过将32位分组为8位的4组(R,G,B,A)来进行去交错。 然后,为了处理每通道8位RGBA图像,我正在做以下(请参阅此处附带的源代码):

  1. 我将图像数据存储为uint32选项卡(使用TIFFReadRGBAImageOriented),我称之为data_tiff
  2. 我使用以下命令对像素进行去隔行扫描: (uint8) TIFFGetR(*data_tiff)(uint8) TIFFGetG(*data_tiff)(uint8) TIFFGetB(*data_tiff)(uint8) TIFFGetA(*data_tiff)

如果每通道RGBA图像为16位,您能告诉我如何对像素进行去隔行扫描? 如果我可以将图像数据作为uint64选项卡进行检索,那么我可以执行以下操作:

 #define TIFF16GetR(abgr) ((abgr) & 0xffff) #define TIFF16GetG(abgr) (((abgr) >> 16) & 0xffff) #define TIFF16GetB(abgr) (((abgr) >> 32) & 0xffff) #define TIFF16GetA(abgr) (((abgr) >> 48) & 0xffff)` 
  1. 我将图像数据作为uint64选项卡读取
  2. 我使用(uint16) TIFF16GetR(*data_tiff)(uint16) TIFF16GetG(*data_tiff)(uint16) TIFF16GetB(*data_tiff)(uint16) TIFF16GetA(*data_tiff)去隔行像素

但似乎数据本身并未存储在uint64选项卡中,所以我想知道如何将每通道16位的图像隔行扫描到uint32像素选项卡中。

我也面临着以相同方式处理16位灰度图像的困难(使用TIFFReadRGBAImageOriented获取图像数据并尝试将每个像素转换为uint16)

更一般地说,你有任何关于16位灰度和彩色图像的文档吗?

谢谢您最好的问候,

雷米A.

TIFFReadRGBAImage高级接口将始终以每个样本8位的精度读取图像。

为了在不丢失精度的情况下读取每通道16位图像,您可以直接使用TIFFReadScanline并根据SamplesPerPixelTIFFReadScanline读取正确数量的数据。 但这只有在图像存储在条带中时才有效(不是TIFF 6.0中引入的图块),并且每个压缩条带中必须只有一行(如果图像被压缩)。

如果你想使用TIFFReadRGBAImage处理所有类型的TIFF图像,那么你必须检测图像格式并使用低级接口,如TIFFReadEncodedStripTIFFReadEncodedTile

请注意,TIFF规范非常广泛且灵活,使用这些低级接口来处理所有可能的图像并不是一件容易的事,因此如果可以的话,最好使用比libtiff更高级别的库。

编辑

您在评论中提到的是TIFF 6.0规范的第一部分,称为基线TIFF

«当引入TIFF时,它的可扩展性引发了兼容性问题。 编码的灵活性引发了一个笑话,即TIFF代表了数千种不兼容的文件格式。[9] 为避免这些问题,每个TIFF阅读器都需要读取基线TIFF。 基线TIFF不包括图层,也不包括JPEG或LZW压缩。 基线TIFF正式名称为维基百科的 TIFF 6.0,第1部分:基线TIFF

基线TIFF不支持高于8位的位深度,这就是为什么在基线TIFF的规范中,灰度图像的BitsPerSample的值只能是4或8,而RGB图像的值只能是8位渠道。 支持更高的位深度作为Baseline TIFF规范的扩展,并且TIFF阅读器不需要它来支持它们。

Tiled Images也是Baseline规范的扩展,其中StripOffsetsStripByteCountsRowsPerStrip字段由TileWidthTileLengthTileOffsetsTileByteCounts因此您可以通过使用TIFFGetField()查看现有字段来区分平铺图像和剥离图像。