DCR (数码相机原始) 文件格式





5.00/5 (1投票)
某些DCR文件的格式/数据结构
引言
本文描述了某些DCR(数码相机原始文件)文件的格式/数据结构。
通过此数据结构,我们可以将24位(真彩色)的 位图 文件转换为 dcr 文件。
应用场景
Dave Coffin的 dcraw.c 可以解码许多原始照片。如果我们获得他的许可,就可以将代码移植到我们的项目中。但是,如何获得大量的原始照片来测试我们的代码呢?
- 我们可以购买许多不同类型的相机(太费钱)。
- 我们可以等待摄影师上传的非jpeg格式、非png格式的原始照片(太费时)。
- 我们可以使用本文,通过我们自己的小型 `bitMap` 文件来制作原始文件。
数据结构
制造商 | 模型 | tiff_bps | |
1 | 柯达 | DCS760C | 8 |
2 | 理光 | GR Digital | 12 |
3 | 尼康 | SUPER COOLSCAN 5000 ED | |
4 | 爱普生 | R-D1 | |
5 | 宾得 | K110D | |
6 | 丽图 | ||
7 | 仙娜 | ||
8 | 美能达 | DiMAGE 5 | |
9 | 富士胶片 | FinePix S5100 | 14 |
10 | 徕卡 | Digilux 2 | 16 |
11 | 松下 | DMC-LC1 | |
12 | 奥林巴斯 | E-10 | |
13 | 卡西欧 | EX-P600 | |
14 | 飞思 | H 10 |
在许多原始文件中,H(高)和W(宽)是固定的,不能通过我们的源 `bitMap` 进行更改。它们不在本文的讨论范围之内。
背景
某些类型的原始文件不能通过不同的解码器进行转换(例如禄来的 `d530flex` 原始格式,它不被acdsee的 id_dcRaw.apl 2.2版导出)。它们也不在本文的讨论范围之内。
如果我们声明“ `unsigned char bitMap[H][W][3]`”,并从小的24位3通道 `bitMap` (文件)中读取它们,那么我们可以使用以下文件格式自己制作原始文件。
注意:24位3通道 `bitMap` 的文件格式是
0000~ 0001: | 0002~ 0005: | 0006~ 0009: | 000a~ 000d | 000e~0035:(long head[0x0a]) | 0x36~(0x35+H*W4) | |||||||
'B', 'M' | 0x36 +H*W4 | 0 | 0x36 | 000e~ 0011: | 0012~ 0015: | 0016~ 0019: | 001a~001d | 001e~ 0021: | ... | 0032~ 0035: | unsigned char bitMap[H][W4] | |
0x28 | W | H | 1 | 24 | 0 | ... | 0 | |||||
flag | long 文件大小 | ? | long &bitMap | long head_size | long 宽度 | long 高度 | short plane,bps | long compress | ... | long cnt2 |
W4 ( `bitMap` 文件中每 `scanLine` 的字节数)=(W*3+3)&(~3),它对齐到4字节,用于加速。)
上述大多数原始文件使用tiff(标签图像文件格式)格式。在这种格式中,文件开头会有一些ifde(图像文件目录条目),每个ifde都是一个 `12_bytes_structure`:{short tag; short type; long count; long value(or offset)}。
某些原始文件会使用它们的颜色矩阵。那时,我们应该使用我们的默认矩阵,将从xyz空间转换为rgb空间。
有符号长整型 ColorMatrix[3][6]=
(?+0000)~ (?+0017): | {3240479,1000000, -1537151,1000000, -498535,1000000} | //表示: 3.240479, -1.537151, -0.498535 |
(?+0018)~ (?+002f) | {-969256,1000000, 1875992,1000000, 41556,1000000} | //表示: -0.969256, 1.875992, 0.041556 |
(?+0030)~ (?+0047): | { 55648,1000000, -204043,1000000, 1057311,1000000} | //表示: 0.055648, -0.204043, 1.057311 |
1. 柯达
0000~0001: | 'I','I' | 顺序:littleEndian("II":intel) 或 bigEndian("MM":motorola) |
0002~0003: | 0x2a,0 | tif版本 |
0004~0007: | 0x0a,0,0,0 | 长整型 &entries_1 |
0008~0009: | ?,? | |
(entries_1) 000a~000b | 8,0 | 短整型 entry_count=8 |
至少有8个条目紧随其后,每个条目都是一个 `12_bytes_structure`,我们可以断言每个都是 `3_signed_long_array`
1 | 000c~0017 | 0xAc621,?,0x90 | &ColorMatrix |
2 | 0018~0023: | 0x10f, ?, 0x70 | &str_make |
3 | 0024~002f | 0x110, ?, 0x80 | &str_model |
4 | 0030~003b | 0x100, 1, W | W>=22(for irfanView) |
5 | 003c~0047 | 0x101, 1, H | H>=22(for dcRaw) |
6 | 0048~0053: | 0x102, 0, 8 | tiff_bps |
7 | 0054~005f | 0x103, 1, 1 | tiff_compress |
8 | 0060~006b | 0x144, 1, 0xe0 | &raw_data |
条目是乱序的。我们当然可以向其中添加任何内容,我们必须更改上面的 `entry_count`。
006c~006f | 长整型 entries_2=0 |
0070~007f | 字符数组 str_make[]={"Kodak"} |
0080~008f | 字符数组 str_model[]={"DCS760C"} |
0090~00d7 | 有符号长整型 ColorMatrix[3][6] |
00d8~00df | ? |
整型 order[2][2]={{G,R},{B,G}};
(在以下文本中, `bitMap[y][x][c]` 简写为 `m[y,x,c]`,
而 `order[(y)&1][(x)&1]` 简写为“ `o(y,x)`”)。
文件地址 | 无符号字符 raw_data[H*W] | |||||
00e0~ (00df+W) | m[0,0,G] | m[0,1,R] | m[0,2,G] | m[0,3,R] | ... | m[0,W-1,(1&W)?G:R] |
(00e0+W)~ (00df+W*2) | m[1,0,B] | m[1,1,G] | m[1,2,B] | m[1,3,G] | ... | m[1,W-1,(1&W)?B:G] |
(00e0+W*2)~ (00df+W*3) | m[2,0,G] | m[2,1,R] | m[2,2,G] | m[2,3,R] | ... | m[2,W-1,(1&W)?G:R] |
(00e0+W*3)~ (00df+W*4) | m[3,0,B] | m[3,1,G] | m[3,2,B] | m[3,3,G] | ... | m[3,W-1,(1&W)?B:G] |
... | ... | |||||
(00e0+W*(H-1))~ (00df+W*H) | m[H-1,0, o(H-1,0)] | m[H-1,1, o(H-1,1)] | m[H-1,2, o(H-1,2)] | m[H-1,3, o(H-1,3)] | ... | m[H-1,W-1, o(H-1,W-1)] |
就这些,返回主菜单。
2. 理光
0000~0001: | 'I','I' | 顺序:littleEndian("II":intel) 或 bigEndian("MM":motorola) |
0002~0003: | 0x2a,0 | tif版本 |
0004~0007: | 0x0a,0,0,0 | 长整型 &entries_1; |
0008~0009: | ?,? | |
(entries_1) 000a~000b | 7,0 | 短整型 entry_count; |
后面有7个条目。
每个条目都是一个 `12_bytes_structure`,我们可以断言每个都是 `3_signed_long_array`
1 | 000c~0017 | 0x10f,?, 0x70 | &str_make |
2 | 0018~0023: | 0x110,?, 0x80 | &str_model |
3 | 0024~002f | 0x100,1, w*2 | w*2>=22 (irfanView) |
4 | 0030~003b | 0x101,1, H | H>=22 (dcRaw) |
5 | 003c~0047 | 0x102,0, 0x0c | tiff_bps |
6 | 0048~0053: | 0xfd04,4, 0 | 标签(P系列) |
7 | 0054~005f | 0x144,1, 0x90 | &raw_data |
条目是乱序的。当然,我们可以在其中添加任何内容,我们必须更改上面的 `entry_count`。
在这里,我们使用w=W/2,//它表示宽度的一半
因为acdsee 5.0( id_dcRaw.apl 版本 2.2)声明每 `scanLine` 有( `12*W`)位,
而cxImg6.0( `libdcr` 版本 0.1.8.93)声明每 `scanLine` 有( `12*raw_width`)位,
而irfan 4.42( formats.dll 4.42)声明每 `scanLine` 有( `12*raw_width+7`)&(~7)位。
0060~006f | 长整型 entries_2[]={0}; |
0070~007f | 字符数组 str_make[16]={"ricoh"}; |
0080~008f | 字符数组 str_model[16]={"GR Digital"}; |
整型 order[2][2]={{R,G},{G,B}};
(在以下文本中, `bitMap[y][x][c]` 简写为 `m[y,x,c]`,
而 `order[(y)&1][(x)&1]` 简写为“ `o(y,x)`”)
无符号字符 raw_data[H*u]
第一行 a~ (a+u-1) | m[0,0,R] | m[0,1,G]>>4 | m[0,1,G]<<4 | m[0,2,R] | m[0,3,G]>>4 | m[0,3,G]<<4 | ... | m[0,2*w-2,R] | m[0,2*w-1,G]>>4 | m[0,2*w-1,G]<<4 |
第二行 (a+u)~ (a+u*2-1) | m[1,0,G] | m[1,1,B]>>4 | m[1,1,B]<<4 | m[1,2,G] | m[1,3,B]>>4 | m[1,3,B]<<4 | ... | m[1,2*w-2,G] | m[1,2*w-1,B]>>4 | m[1,2*w-1,B]<<4 |
第三行 (a+u*2)~ (a+u*3-1) | m[2,0,R] | m[2,1,G]>>4 | m[2,1,G]<<4 | m[2,2,R] | m[2,3,G]>>4 | m[2,3,G]<<4 | ... | m[2,2*w-2,R] | m[2,2*w-1,G]>>4 | m[2,2*w-1,G]<<4 |
第四行 (a+u*3)~ (a+u*4-1) | m[3,0,G] | m[3,1,B]>>4 | m[3,1,B]<<4 | m[3,2,G] | m[3,3,B]>>4 | m[3,3,B]<<4 | ... | m[3,2*w-2,G] | m[3,2*w-1,B]>>4 | m[3,2*w-1,B]<<4 |
... | ... | |||||||||
最后一行 (a+u*(H-1))~ (a+u* H-1) | m[H-1,0, o(H-1,0)] | m[H-1,1, o(H-1,1)]>>4 | m[H-1,1, o(H-1,1)]<<4 | m[H-1,2, o(H-1,2)] | m[H-1,3, o(H-1,3)]>>4 | m[H-1,3, o(H-1,3)]<<4 | ... | m[H-1,2*w-2, o(H-1,2*w-2)] | m[H-1,2*w-1, o(H-1,2*w-1)]>>4 | m[H-1,2*w-1, o(H-1,2*w-1)] |
对于理光, `a=0x90, u=w*3;`
对于尼康, `a=0xa0, u=w*3;`
对于宾得, `a=0xe0, u=w*3;`
对于爱普生, `a=0xe0, u=w*3+((w*2)/10)`
就这些,返回主菜单。
3. 尼康
0000~0001: | 'I','I' | 顺序:littleEndian("II":intel) 或 bigEndian("MM":motorola) |
0002~0003: | 0x2a,0 | tif版本 |
0004~0007: | 0x0a,0,0,0 | 长整型 &entries_1; |
0008~0009: | ?,? | |
(entries_1) 000a~000b | 8,0 | 短整型 entry_count; |
有8个条目紧随其后。
每个条目都是一个 `12_bytes_structure`,我们可以断言每个都是 `3_signed_long_array`
1 | 000c~0017 | 0x10f,?, 0x70 | &str_make |
2 | 0018~0023: | 0x110,?, 0x80 | &str_model |
3 | 0024~002f | 0x100,1, w*2 | w*2>=22 (irfanView) |
4 | 0030~003b | 0x101,1, H | H>=22 (dcRaw) |
5 | 003c~0047 | 0x102,0, 0x0c | tiff_bps |
6 | 0048~0053: | 0x828e,1, 0 | 清除滤镜 |
7 | 0054~005f | 0x828e,4, 0x2010100 | 设置滤镜= 0x94949494 |
8 | 0060~006b | 0x144,1, 0xA0 | &raw_data |
条目是乱序的。当然,我们可以在其中添加任何内容,我们必须更改上面的 `entry_count`。
在这里,我们使用w=W/2,//它表示宽度的一半
因为acdsee 5.0( id_dcRaw.apl 版本 2.2)声明每 `scanLine` 有( `12*W`)位,
而cxImg6.0( `libdcr` 版本 0.1.8.93)声明每 `scanLine` 有( `12*raw_width`)位,
而irfan 4.42( formats.dll 4.42)声明每 `scanLine` 有( `12*raw_width+7`)&(~7)位。
006c~006f | 长整型 entries_2[]={0}; |
0070~007f | 字符数组 str_make[16]={"NIKON"}; |
0080~009f | 字符数组 str_model[32]={"SUPER COOLSCAN 5000 ED"}; |
0xa0~ (0x9f+u*H) | 无符号字符 raw_data[H*u]; |
(注意:u=w*3)
就这些,返回主菜单。
5. 宾得
0000~0001: | 'I','I' | 顺序:littleEndian("II":intel) 或 bigEndian("MM":motorola) |
0002~0003: | 0x2a,0 | tif版本 |
0004~0007: | 0x0a,0,0,0 | 长整型 &entries_1; |
0008~0009: | ?,? | |
(entries_1) 000a~000b | 7,0 | 短整型 entry_count; |
有7个条目紧随其后。
每个条目都是一个 `12_bytes_structure`,我们可以断言每个都是 `3_signed_long_array`
1 | 000c~0017 | 0x10f,?, 0x70 | &str_make |
2 | 0018~0023: | 0x110,?, 0x80 | &str_model |
3 | 0024~002f | 0x100,1, w*2 | w*2>=22 (irfanView) |
4 | 0030~003b | 0x101,1, H | H>=22 (dcRaw) |
5 | 003c~0047 | 0x102,0, 0x0c | tiff_bps |
6 | 0048~0053: | 0xAc621,?, 0x90 | &ColorMatrix |
7 | 0054~005f | 0x144,1, 0xe0 | &raw_data |
条目是乱序的。当然,我们可以在其中添加任何内容,我们必须更改上面的 `entry_count`。
在这里,我们使用w=W/2,//它表示宽度的一半
因为acdsee 5.0( id_dcRaw.apl 版本 2.2)声明每 `scanLine` 有( `12*W`)位,
而cxImg6.0( `libdcr` 版本 0.1.8.93)声明每 `scanLine` 有( `12*raw_width`)位,
而irfan 4.42( formats.dll 4.42)声明每 `scanLine` 有( `12*raw_width+7`)&(~7)位。
0060~006f | 长整型 entries_2[]={0}; |
0070~007f | 字符数组 str_make[16]={"Pentax"}; |
0080~008f | 字符数组 str_model[16]={"K110D"}; |
0090~00d7 | 有符号长整型 ColorMatrix[3][6]; |
00d8~00df | ? |
0xe0~ (0xdf+u*H) | 无符号字符 raw_data[H*u]; |
(注意: `u=w*3`)
就这些,返回主菜单。
4. 爱普生
0000~0001: | 'I','I' | 顺序:littleEndian("II":intel) 或 bigEndian("MM":motorola) |
0002~0003: | 0x2a,0 | tif版本 |
0004~0007: | 0x0a,0,0,0 | 长整型 &entries_1; |
0008~0009: | ?,? | |
(entries_1) 000a~000b | 8,0 | 短整型 entry_count; |
后面有8个条目。
每个条目都是一个 `12_bytes_structure`,我们可以断言每个都是 `3_signed_long_array`
1 | 000c~0017 | 0x10f,?, 0x70 | &str_make |
2 | 0018~0023: | 0x110,?, 0x80 | &str_model |
3 | 0024~002f | 0x100,1, w*2 | w*2>=22 (irfanView) |
4 | 0030~003b | 0x101,1, H | H>=22 (dcRaw) |
5 | 003c~0047 | 0x102,0, 0x0c | tiff_bps |
6 | 0048~0053: | 0x103,0,0x8001 | tiff_compress |
7 | 0054~005f | 0xAc621,?, 0x90 | &ColorMatrix |
8 | 0060~006b | 0x144,1, 0xe0 | &raw_data |
条目是乱序的。当然,我们可以在其中添加任何内容,我们必须更改上面的 `entry_count`。
在这里,我们使用w=W/2,//它表示宽度的一半
因为acdsee 5.0( id_dcRaw.apl 版本 2.2)声明每 `scanLine` 有( `12*W`)位,
而cxImg6.0( `libdcr` 版本 0.1.8.93)声明每 `scanLine` 有( `12*raw_width`)位,
而irfan 4.42( formats.dll 4.42)声明每 `scanLine` 有( `12*raw_width+7`)&(~7)位。
006c~006f | 长整型 entries_2[]={0}; |
0070~007f | 字符数组 str_make[16]={"EPSON"}; |
0080~008f | 字符数组 str_model[16]={"R-D1"}; |
0090~00d7 | 有符号长整型 ColorMatrix[3][6]; |
00d8~00df | ? |
0xe0~ (0xdf+u*H) | 无符号字符 raw_data[H*u]; |
//注意:u=w*3+((w*2)/10)。
仅适用于爱普生:在(扫描)行中每 `15_bytes` 的 `raw_data` 后,我们必须插入1个零字节(对齐到16字节,用于加速)。
所以, `if(2<=(width%10)<8)`,这些 `zero_bytes` 会在 `cxImg7.0` 中引起一个bug,但在 `cxImg6.0` 中不会。
就这些,返回主菜单。
6. 丽图
0000~0001: | 'I','I' | 顺序:littleEndian("II":intel) 或 bigEndian("MM":motorola) |
0002~0003: | 0x2a,0 | tif版本 |
0004~0007: | 0x0a,0,0,0 | 长整型 &entries_1; |
0008~0009: | ?,? | |
(entries_1) 000a~000b | 8,0 | 短整型 entry_count; |
后面有8个条目。
每个条目都是一个 `12_bytes_structure`,我们可以断言每个都是 `3_signed_long_array`
1 | 000c~0017 | 0x85ff, ?, ? | 丽图标签 |
2 | 0018~0023: | 0x100,1, W | W>=22(for irfanView) |
3 | 0024~002f | 0x101,1, H | H>=22(for dcRaw) |
4 | 0030~003b | 0x115,1, 1 | tiff_samples |
5 | 003c~0047 | 0xAc621,?, 0x70 | &ColorMatrix |
6 | 0048~0053: | 0x144,1, 0xc0 | &raw_data |
7 | 0054~005f | 0x142,1, W | tile_width |
8 | 0060~006b | 0x143,1, H-1 | tile_length |
条目是乱序的。当然,我们可以在其中添加任何内容,我们必须更改上面的 `entry_count`。
006c~006f | 长整型 entries_2[]={0} |
0070~00b7 | 有符号长整型 ColorMatrix[3][6] |
00b8~00bf | ? |
00c0~00cf | 长整型 ptr[4]={0xd0, 0xd0+(H-1)*W*2}; //&第一行, &最后一行 |
整型 order[2][2]={{R,G},{G,B}};
(在以下文本中,bitMap[y][x][c] 简写为 m[y,x,c],
而 order[(y)&1][(x)&1] 简写为“o(y,x)”)
无符号短整型 raw_data[H*W]
第一行 a~ (a+W*2-1) | m[0,0,R]<<s | m[0,1,G]<<s | m[0,2,R]<<s | m[0,3,G]<<s | ... | m[0,W-1,(1&W)?R:G]<<s |
第二行 (a+W*2)~ (a+W*4-1) | m[1,0,G]<<s | m[1,1,B]<<s | m[1,2,G]<<s | m[1,3,B]<<s | ... | m[1,W-1,(1&W)?G:B]<<s |
第三行 (a+W*4)~ (a+W*6-1) | m[2,0,R]<<s | m[2,1,G]<<s | m[2,2,R]<<s | m[2,3,G]<<s | ... | m[2,W-1,(1&W)?R:G]<<s |
第四行 (a+W*6)~ (a+W*8-1) | m[3,0,G]<<s | m[3,1,B]<<s | m[3,2,G]<<s | m[3,3,B]<<s | ... | m[3,W-1,(1&W)?G:B]<<s |
... | ... | |||||
最后一行 (a+W*2*(H-1))~ (a+W*2* H-1) | m[H-1,0, o(H-1,0)]<<s | m[H-1,1, o(H-1,1)]<<s | m[H-1,2, o(H-1,2)]<<s | m[H-1,3, o(H-1,3)]<<s | ... | m[H-1,W-1, o(H-1,W-1)]<<s |
对于丽图, `a= 0xd0, s=4;`
对于仙娜, `a= 0xb0, s=4;`
对于富士胶片, `a= 0xe0, s=6;`
对于徕卡, `a= 0x90, s=8;`
对于松下, `a= 0xe0, s=8;`
对于奥林巴斯, `a=0x100, s=8;`
对于卡西欧, `a= 0xc0, s=8;`
对于美能达, `a=0x110, s=4`
就这些,返回主菜单。
7. 仙娜
0000~0001: | 'I','I' | 顺序:littleEndian("II":intel) 或 bigEndian("MM":motorola) |
0002~0003: | 0x2a,0 | tif版本 |
0004~0007: | 0x0a,0,0,0 | 长整型 &entries_1; |
0008~0009: | ?,? | |
(entries_1) 000a~000b | 5,0 | 短整型 entry_count; |
有5个条目紧随其后。
每个条目都是一个 `12_bytes_structure`,我们可以断言每个都是 `3_signed_long_array`
1 | 000c~0017 | 0x10f,?, 0x50 | &str_make |
2 | 0018~0023: | 0x100,1, W | W>=22(for irfanView) |
3 | 0024~002f | 0x101,1, H | H>=22(for dcRaw) |
4 | 0030~003b | 0xAc621,?, 0x60 | &ColorMatrix |
5 | 003c~0047 | 0x144,1, 0xB0 | &raw_data |
条目是乱序的。当然,我们可以在其中添加任何内容,我们必须更改上面的 `entry_count`。
0048~004f | 长整型 entries_2[]={0}; |
0050~005f | 字符数组 str_make[16]={"Sinar"}; |
0060~00a7 | 有符号长整型 ColorMatrix[3][6]; |
00a8~00af | ? |
00b0~ (00af+W*2*H) | 无符号短整型 raw_data[H*W]; |
就这些,返回主菜单。
9. 富士胶片
0000~0001: | 'I','I' | 顺序:littleEndian("II":intel) 或 bigEndian("MM":motorola) |
0002~0003: | 0x2a,0 | tif版本 |
0004~0007: | 0x0a,0,0,0 | 长整型 &entries_1; |
0008~0009: | ?,? | |
(entries_1) 000a~000b | 7,0 | 短整型 entry_count; |
有7个条目紧随其后。
每个条目都是一个 `12_bytes_structure`,我们可以断言每个都是 `3_signed_long_array`
1 | 000c~0017 | 0x10f,?, 0x70 | &str_make |
2 | 0018~0023: | 0x110,?, 0x80 | &str_model |
3 | 0024~002f | 0x100,1, W | W>=22(for irfanView) |
4 | 0030~003b | 0x101,1, H | H>=22(for dcRaw) |
5 | 003c~0047 | 0x102,0, 0x0E | tiff_bps |
6 | 0048~0053: | 0xAc621,?, 0x90 | &ColorMatrix |
7 | 0054~005f | 0x144,0, 0xe0 | &raw_data |
条目是乱序的。当然,我们可以在其中添加任何内容,我们必须更改上面的 `entry_count`。
0060~006f | 长整型 entries_2[]={0}; |
0070~007f | 字符数组 str_make[16]={"FujiFilm"}; |
0080~008f | 字符数组 str_model[16]={"FinePix S5100"}; |
0090~00d7 | 有符号长整型 ColorMatrix[3][6]; |
00d8~00df | ? |
00e0~ (00df+W*2*H) | 无符号短整型 raw_data[H*W]; |
就这些,返回主菜单。
10. 徕卡
0000~0001: | 'I','I' | 顺序:littleEndian("II":intel) 或 bigEndian("MM":motorola) |
0002~0003: | 0x2a,0 | tif版本 |
0004~0007: | 0x0a,0,0,0 | 长整型 &entries_1; |
0008~0009: | ?,? | |
(entries_1) 000a~000b | 7,0 | 短整型 entry_count; |
有7个条目紧随其后。
每个条目都是一个 `12_bytes_structure`,我们可以断言每个都是 `3_signed_long_array`
1 | 000c~0017 | 0x10f,?, 0x70 | &str_make |
2 | 0018~0023: | 0x110,?, 0x80 | &str_model |
3 | 0024~002f | 0x100,1, W | W>=22(for irfanView) |
4 | 0030~003b | 0x101,1, H | H>=22(for dcRaw) |
5 | 003c~0047 | 0x102,0, 0x10 | tiff_bps |
6 | 0048~0053: | 9,1, 1 | 设置滤镜(用于irfanView) |
7 | 0054~005f | 0x144,0, 0x90 | &raw_data |
条目是乱序的。当然,我们可以在其中添加任何内容,我们必须更改上面的 `entry_count`。
0060~006f | 长整型 entries_2[]={0}; |
0070~007f | 字符数组 str_make[16]={"LEICA"}; |
0080~008f | 字符数组 str_model[16]={"Digilux 2"}; |
0090~ (008f+W*2*H) | 无符号短整型 raw_data[H*W]; |
就这些,返回主菜单。
11. 松下
0000~0001: | 'I','I' | 顺序:littleEndian("II":intel) 或 bigEndian("MM":motorola) |
0002~0003: | 0x2a,0 | tif版本 |
0004~0007: | 0x0a,0,0,0 | 长整型 &entries_1; |
0008~0009: | ?,? | |
(entries_1) 000a~000b | 8,0 | 短整型 entry_count; |
有8个条目紧随其后。
每个条目都是一个 `12_bytes_structure`,我们可以断言每个都是 `3_signed_long_array`
1 | 000c~0017 | 0x10f,?, 0x70 | &str_make |
2 | 0018~0023: | 0x110,?, 0x80 | &str_model |
3 | 0024~002f | 0x100,1, W | W>=22(for irfanView) |
4 | 0030~003b | 0x101,1, H | H>=22(for dcRaw) |
5 | 003c~0047 | 0x102,0, 0x10 | tiff_bps |
6 | 0048~0053: | 9,1, 1 | 设置滤镜(用于irfanView) |
7 | 0054~005f | 0xAc621,?, 0x90 | &ColorMatrix |
8 | 0060~006b | 0x144,0, 0xe0 | &raw_data |
条目是乱序的。当然,我们可以在其中添加任何内容,我们必须更改上面的 `entry_count`。
006c~006f | 长整型 entries_2[]={0}; |
0070~007f | 字符数组 str_make[16]={"Panasonic"}; |
0080~008f | 字符数组 str_model[16]={"DMC-LC1"}; |
0090~00d7 | 有符号长整型 ColorMatrix[3][6]; |
00d8~00df | ? |
00e0~ (00df+W*2*H) | 无符号短整型 raw_data[H*W]; |
就这些,返回主菜单。
12. 奥林巴斯
0000~0001: | 'I','I' | 顺序:littleEndian("II":intel) 或 bigEndian("MM":motorola) |
0002~0003: | 0x2a,0 | tif版本 |
0004~0007: | 0x0a,0,0,0 | 长整型 &entries_1; |
0008~0009: | ?,? | |
(entries_1) 000a~000b | 8,0 | 短整型 entry_count; |
有8个条目紧随其后。
每个条目都是一个 `12_bytes_structure`,我们可以断言每个都是 `3_signed_long_array`
1 | 000c~0017 | 0x10f,?, 0x70 | &str_make |
2 | 0018~0023: | 0x110,?, 0x80 | &str_model |
3 | 0024~002f | 0x100,1, W | W>=22(for irfanView) |
4 | 0030~003b | 0x101,1, H | H>=22(for dcRaw) |
5 | 003c~0047 | 0x102,0, 0x10 | tiff_bps |
6 | 0048~0053: | 0x8769,1, 0x92 | (&exif_3)+2 |
7 | 0054~005f | 0xAc621,?, 0xb0 | &ColorMatrix |
8 | 0060~006b | 0x144,0,0x100 | &raw_data |
条目是乱序的。当然,我们可以在其中添加任何内容,我们必须更改上面的 `entry_count`。
006c~006f | 长整型 entries_2[]={0}; |
0070~007f | 字符数组 str_make[16]={"OLYMPUS"}; |
0080~008f | 字符数组 str_model[16]={"E-10"}; |
0090~00af | 无符号长整型 str_exif[8]= {0x1????,41730,8,0xA0,0x20002,0x2010100}; //单个 &entry=0xa0,其标签==41730 |
00b0~00f7 | 有符号长整型 ColorMatrix[3][6]; |
00f8~00ff | ? |
0100~ (00ff+W*2*H) | 无符号短整型 raw_data[H*W]; |
就这些,返回主菜单。
13. 卡西欧
0000~0001: | 'I','I' | 顺序:littleEndian("II":intel) 或 bigEndian("MM":motorola) |
0002~0003: | 0x2a,0 | tif版本 |
0004~0007: | 0x0a,0,0,0 | 长整型 &entries_1; |
0008~0009: | ?,? | |
(entries_1) 000a~000b | 0B,0 | 短整型 entry_count; |
有0B个条目紧随其后。
每个条目都是一个 `12_bytes_structure`,我们可以断言每个都是 `3_signed_long_array`
1 | 000c~0017 | 0x10f,?, 0xA0 | &str_make |
2 | 0018~0023: | 0x110,?, 0xb0 | &str_model |
3 | 0024~002f | 0x100,1, W | W>=22(for irfanView) |
4 | 0030~003b | 0x101,1, H | H>=22(for dcRaw) |
5 | 003c~0047 | 0x102,0, 0x10 | tiff_bps |
6 | 0048~0053: | 0x103,1, 1 | tiff_compress |
7 | 0054~005f | 0x115,1, 1 | tiff_samples |
8 | 0060~006b | 0xc612,1,0x1000000 | dng_version |
9 | 006c~0077 | 0x828e,1, 0 | 清除滤镜 |
0A | 0078~0083: | 0x828e,4,0x2030100 | 设置滤镜= 0x94949494 |
0B | 0084~008f | 0x144,0,0xc0 | &raw_data |
条目是乱序的。当然,我们可以在其中添加任何内容,我们必须更改上面的 `entry_count`。
0090~009f | 长整型 entries_2[]={0}; |
00A0~00Af | 字符数组 str_make[16]={"Casio"}; |
00b0~00bf | 字符数组 str_model[16]={"EX-P600"}; |
00c0~ (00bf+W*2*H) | 无符号短整型 raw_data[H*W]; |
就这些,返回主菜单。
8. 美能达
0000~0003: | 0,'M','R','M' | 标记 |
0004~0007: | 0,0,1,8 | 长整型 &row_data-8 |
0008~000b | 0,'P','R','D' | 标签 |
000c~000f | 0,0,0,0x18 | 长整型 pascal_len |
0010~0017: | ?...? | |
0018~0019: | H(大端) | 短整型 height |
001a~001b | W(大端) | 短整型 width |
001c~0027 | ?...? | |
0028~002b | 0,'T','T','W' | 标签 |
002c~002f | 0x7f,0xff,0xff,0xff | 长整型 len |
0030~0031: | 'M','M' | 顺序:littleEndian("II":intel) 或 bigEndian("MM":motorola) |
0032~0033: | 0,0x2a | tif版本 |
0034~0037: | 0,0,0,0x0a | 长整型 &entries_1; |
0038~0039: | ?,? | |
(entries_1) 003a~003b | 0,7 | 短整型 entry_count; |
有7个条目紧随其后。
每个条目都是一个 `12_bytes_structure`,我们可以断言每个都是 `3_bigEndian_signed_long_array`
1 | 003c~0047 | 0x10f,?, 0x70 | (&str_make)-(&order) |
2 | 0048~0053: | 0x110,?, 0x80 | (&str_model)-(&order) |
3 | 0054~005f | 0x100,1, W | W>=22(for irfanView) |
4 | 0060~006b | 0x101,1, H | H>=22(for dcRaw) |
5 | 006c~0077 | 0x102,0, 0x10 | tiff_bps |
6 | 0078~0083: | 0xAc621,?, 0x90 | (&ColorMatrix)-(&order) |
7 | 0084~008f | 0x144,0,0x110 | &raw_data |
条目是乱序的。当然,我们可以在其中添加任何内容,我们必须更改上面的 `entry_count`。
0090~009f | 长整型 entries_2[]={0}; |
00A0~00Af | 字符数组 str_make[16]={"Minolta"}; |
00b0~00bf | 字符数组 str_model[16]={"DiMAGE 5"}; |
00c0~0107 | 有符号长整型 ColorMatrix[3][6]; (大端) |
0108~010f | ? |
0110~ (010f+W*2*H) | 无符号短整型 raw_data[H*W]; (大端) |
就这些,返回主菜单。
14. 飞思
0000~0003: | 'I','I','I','I' | 顺序:intel("IIII") 或 motorola("MMMM") |
0004~0007: | 0, 'w','a','R' | 原始标志 |
0008~000b | 0x0c,0, 0, 0 | 长整型 &entries==000c |
(entries:) 000c~000f | 6,0,0,0 | 长整型 entry_count=6 |
0010~0013: | ? | |
至少有6个条目紧随其后,每个条目都是一个 `16_bytes_structure`,我们可以断言每个都是 `4_signed_long_array`
1 | 0014~0023: | 0x108, ?, 4, W | W >=22(用于irfanView) |
2 | 0024~0033: | 0x109, ?, 4, H | H >=22(用于dcRaw) |
3 | 0034~0043: | 0x10e, ?, 4, 1 | tiff_compress==1 |
4 | 0044~0053: | 0x10f, ?, 4, 0x80 | 长整型 &row_data==0080 |
5 | 0054~0063: | 0x112, ?, 4, 0 | 短整型 akey,bkey |
6 | 0064~0073: | 0x301, ?, 4, 0x74 | 长整型 &str_model==0074 |
条目是乱序的。当然,我们可以在其中添加任何内容,我们必须更改上面的 `entry_count`。
0074~007f | 字符数组 str_model[]={"H 10"} |
整型 order[2][2]={{R,G},{G,B}};
(在以下文本中, `bitMap[y][x][c]` 简写为 `m[y,x,c]` (并且我们声明“ `bitMap[y][W][c]==bitMap[y][W-1][c]`”以防边缘情况),
而 `bitMap[y][x][order[(y)&1][(x)&1]]` 简写为“ `p[y,x]`”)
文件地址 | 无符号短整型 raw_data[H*W] | |||||
第一行 0x80~ (0x80+W*2-1) | ((m[0,0,R]<<8)&0x5555) +((m[0,1,G]<<8)&0xaaaa) | ((m[0,1,G]<<8)&0x5555) +((m[0,0,R]<<8)&0xaaaa) | ((m[0,2,R]<<8)&0x5555) +((m[0,3,G]<<8)&0xaaaa) | ((m[0,3,G]<<8)&0x5555) +((m[0,2,R]<<8)&0xaaaa) | ... | ((m[0, W-1, (1&W)?R:G]<<8)&0x5555) +((m[0,(W-1)^1,(1&W)?G:R]<<8)&0xaaaa) |
第二行 (0x80+W*2)~ (0x80+W*4-1) | ((m[1,0,G]<<8)&0x5555) +((m[1,1,B]<<8)&0xaaaa) | ((m[1,1,B]<<8)&0x5555) +((m[1,0,G]<<8)&0xaaaa) | ((m[1,2,G]<<8)&0x5555) +((m[1,3,B]<<8)&0xaaaa) | ((m[1,3,B]<<8)&0x5555) +((m[1,2,G]<<8)&0xaaaa) | ... | ((m[1, W-1, (1&W)?G:B]<<8)&0x5555) +((m[1,(W-1)^1,(1&W)?B:G]<<8)&0xaaaa) |
第三行 (0x80+W*4)~ (0x80+W*6-1) | ((m[2,0,R]<<8)&0x5555) +((m[2,1,G]<<8)&0xaaaa) | ((m[2,1,G]<<8)&0x5555) +((m[2,0,R]<<8)&0xaaaa) | ((m[2,2,R]<<8)&0x5555) +((m[2,3,G]<<8)&0xaaaa) | ((m[2,3,G]<<8)&0x5555) +((m[2,2,R]<<8)&0xaaaa) | ... | ((m[2, W-1, (1&W)?R:G]<<8)&0x5555) +((m[2,(W-1)^1,(1&W)?G:R]<<8)&0xaaaa) |
第四行 (0x80+W*6)~ (0x80+W*8-1) | ((m[3,0,G]<<8)&0x5555) +((m[3,1,B]<<8)&0xaaaa) | ((m[3,1,B]<<8)&0x5555) +((m[3,0,G]<<8)&0xaaaa) | ((m[3,2,G]<<8)&0x5555) +((m[3,3,B]<<8)&0xaaaa) | ((m[3,3,B]<<8)&0x5555) +((m[3,2,G]<<8)&0xaaaa) | ... | ((m[3, W-1, (1&W)?G:B]<<8)&0x5555) +((m[3,(W-1)^1,(1&W)?B:G]<<8)&0xaaaa) |
... | ... | |||||
最后一行 (0x80+W*2*(H-1))~ (0x80+W*2* H-1) | ((p[H-1,0]<<8)&0x5555) +((p[H-1,1]<<8)&0xaaaa) | ((p[H-1,1]<<8)&0x5555) +((p[H-1,0]<<8)&0xaaaa) | ((p[H-1,2]<<8)&0x5555) +((p[H-1,3]<<8)&0xaaaa) | ((p[H-1,3]<<8)&0x5555) +((p[H-1,2]<<8)&0xaaaa) | ... | ((p[H-1, W-1 ]<<8)&0x5555) +((p[H-1,(W-1)^1]<<8)&0xaaaa) |
就这些,返回主菜单。
Using the Code
所附的zip文件包含 bmp2raw.exe 和 demo.bmp,前者可以在命令行窗口中运行,后者是一个普通的24位真彩色 `bitMap` 文件。
在命令行窗口中,我们可以
使用“ `bmp2raw.exe /e=1 demo.bmp`”自行获取一个 `maker=="Kodak"` 且 `model=="DCS760C"` 的原始文件;
或者使用“ bmp2raw.exe /e=2 demo.bmp ”获取一个 `maker=="ricoh"` 且 `model=="GR Digital"` 的原始文件;
...
或者使用“ `bmp2raw.exe /e=14 demo.bmp` ”获取一个 `maker=="Phase One"` 且 `model=="H 10"` 的原始文件。
用法是“bmp2raw [/e=enum] <src_file.bmp>”,enum的含义与本文主菜单中的相同。
bmp2raw.exe 可以(可以!=必须)用单个C文件( bmp2raw.c,43k字节)构建,该文件可以通过tinycc,borland c,visual c构建。并且命令行(如何构建它)在C文件的前面。
并且这个 bmp2raw.exe (在附件zip中)是一个独立的32位可执行文件,17k字节,可以在任何win32(64)平台上运行。在这里,我们用 32stub.asm(Thomas Pytel的pMode)构建它,所以它可以在dos下独立运行,不需要任何扩展器,如dos4g或hxDos。
为什么我们不在这里描述源代码?
哦,不! `fread()`、 `fwrite()`、填空,太无聊了……
柯达示例
unsigned char str_tif_head_littleEndian[0x0c]={
'I','I', //[0000~0001]: order:intel("II") or motorola("MM")
0x2a,0, //[0002~0003]: tif version
0x0a,0,0,0, //[0004~0007]: long &entries_1==000A
'?','?', //[0008~0009]:
'?',0, //[000a~000b]: pascal_len
};
unsigned long str_kodak_head[8][3]={
//tag len, info or ofs
{0xAc621,0x3f3f3f3f, 0x90}, //[000c~0017]: &color_matrix
{0x10f, 0x3f3f3f3f, 0x70}, //[0018~0023]: &str_make ==0070
{0x110, 0x3f3f3f3f, 0x80}, //[0024~002f]: &str_model==0080
{0x100, 1, 0x3f3f3f3f}, //[0030~003b]: width >=22(irfanView)
{0x101, 1, 0x3f3f3f3f}, //[003c~0047]: height>=22(dcRaw)
{0x102, 0, 8}, //[0048~0053]: tiff_bps
{0x103, 1, 1}, //[0054~005f]: tiff_compress
{0x144, 1, 0xe0}, //[0060~006b]: &raw_data ==00e0
};
unsigned long str_zero[4]={0, 0x3f3f3f3f,0x3f3f3f3f,0x3f3f3f3f};
char str_kodak_make[ 16]={"Kodak"}; //[0070~007f]
char str_kodak_model[16]={"DCS760C"}; //[0080~008f]
signed long str_matrix[4][6]={
{3240479,1000000, -1537151,1000000, -498535,1000000}, //means: 3.240479,
// -1.537151, -0.498535
{-969256,1000000, 1875992,1000000, 41556,1000000}, //means:-0.969256,
// 1.875992, 0.041556
{ 55648,1000000, -204043,1000000, 1057311,1000000}, //means: 0.055648,
// -0.204043, 1.057311
{0x3f3f3f3f,0x3f3f3f3f, 0x3f3f3f3f,0x3f3f3f3f, 0x3f3f3f3f,0x3f3f3f3f},
};
unsigned int bmp_width,abs_height;
unsigned int src_byte_per_line,dst_byte_per_line;
FILE *h_src=0,*h_dst;
unsigned char str_in[ MAX_BUFF];
unsigned char str_out[MAX_BUFF];
int write_kodak_8bit_fail(void)
{
unsigned int x,y;
unsigned char L,R;
unsigned long ofs;
unsigned char *p24, *p8;
int order[2][2]={{G,R},{B,G}};
//----------- write head ---------------------------
str_tif_head_littleEndian[0x0a]=8;//8 entry
str_kodak_head[3][2]=bmp_width;
str_kodak_head[4][2]=abs_height;
fwrite(str_tif_head_littleEndian, 1,
sizeof(str_tif_head_littleEndian),h_dst);//0000~000b
fwrite(str_kodak_head, 1,
sizeof(str_kodak_head),h_dst); //000c~006b
fwrite(&str_zero, 1,4,h_dst); //006c~006f
fwrite(str_kodak_make, 1,16,h_dst); //0070~007f
fwrite(str_kodak_model, 1,16,h_dst); //0080~008f
fwrite(str_matrix,1,0x50,h_dst); //0090~00df
//----------- write body ---------------------------
src_byte_per_line = (bmp_width*3+3)&0xfffc;
dst_byte_per_line=bmp_width;
ofs=0x36L+src_byte_per_line*(abs_height-1);
fseek(h_src,ofs,SEEK_SET);
for(y=0;y<abs_height;y++)
{
fread(str_in,1,src_byte_per_line,h_src);
//read y_th line from bitMap to strIn[]
p24=str_in;
p8 =str_out;
x=0;
while(x<bmp_width)
{L=p24[order[y&1][0]]; p24+=3; x++;
//src=24bit bmp, means: 3bytes/pixel
R=p24[order[y&1][1]]; p24+=3; x++;
p8[0]=L; p8[1]=R; p8+=2;
//dst=8 bit/channel
}
fwrite(str_out,1,dst_byte_per_line,h_dst);
//write y_th line from strOut[] to dcr [(00e0+y*W)~(00df+W+y*W)]
ofs-=src_byte_per_line;//file point to next line
fseek(h_src,ofs,SEEK_SET);
}
}
如你所见,太无聊了……即使我们可以在没有任何注释的情况下阅读这段源代码。
历史
- 2023年4月9日:文章提交(可使用bc4.5和vc 6.0编译)