/
image_tiff_lzw.c
148 lines (119 loc) · 3.65 KB
/
image_tiff_lzw.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
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
void lzw_dict_init(buffer_t **dict, size_t *dict_as)
{
uint8_t byte;
if (*dict_as == 0)
alloc_enough(dict, 4096, dict_as, sizeof(buffer_t), 1.);
for (int i=0; i < *dict_as; i++)
{
clear_buf(&(*dict)[i]);
if (i < 256) // set the first 256 elements to i as a one byte entry
{
byte = i;
bufwrite(&(*dict)[i], &byte, sizeof(byte));
}
}
}
void lzw_add_to_dict(buffer_t **dict, size_t *dict_as, size_t index, int append, uint8_t *data, size_t data_len, int *bpc)
{
alloc_enough(dict, index+2, dict_as, sizeof(buffer_t), 2.); // make room for the requested entry
if (append==0)
clear_buf(&(*dict)[index]);
bufwrite(&(*dict)[index], data, data_len);
}
void tiff_lzw_calc_maxcode(int bpc, int *maxcode)
{
*maxcode = ((1L<<bpc)-1) - 1;
}
void tiff_lzw_calc_bpc(int new_index, int *bpc, int *maxcode)
{
if (new_index > *maxcode)
{
(*bpc)++;
tiff_lzw_calc_maxcode(*bpc, maxcode);
}
}
void tiff_lzw_decode(uint8_t *coded, buffer_t *dec, int bytesperstrip)
{
buffer_t word={0}, outstring={0};
size_t coded_pos; // position in bits
int i=0, new_index, code, maxcode, bpc, dec_limit;
buffer_t *dict={0};
size_t dict_as=0;
bpc = 9; // starts with 9 bits per code, increases later
tiff_lzw_calc_maxcode(bpc, &maxcode); // starts at 510, which indicates where new_index triggers an increment of bpc
new_index = 258; // index at which new dict entries begin
coded_pos = 0; // bit position
dec_limit = dec->len + bytesperstrip; // we must stop decoding based on the number of decoded bytes per strip
lzw_dict_init(&dict, &dict_as);
while ((code = get_bits_in_stream(coded, coded_pos, bpc)) != 257) // while ((Code = GetNextCode()) != EoiCode)
{
coded_pos += bpc;
if (code > new_index)
{
fprintf_rl(stderr, "Out of range code %d (new_index %d)\n", code, new_index);
break;
}
if (code == 256) // if (Code == ClearCode)
{
lzw_dict_init(&dict, &dict_as); // InitializeTable();
bpc = 9;
tiff_lzw_calc_maxcode(bpc, &maxcode);
new_index = 258;
code = get_bits_in_stream(coded, coded_pos, bpc); // Code = GetNextCode();
coded_pos += bpc;
if (code == 257) // if (Code == EoiCode)
break;
append_buf(dec, &dict[code]); // WriteString(StringFromCode(Code));
clear_buf(&word);
append_buf(&word, &dict[code]); // OldCode = Code;
}
else if (code < 4096)
{
if (dict[code].len) // if (IsInTable(Code))
{
append_buf(dec, &dict[code]); // WriteString(StringFromCode(Code));
lzw_add_to_dict(&dict, &dict_as, new_index, 0, word.buf, word.len, &bpc);
lzw_add_to_dict(&dict, &dict_as, new_index, 1, dict[code].buf, 1, &bpc); // AddStringToTable
}
else
{
clear_buf(&outstring);
append_buf(&outstring, &word);
bufwrite(&outstring, word.buf, 1); // OutString = StringFromCode(OldCode) + FirstChar(StringFromCode(OldCode));
append_buf(dec, &outstring); // WriteString(OutString);
lzw_add_to_dict(&dict, &dict_as, new_index, 0, outstring.buf, outstring.len, &bpc); // AddStringToTable
}
if (dec->len >= dec_limit)
break;
new_index++;
tiff_lzw_calc_bpc(new_index, &bpc, &maxcode);
clear_buf(&word);
append_buf(&word, &dict[code]); // OldCode = Code;
}
}
free_buf(&word);
free_buf(&outstring);
for (i=0; i < dict_as; i++)
free_buf(&dict[i]);
free(dict);
}
void tiff_lzw_diff_decode(uint8_t *d, tiff_info_t info)
{
xyi_t ip;
int ic, prev;
int8_t *p8;
// 8-bit (and somehow 16-bit) version
for (ip.y=0; ip.y < info.dim.y; ip.y++)
{
for (ic=0; ic < info.chan; ic++)
{
prev = 0;
for (ip.x=0; ip.x < info.dim.x; ip.x++)
{
p8 = &d[(ip.y*info.dim.x + ip.x)*info.chan + ic];
p8[0] += prev;
prev = p8[0];
}
}
}
}