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

C语言读取TIFF/RGB raw图像32位浮点像素值异常问题

手动读取32位浮点TIFF及RGB文件像素值异常问题

问题概述

我尝试读取RawTherapee生成的32位浮点TIFF文件中的像素值,GIMP可正常打开该文件。通过ExifTool和tiffdump获取到核心信息:

  • TIFF头大小:13022字节
  • 图像尺寸:宽4916、高7370
  • 位图数据大小:434771040字节

测试操作与异常结果

我编写了C程序测试读取(0,0)像素,步骤如下:

  • 以二进制模式打开文件
  • 跳过13022字节的TIFF头
  • 读取第一个像素的3个浮点值(共12字节)
  • 用%f格式打印结果

RawTherapee中显示该像素RGB值为(22.7%, 31.0%, 0%),对应浮点值应处于[0.0, 1.0]范围内,但程序输出的是随机数。

随后用ImageMagick将TIFF转换为raw RGB位图,执行相同读取步骤(无需跳过头部),结果仍为随机数,且与TIFF文件的读取结果不匹配。但将该RGB文件转成JPG后显示正常,说明RGB文件本身数据完好。

文件验证信息

该浮点TIFF仅包含1个strip,StripByteCounts为标量而非数组,其值与预期的RGB数据大小(宽×高×12字节/像素)完全一致,RGB文件大小也与该值匹配:

lsr -s pf-274887.edge.f32.tif.rgb  ->  434771040
mult 4916 7370 12            434771040

ExifTool输出的关键字段:

exiftool -s -all pf-274887.edge.f32.tif | sort | egrep "^ImageSize|^Strip|SampleFormat"
ImageSize                       : 4916x7370
SampleFormat                    : Float; Float; Float
StripByteCounts                 : 434771040
StripOffsets                    : 13022  << Scalar,not array

tiffdump输出的关键字段:

tiffdump pf-274887.edge.f32.tif | egrep "BitsPerSample|ImageLength|ImageWidth|^Strip"
ImageWidth (256) SHORT (3) 1<4916>
ImageLength (257) SHORT (3) 1<7370>
BitsPerSample (258) SHORT (3) 3<32 32 32>
StripOffsets (273) LONG (4) 1<13022>
StripByteCounts (279) LONG (4) 1<434771040>

程序运行结果

----------
Running:
float.pixel.test
pf-274887.edge.f32.tif: Seek -> 13022, Read 3:  
float:  B -0.000000, G -0.000003, R 0.000000 ->  
UINT32: B 2634654270, G 3059326270, R  457414589

pf-274887.edge.f32.tif.rgb: Seek -> 0, Read 3:  
float:  B 35650027520.000000, G 1450022528.000000, R 0.000000 ->  
UINT32: B 1359269508, G 1319951149, R          0

----
IMAGEMAGICK CONVERSION: ------
convert pf-274887.edge.f32.tif -depth 32 RGB:pf-274887.edge.f32.tif.rgb
convert  -size 4916x7370 -depth 32  RGB:pf-274887.edge.f32.tif.rgb pf-274887.edge.f32.jpg
The .JPG looks perfect. 

SIZE CHECK: ------
lsr -s pf-274887.edge.f32.tif.rgb  ->  434771040
mult 4916 7370 12                      434771040

排查情况与需求

我原本认为读取无TIFF结构的RGB文件能得到合理结果,且浮点值采用与内存一致的IEEE 754格式。我的目标是掌握手动读取的方法,而非仅获取当前案例的像素值,能正确读取RGB文件是关键进展。

我尝试读取(0,0)和(3,3)像素,得到的浮点值均不在[0.0,1.0]范围内,且TIFF与RGB文件的原始值不匹配。我已确保所有seek和fread操作使用size_t类型,检查了fread的读取数量,验证了浮点值并非NaN,也简化了测试程序排除多余操作,但问题依旧。有人建议使用libtiff,但这无法解决RGB文件的读取问题,我希望手动实现解析逻辑。

测试代码

// =============================================================================
// Read and decode a specific pixel in a float32 tiff
/*
 gcc -g -O0 -m64  bln/float.pixel.test.c -lm -lz -o bln/float.pixel.test
*/

#include "stdio.h"
#include "stdlib.h"
#include "stdint.h"
#include <math.h>

int osrp(char *ifn, size_t soff, size_t numf);  // Open, Seek, Read, Print

// =============================================================================
void main(int argc, char *argv[])  {
char tfn[]={ "pf-274887.edge.f32.tif" };      // From RawTherapee
char rfn[]={ "pf-274887.edge.f32.tif.rgb" };  // From ImageMagick
size_t toff=13022ll, roff=0, pixoff=0; // Tif and raw-RGB header Offsets 
int imgx=3, imgy=3, imgw=4916, pix_bytes=12;
    pixoff = (imgy * imgw + imgx) * pix_bytes;  // Byte offet to pixel (3,3)
    pixoff = 0ll;  // Try pixel (0, 0)
    osrp(tfn, toff+pixoff, 3);  // Open, seek, read, print
    osrp(rfn, roff+pixoff, 3);  // FileName, seek_OFFset, #_floats per pixel
    exit(0);                    // 
}  // End Main(). 
// =============================================================================


// =============================================================================
// Open, seek, read, print. Expect floats in (0.0 .. 1.0) range
// Check for errors in number of floats read and NAN on their values
int osrp(char *ifn, size_t soff, size_t numf)  {
union  {  // Overlay floats and 32 bit unsigned ints
    float    fpix[4];  // Holds 1 pixel
    uint32_t ipix[4];  // UI32 and float share same bits    
} fiu;             // Float-Int-Union
FILE *ifp;         // Image_File_Pointer
int ii, numnan=0;  // Number of NANs, Not_A_Numbers
size_t numr;       // uint64_t

    ifp = fopen(ifn, "rb");      // Read Image in Binary mode
    fseek(ifp, soff, SEEK_SET);  // Seek to start of bitmap data
                                 
    // Read numf * 4 bytes from bitmap, store in uint/float union
    numr = fread((void *)fiu.fpix, sizeof(float), numf, ifp);  // 3*4=12B  
    fclose(ifp); 
    if(numr != numf)  {  
        printf("ERROR! NumR %llu != NumF %llu\n", numr, numf);  }

    printf("%s: Seek -> %lld, Read %llu: \nfloat:  B %8.6f, G %8.6f, R %8.6f -> \nUINT32: B %10u, G %10u, R %10u\n",
        ifn, soff, numf, 
        fiu.fpix[0], fiu.fpix[1], fiu.fpix[2],
        fiu.ipix[0], fiu.ipix[1], fiu.ipix[2]);

    for(ii=0; ii < numf; ii++)  {  // Check for Non-Number floats
        if(isnan(fiu.fpix[ii]))  {  numnan++;  }  // Count NANs
    }
    if(numnan == 0)  {  printf("\n");  return(0);  }
    printf("%d floats, %d are NANs!\n\n", numf, numnan);
    return(numnan);
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.27 18:17:06