You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

使用libtiff在C语言中读写TIFF文件时输出黑图问题求助

问题分析与修复方案

你的代码输出全黑图像,核心是几个关键逻辑错误导致的,以下是问题点和修复后的完整代码:

关键错误点

  • 错误复用STRIPOFFSETS和STRIPBYTECOUNTS:这两个标签是输入文件内部的字节偏移与条带大小记录,输出文件有独立的文件结构,直接复制会导致输出文件的偏移指向无效位置,无法正确解析图像数据。
  • 强制设置COLORMAP:如果输入文件不是调色板类型TIFF(比如灰度、RGB图),强行设置调色板会破坏图像的颜色解释逻辑,引发显示异常。
  • 缺失关键标签PHOTOMETRIC:这个标签定义了图像的光度解释类型(灰度、RGB、调色板等),未设置会导致阅读器无法正确识别图像色彩模式。
  • 未检查关键操作返回值:输出文件打开、内存分配、条带读取/写入的操作未做错误校验,一旦失败会引发后续逻辑崩溃。
  • 输出文件打开模式错误:使用w+不符合libtiff推荐写法,应使用w创建新文件。

修复后的代码

// Include necessary header files
#include <stdio.h>
#include <stdlib.h>
#include <tiffio.h>

// Main function
int main() {
    // Open the input TIFF file
    TIFF* tif_in = TIFFOpen("image.tiff", "rb");
    if (!tif_in) {
        printf("Failed to open input TIFF file.\n");
        return 1;
    }

    // Open the output TIFF file
    TIFF* tif_out = TIFFOpen("output.tiff", "w");
    if (!tif_out) {
        printf("Failed to open output TIFF file.\n");
        TIFFClose(tif_in);
        return 1;
    }
    
    // Variables to store image properties
    uint32 width, height;
    uint16 bits_per_sample, samples_per_pixel, photometric, planar_config;
    uint32 strip_size;
    uint8* strip_data;
    uint32 number_of_strips;
    uint16 compression_method;
    
    // Retrieve core image properties from input
    TIFFGetField(tif_in, TIFFTAG_IMAGEWIDTH, &width);
    TIFFGetField(tif_in, TIFFTAG_IMAGELENGTH, &height);
    TIFFGetField(tif_in, TIFFTAG_BITSPERSAMPLE, &bits_per_sample);
    TIFFGetField(tif_in, TIFFTAG_SAMPLESPERPIXEL, &samples_per_pixel);
    TIFFGetField(tif_in, TIFFTAG_COMPRESSION, &compression_method);
    TIFFGetField(tif_in, TIFFTAG_PHOTOMETRIC, &photometric);
    TIFFGetField(tif_in, TIFFTAG_PLANARCONFIG, &planar_config);
    
    // Set core properties for output file
    TIFFSetField(tif_out, TIFFTAG_IMAGEWIDTH, width);
    TIFFSetField(tif_out, TIFFTAG_IMAGELENGTH, height);
    TIFFSetField(tif_out, TIFFTAG_BITSPERSAMPLE, bits_per_sample);
    TIFFSetField(tif_out, TIFFTAG_SAMPLESPERPIXEL, samples_per_pixel);
    TIFFSetField(tif_out, TIFFTAG_COMPRESSION, compression_method);
    TIFFSetField(tif_out, TIFFTAG_PHOTOMETRIC, photometric);
    TIFFSetField(tif_out, TIFFTAG_PLANARCONFIG, planar_config);

    // Only copy color map if input is palette-type image
    if (photometric == PHOTOMETRIC_PALETTE) {
        uint16 cmap_depth;
        uint16 *cmap_red, *cmap_green, *cmap_blue;
        TIFFGetField(tif_in, TIFFTAG_COLORMAP, &cmap_red, &cmap_green, &cmap_blue);
        TIFFGetField(tif_in, TIFFTAG_COLORMAPDEPTH, &cmap_depth);
        TIFFSetField(tif_out, TIFFTAG_COLORMAP, cmap_red, cmap_green, cmap_blue);
        TIFFSetField(tif_out, TIFFTAG_COLORMAPDEPTH, cmap_depth);
    }
    
    // Allocate memory for strip data
    strip_size = TIFFStripSize(tif_in);
    strip_data = (uint8*)malloc(strip_size);
    if (!strip_data) {
        printf("Failed to allocate memory for strip data.\n");
        TIFFClose(tif_in);
        TIFFClose(tif_out);
        return 1;
    }

    // Get total number of strips
    number_of_strips = TIFFNumberOfStrips(tif_in);
    
    // Print image properties for debugging
    printf("Strip size is %u\n", strip_size);
    printf("Number of strips are %u\n", number_of_strips);
    printf("Compression method is %u\n", compression_method);
    printf("Width: %u, Height: %u\n", width, height);
    printf("Photometric interpretation: %u\n", photometric);
    
    // Read and write each strip
    for (uint32 strip = 0; strip < number_of_strips; strip++) {
        tsize_t bytes_read = TIFFReadEncodedStrip(tif_in, strip, strip_data, strip_size);
        if (bytes_read < 0) {
            printf("Failed to read strip %u\n", strip);
            free(strip_data);
            TIFFClose(tif_in);
            TIFFClose(tif_out);
            return 1;
        }
        if (TIFFWriteEncodedStrip(tif_out, strip, strip_data, bytes_read) < 0) {
            printf("Failed to write strip %u\n", strip);
            free(strip_data);
            TIFFClose(tif_in);
            TIFFClose(tif_out);
            return 1;
        }
    }
    
    // Cleanup resources
    TIFFClose(tif_in);
    TIFFClose(tif_out);
    free(strip_data);
    
    return 0;
}

额外说明

  • 代码会根据输入文件的PHOTOMETRIC标签自动判断是否复制调色板,避免强制设置引发的兼容性问题。
  • 所有关键操作都添加了错误校验,能及时定位并报告问题。
  • 不再手动处理条带偏移和字节计数,由libtiff自动管理输出文件的结构标签。
  • 使用读取操作的实际字节数作为写入长度,确保数据完全一致。

内容的提问来源于stack exchange,提问作者hacker4life

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.30 06:00:15