-
-
Notifications
You must be signed in to change notification settings - Fork 39
/
scan.c
112 lines (100 loc) · 2.27 KB
/
scan.c
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
#include <stdio.h>
#define MIN(a,b) (((a) < (b)) ? (a) : (b))
#define ushort UshORt
typedef unsigned char uchar;
typedef unsigned short ushort;
short order;
int width, height, bps, data_offset;
FILE *ifp;
ushort sget2 (uchar *s)
{
if (order == 0x4949) /* "II" means little-endian */
return s[0] | s[1] << 8;
else /* "MM" means big-endian */
return s[0] << 8 | s[1];
}
ushort get2()
{
uchar str[2] = { 0xff,0xff };
fread (str, 1, 2, ifp);
return sget2(str);
}
int sget4 (uchar *s)
{
if (order == 0x4949)
return s[0] | s[1] << 8 | s[2] << 16 | s[3] << 24;
else
return s[0] << 24 | s[1] << 16 | s[2] << 8 | s[3];
}
int get4()
{
uchar str[4] = { 0xff,0xff,0xff,0xff };
fread (str, 1, 4, ifp);
return sget4(str);
}
void parse_tiff_ifd()
{
unsigned entries, tag, type, len, save;
entries = get2();
if (entries > 512) return;
while (entries--) {
tag = get2();
type = get2();
len = get4();
save = ftell(ifp) + 4;
if (len * ("1112481124848"[type < 13 ? type:0]-'0') > 4)
fseek (ifp, get4(), SEEK_SET);
switch (tag) {
case 256: width = get4(); break;
case 257: height = get4(); break;
case 258: bps = get2(); break;
case 273: data_offset = get4(); break;
case 330:
fseek (ifp, get4(), SEEK_SET);
parse_tiff_ifd();
}
fseek (ifp, save, SEEK_SET);
}
}
void parse_tiff()
{
int doff;
order = get2();
if (order != 0x4949 && order != 0x4d4d) return;
get2();
while ((doff = get4())) {
fseek (ifp, doff, SEEK_SET);
parse_tiff_ifd();
}
}
int main (int argc, char **argv)
{
char buf[4096];
int size, red;
if (argc == 1) {
fprintf (stderr, "Usage: %s [options] file.nef\n", argv[0]);
return 1;
}
if (!(ifp = fopen (argv[1], "rb"))) {
perror (argv[1]);
return 1;
}
width = height = bps = 0;
parse_tiff();
if (!height) {
fprintf (stderr, "TIFF decode failed.\n");
return 1;
}
printf ("P6 %d %d %d\n", width, height, (1 << bps)-1);
size = width*height*3*bps/8;
fseek (ifp, data_offset, SEEK_SET);
while (size > 0) {
red = fread (buf, 1, MIN(size,4096), ifp);
if (bps > 8 && order == 0x4949)
swab (buf, buf, red);
fwrite (buf, 1, red, stdout);
size -= 4096;
}
fclose (ifp);
return 0;
}