Mercurial > libavcodec.hg
comparison gifdec.c @ 4080:f426c81afc9e libavcodec
LZW decoder as separate module plus TIFF LZW support
author | kostya |
---|---|
date | Thu, 26 Oct 2006 04:15:48 +0000 |
parents | e46fa0f9192a |
children | a8e3a116b41f |
comparison
equal
deleted
inserted
replaced
4079:00a0b18cfb92 | 4080:f426c81afc9e |
---|---|
22 | 22 |
23 //#define DEBUG | 23 //#define DEBUG |
24 | 24 |
25 #include "avcodec.h" | 25 #include "avcodec.h" |
26 #include "bytestream.h" | 26 #include "bytestream.h" |
27 | 27 #include "lzw.h" |
28 #define MAXBITS 12 | |
29 #define SIZTABLE (1<<MAXBITS) | |
30 | 28 |
31 #define GCE_DISPOSAL_NONE 0 | 29 #define GCE_DISPOSAL_NONE 0 |
32 #define GCE_DISPOSAL_INPLACE 1 | 30 #define GCE_DISPOSAL_INPLACE 1 |
33 #define GCE_DISPOSAL_BACKGROUND 2 | 31 #define GCE_DISPOSAL_BACKGROUND 2 |
34 #define GCE_DISPOSAL_RESTORE 3 | 32 #define GCE_DISPOSAL_RESTORE 3 |
48 /* delay during which the frame is shown */ | 46 /* delay during which the frame is shown */ |
49 int gce_delay; | 47 int gce_delay; |
50 | 48 |
51 /* LZW compatible decoder */ | 49 /* LZW compatible decoder */ |
52 uint8_t *bytestream; | 50 uint8_t *bytestream; |
53 int eob_reached; | 51 LZWState *lzw; |
54 uint8_t *pbuf, *ebuf; | |
55 int bbits; | |
56 unsigned int bbuf; | |
57 | |
58 int cursize; /* The current code size */ | |
59 int curmask; | |
60 int codesize; | |
61 int clear_code; | |
62 int end_code; | |
63 int newcodes; /* First available code */ | |
64 int top_slot; /* Highest code for current size */ | |
65 int slot; /* Last read code */ | |
66 int fc, oc; | |
67 uint8_t *sp; | |
68 uint8_t stack[SIZTABLE]; | |
69 uint8_t suffix[SIZTABLE]; | |
70 uint16_t prefix[SIZTABLE]; | |
71 | 52 |
72 /* aux buffers */ | 53 /* aux buffers */ |
73 uint8_t global_palette[256 * 3]; | 54 uint8_t global_palette[256 * 3]; |
74 uint8_t local_palette[256 * 3]; | 55 uint8_t local_palette[256 * 3]; |
75 uint8_t buf[256]; | |
76 } GifState; | 56 } GifState; |
77 | 57 |
78 static const uint8_t gif87a_sig[6] = "GIF87a"; | 58 static const uint8_t gif87a_sig[6] = "GIF87a"; |
79 static const uint8_t gif89a_sig[6] = "GIF89a"; | 59 static const uint8_t gif89a_sig[6] = "GIF89a"; |
80 | |
81 static const uint16_t mask[17] = | |
82 { | |
83 0x0000, 0x0001, 0x0003, 0x0007, | |
84 0x000F, 0x001F, 0x003F, 0x007F, | |
85 0x00FF, 0x01FF, 0x03FF, 0x07FF, | |
86 0x0FFF, 0x1FFF, 0x3FFF, 0x7FFF, 0xFFFF | |
87 }; | |
88 | |
89 static void GLZWDecodeInit(GifState * s, int csize) | |
90 { | |
91 /* read buffer */ | |
92 s->eob_reached = 0; | |
93 s->pbuf = s->buf; | |
94 s->ebuf = s->buf; | |
95 s->bbuf = 0; | |
96 s->bbits = 0; | |
97 | |
98 /* decoder */ | |
99 s->codesize = csize; | |
100 s->cursize = s->codesize + 1; | |
101 s->curmask = mask[s->cursize]; | |
102 s->top_slot = 1 << s->cursize; | |
103 s->clear_code = 1 << s->codesize; | |
104 s->end_code = s->clear_code + 1; | |
105 s->slot = s->newcodes = s->clear_code + 2; | |
106 s->oc = s->fc = 0; | |
107 s->sp = s->stack; | |
108 } | |
109 | |
110 /* XXX: optimize */ | |
111 static inline int GetCode(GifState * s) | |
112 { | |
113 int c, sizbuf; | |
114 uint8_t *ptr; | |
115 | |
116 while (s->bbits < s->cursize) { | |
117 ptr = s->pbuf; | |
118 if (ptr >= s->ebuf) { | |
119 if (!s->eob_reached) { | |
120 sizbuf = bytestream_get_byte(&s->bytestream); | |
121 s->ebuf = s->buf + sizbuf; | |
122 s->pbuf = s->buf; | |
123 if (sizbuf > 0) { | |
124 bytestream_get_buffer(&s->bytestream, s->buf, sizbuf); | |
125 } else { | |
126 s->eob_reached = 1; | |
127 } | |
128 } | |
129 ptr = s->pbuf; | |
130 } | |
131 s->bbuf |= ptr[0] << s->bbits; | |
132 ptr++; | |
133 s->pbuf = ptr; | |
134 s->bbits += 8; | |
135 } | |
136 c = s->bbuf & s->curmask; | |
137 s->bbuf >>= s->cursize; | |
138 s->bbits -= s->cursize; | |
139 return c; | |
140 } | |
141 | |
142 /* NOTE: the algorithm here is inspired from the LZW GIF decoder | |
143 written by Steven A. Bennett in 1987. */ | |
144 /* return the number of byte decoded */ | |
145 static int GLZWDecode(GifState * s, uint8_t * buf, int len) | |
146 { | |
147 int l, c, code, oc, fc; | |
148 uint8_t *sp; | |
149 | |
150 if (s->end_code < 0) | |
151 return 0; | |
152 | |
153 l = len; | |
154 sp = s->sp; | |
155 oc = s->oc; | |
156 fc = s->fc; | |
157 | |
158 while (sp > s->stack) { | |
159 *buf++ = *(--sp); | |
160 if ((--l) == 0) | |
161 goto the_end; | |
162 } | |
163 | |
164 for (;;) { | |
165 c = GetCode(s); | |
166 if (c == s->end_code) { | |
167 s->end_code = -1; | |
168 break; | |
169 } else if (c == s->clear_code) { | |
170 s->cursize = s->codesize + 1; | |
171 s->curmask = mask[s->cursize]; | |
172 s->slot = s->newcodes; | |
173 s->top_slot = 1 << s->cursize; | |
174 while ((c = GetCode(s)) == s->clear_code); | |
175 if (c == s->end_code) { | |
176 s->end_code = -1; | |
177 break; | |
178 } | |
179 /* test error */ | |
180 if (c >= s->slot) | |
181 c = 0; | |
182 fc = oc = c; | |
183 *buf++ = c; | |
184 if ((--l) == 0) | |
185 break; | |
186 } else { | |
187 code = c; | |
188 if (code >= s->slot) { | |
189 *sp++ = fc; | |
190 code = oc; | |
191 } | |
192 while (code >= s->newcodes) { | |
193 *sp++ = s->suffix[code]; | |
194 code = s->prefix[code]; | |
195 } | |
196 *sp++ = code; | |
197 if (s->slot < s->top_slot) { | |
198 s->suffix[s->slot] = fc = code; | |
199 s->prefix[s->slot++] = oc; | |
200 oc = c; | |
201 } | |
202 if (s->slot >= s->top_slot) { | |
203 if (s->cursize < MAXBITS) { | |
204 s->top_slot <<= 1; | |
205 s->curmask = mask[++s->cursize]; | |
206 } | |
207 } | |
208 while (sp > s->stack) { | |
209 *buf++ = *(--sp); | |
210 if ((--l) == 0) | |
211 goto the_end; | |
212 } | |
213 } | |
214 } | |
215 the_end: | |
216 s->sp = sp; | |
217 s->oc = oc; | |
218 s->fc = fc; | |
219 return len - l; | |
220 } | |
221 | 60 |
222 static int gif_read_image(GifState *s) | 61 static int gif_read_image(GifState *s) |
223 { | 62 { |
224 int left, top, width, height, bits_per_pixel, code_size, flags; | 63 int left, top, width, height, bits_per_pixel, code_size, flags; |
225 int is_interleaved, has_local_palette, y, pass, y1, linesize, n, i; | 64 int is_interleaved, has_local_palette, y, pass, y1, linesize, n, i; |
265 s->image_palette[s->transparent_color_index] = 0; | 104 s->image_palette[s->transparent_color_index] = 0; |
266 line = NULL; | 105 line = NULL; |
267 | 106 |
268 /* now get the image data */ | 107 /* now get the image data */ |
269 code_size = bytestream_get_byte(&s->bytestream); | 108 code_size = bytestream_get_byte(&s->bytestream); |
270 GLZWDecodeInit(s, code_size); | 109 //TODO: add proper data size |
110 ff_lzw_decode_init(s->lzw, code_size, s->bytestream, 0, FF_LZW_GIF); | |
271 | 111 |
272 /* read all the image */ | 112 /* read all the image */ |
273 linesize = s->picture.linesize[0]; | 113 linesize = s->picture.linesize[0]; |
274 ptr1 = s->picture.data[0] + top * linesize + (left * 3); | 114 ptr1 = s->picture.data[0] + top * linesize + (left * 3); |
275 ptr = ptr1; | 115 ptr = ptr1; |
276 pass = 0; | 116 pass = 0; |
277 y1 = 0; | 117 y1 = 0; |
278 for (y = 0; y < height; y++) { | 118 for (y = 0; y < height; y++) { |
279 GLZWDecode(s, ptr, width); | 119 ff_lzw_decode(s->lzw, ptr, width); |
280 if (is_interleaved) { | 120 if (is_interleaved) { |
281 switch(pass) { | 121 switch(pass) { |
282 default: | 122 default: |
283 case 0: | 123 case 0: |
284 case 1: | 124 case 1: |
312 } | 152 } |
313 } | 153 } |
314 av_free(line); | 154 av_free(line); |
315 | 155 |
316 /* read the garbage data until end marker is found */ | 156 /* read the garbage data until end marker is found */ |
317 while (!s->eob_reached) | 157 ff_lzw_decode_tail(s->lzw); |
318 GetCode(s); | 158 s->bytestream = ff_lzw_cur_ptr(s->lzw); |
319 return 0; | 159 return 0; |
320 } | 160 } |
321 | 161 |
322 static int gif_read_extension(GifState *s) | 162 static int gif_read_extension(GifState *s) |
323 { | 163 { |
443 GifState *s = avctx->priv_data; | 283 GifState *s = avctx->priv_data; |
444 | 284 |
445 avcodec_get_frame_defaults(&s->picture); | 285 avcodec_get_frame_defaults(&s->picture); |
446 avctx->coded_frame= &s->picture; | 286 avctx->coded_frame= &s->picture; |
447 s->picture.data[0] = NULL; | 287 s->picture.data[0] = NULL; |
288 ff_lzw_decode_open(&s->lzw); | |
448 return 0; | 289 return 0; |
449 } | 290 } |
450 | 291 |
451 static int gif_decode_frame(AVCodecContext *avctx, void *data, int *data_size, uint8_t *buf, int buf_size) | 292 static int gif_decode_frame(AVCodecContext *avctx, void *data, int *data_size, uint8_t *buf, int buf_size) |
452 { | 293 { |
481 | 322 |
482 static int gif_decode_close(AVCodecContext *avctx) | 323 static int gif_decode_close(AVCodecContext *avctx) |
483 { | 324 { |
484 GifState *s = avctx->priv_data; | 325 GifState *s = avctx->priv_data; |
485 | 326 |
327 ff_lzw_decode_close(&s->lzw); | |
486 if(s->picture.data[0]) | 328 if(s->picture.data[0]) |
487 avctx->release_buffer(avctx, &s->picture); | 329 avctx->release_buffer(avctx, &s->picture); |
488 return 0; | 330 return 0; |
489 } | 331 } |
490 | 332 |