我正在尝试访问用Rawtherapee生成的tiff文件中的32位浮点数。GIMP可以打开tiff,它看起来很好。
我从ExifTool和tiffdump得到了tif头大小,它们都匹配13,022字节。它们还同意4916宽7370高的宽度和高度以及434,771,040的位图大小。
I wrote a small C program to test reading and decoding the pixel at (0,0):
- Open the file in binary mode
- Seek past the 13022 byte header
- Read the first pixel of 3 floats, 12 bytes into memory
- printf the results with a "%f" format
在RawTherapee中,(0,0)处的像素具有RGB值(22.7%,31.0%和0%)。浮点数应在[0.0.. 1.0]范围内。
解码的浮点数看起来像随机数。所以我用ImageMagick将.tif转换为原始的RGB位图,做了同样的过程,除了寻找0,因为没有标题。结果看起来又是随机的,不匹配tiff像素。
“您的文章似乎包含格式不正确的代码。请使用代码工具栏按钮或CTRL+K键盘快捷键将所有代码缩进4个空格。有关更多编辑帮助,请单击[?]工具栏图标。”这不是代码。
我用ImageMagick将RGB文件转换为JPG,JPG很好,所以RGB文件也一定很好。
浮点tif似乎只有1个条带,并且“StripByteCounts”是标量,而不是数组。StripByteCounts与预期的RGB大小$xres * $yres * 12字节/像素匹配。
RGB文件大小与TIFF StripByteCounts完全匹配:lsr -s pf-274887.edge.f32.tif.rgb -〉434771040 mult 4916 7370 12 434771040
我写了一个小的C程序来尝试访问位图(见下面的代码)。我得到了混乱的数据和tiff和RGB之间的不匹配:
----------
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
EXIFTOOL DATA: ------
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 DATA: ------
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>
=========================================================
float.pixel.test c program:
我期望在没有任何TIFF并发症的情况下阅读RGB文件应该会给予合理的结果。这些值必须以IEEE 754浮点格式存储,与数据存储在内存中的方式相同。
我们的目的是学习如何获取值,而不仅仅是在这种情况下获取值。从RGB获取值将是向前迈出的一大步。
我试着阅读像素(0,0)和(3,3),得到了类似的结果;浮点数不在[0.0.. 1.0]范围内,原始RGB值与tiff值不匹配。
我将tif转换为RGB,然后将RGB转换为JPG,JPG看起来很完美,所以RGB也必须完好无损。
我在所有的seek和fread上使用了size_t。我检查了fread读取的浮点数与请求的数字的错误。我检查了NAN mangling的浮点数。所有的浮点数都是数字,只是不在正确的范围内。
我还期望tiff像素与相应的RGB像素完全匹配,但没有相似之处。我简化了测试程序,不做任何额外的工作。
下面的答案之一是使用“libtiff”,Libtiff对RGB文件阅读问题没有帮助,我不想去Whole Foods买一磅鲑鱼,我想自己抓。
下面是C代码程序,前面有4个空格:
// =============================================================================
// 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);
}
1条答案
按热度按时间bbmckpt71#
我不会直接阅读TIFF文件。它是一种复杂的格式,更糟糕的是,非常灵活。TIFF使写作变得容易(您可以将几乎任何数据布局写入TIFF文件),但阅读困难(数据可以以几乎任何方式呈现,您的读者必须潜在地处理所有许多,许多,许多组合)。
没有人(我认为)曾经写过一个TIFF阅读器,可以加载所有可能的TIFF。甚至libtiff本身也会在许多明显的变化中失败。你可能会让它在这个特定的文件中工作,但它会在(可能)任何其他程序编写的float tiff中失败,如果rawtherapee修改他们的tiff编写器,即使是轻微的修改,它也可能会失败。
我会使用libtiff,或者更好,使用一个高级库,可以为您隐藏大部分的丑陋。
例如,libvips支持浮点像素,可以读取和写入浮点TIFF。它将读取所有基准级TIFF和大多数常用的变体。
这是将常规的8位JPEG转换为scRGB色彩空间,其中像素为线性0 - 1,并保存为TIFF。您可以从
tiffinfo
输出中看到,它是一个简单的浮点TIFF,可能与您的文件类似。你可以读出像素,例如:
检查其价值。
你可以将图像读入大型的C数组,比如:
我看到: