2

我有一个程序可以拍摄图像并将其写入 TIFF 文件。图像可以是灰度(8 位)、带 Alpha 通道的灰度(16 位)、RGB(24 位)或 ARGB(32 位)。我在写出没有 alpha 通道的图像时没有任何问题,但是对于具有 alpha 的图像,当我尝试设置额外的样本标记时,我会被发送到由 TIFFSetErrorHandler 设置的 TIFF 错误处理例程。传入的消息<filename>: Bad value 1 for "ExtraSamples"位于 _TIFFVSetField 模块中。下面的一些示例代码:

#include "tiff.h"
#include "tiffio.h"
#include "xtiffio.h"
//Other includes

class MyTIFFWriter
{
public:
    MyTIFFWriter(void);

    ~MyTIFFWriter(void);

    bool writeFile(MyImage* outputImage);
    bool openFile(std::string filename);
    void closeFile();

private:
    TIFF* m_tif;
};

//...

bool MyTIFFWriter::writeFile(MyImage* outputImage)
{
    // check that we have data and that the tiff is ready for writing
    if (outputImage->getHeight() == 0 || outputImage->getWidth() == 0 || !m_tif)
        return false;

    TIFFSetField(m_tif, TIFFTAG_IMAGEWIDTH, outputImage->getWidth());
    TIFFSetField(m_tif, TIFFTAG_IMAGELENGTH, outputImage->getHeight());
    TIFFSetField(m_tif, TIFFTAG_COMPRESSION, COMPRESSION_NONE);
    TIFFSetField(m_tif, TIFFTAG_PLANARCONFIG, PLANARCONFIG_CONTIG);

    if (outputImage->getColourMode() == MyImage::ARGB)
    {
        TIFFSetField(m_tif, TIFFTAG_PHOTOMETRIC, PHOTOMETRIC_RGB);
        TIFFSetField(m_tif, TIFFTAG_BITSPERSAMPLE, outputImage->getBitDepth() / 4);
        TIFFSetField(m_tif, TIFFTAG_SAMPLESPERPIXEL, 4);
        TIFFSetField(m_tif, TIFFTAG_EXTRASAMPLES, EXTRASAMPLE_ASSOCALPHA);  //problem exists here
    } else if (/*other mode*/)
        //apply other mode settings

    //...

    return (TIFFWriteEncodedStrip(m_tif, 0, outputImage->getImgDataAsCharPtr(), 
        outputImage->getWidth() * outputImage->getHeight() *
        (outputImage->getBitDepth() / 8)) != -1);
}

据我所知,标签永远不会被写入文件。幸运的是,GIMP 仍然可以识别附加通道是 alpha,但是需要读取这些 TIFF 的其他一些程序并不那么慷慨。我是否缺少必须在 TIFFTAG_EXTRASAMPLES 之前设置的标签?我是否缺少其他需要存在的标签?任何帮助,将不胜感激。

4

2 回答 2

4

我找到了解决方案。Extra_Samples 字段不是 uint16,而是首先是一个计数(即 uint16),然后是一个该大小的数组(类型为 uint16)。因此,调用应如下所示:

uint16 out[1];
out[0] = EXTRASAMPLE_ASSOCALPHA;

TIFFSetField( outImage, TIFFTAG_EXTRASAMPLES, 1, &out );

这样做的原因是允许多于一个额外的样本。

希望这可以帮助!

干杯,卡斯帕

于 2010-09-09T08:36:04.517 回答
2

感谢 Kaspar、Tomas 和其他所有人的宝贵指导。

以下是此线程中 RGBA 的相关位:

const uint16 extras[] = {EXTRASAMPLE_ASSOCALPHA};
TIFFSetField(tifptr, TIFFTAG_SAMPLESPERPIXEL, 4);
TIFFSetField(tifptr, TIFFTAG_PHOTOMETRIC, PHOTOMETRIC_RGB);
TIFFSetField(tifptr, TIFFTAG_EXTRASAMPLES, EXTRASAMPLE_ASSOCALPHA, 1, extras);

其中 tifptr 是指向定义在tiffio.h.

这是帮助消除 TIFF 标签歧义的链接:

https://www.awaresystems.be/imaging/tiff/tifftags/extrasamples.html

这是获取 libtiff 源代码的链接:

http://www.libtiff.org/

谢谢!

关于 va_list 和朋友的注意事项:

当使用 va_list(可变参数列表)和朋友时,并且提供了错误数量的参数,您会得到无用的段错误。在这里给我的教训是,如果您使用的是现代 C 库,并且遇到无用的段错误,您至少应该考虑这是因为您将长度但没有数组传递给 va 宏。

于 2021-05-20T10:38:05.187 回答