65.9K
CodeProject 正在变化。 阅读更多。
Home

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

starIconstarIconstarIconstarIconstarIcon

5.00/5 (1投票)

2023年4月23日

CPOL

18分钟阅读

viewsIcon

7594

downloadIcon

82

某些DCR文件的格式/数据结构

引言

本文描述了某些DCR(数码相机原始文件)文件的格式/数据结构。
通过此数据结构,我们可以将24位(真彩色)的 位图 文件转换为 dcr 文件。

应用场景

Dave Coffin的 dcraw.c 可以解码许多原始照片。如果我们获得他的许可,就可以将代码移植到我们的项目中。但是,如何获得大量的原始照片来测试我们的代码呢?

  1. 我们可以购买许多不同类型的相机(太费钱)。
  2. 我们可以等待摄影师上传的非jpeg格式、非png格式的原始照片(太费时)。
  3. 我们可以使用本文,通过我们自己的小型 `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.exedemo.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编译)
© . All rights reserved.