74#define LOCALCOLORMAP 0x80
76#define LM_to_uint(a,b) ((((uchar_t)b)<<8)|((uchar_t)a))
78#define MAXCOLORMAPSIZE 256
79#define MAX_LWZ_BITS 12
128 int num_spill_lines_max;
129 int length[(1 << MAX_LWZ_BITS) + 1];
130 int code_and_byte[(1 << MAX_LWZ_BITS) + 1];
144static void Gif_write(DilloGif *gif,
void *Buf,
uint_t BufSize);
146static size_t Gif_process_bytes(DilloGif *gif,
const uchar_t *buf,
155 DilloGif *gif =
dMalloc(
sizeof(DilloGif));
156 _MSG(
"a_Gif_new: gif=%p\n", gif);
160 gif->version = version;
167 gif->transparent = -1;
168 gif->num_spill_lines_max = 0;
169 gif->spill_lines = NULL;
171 gif->packet_size = 0;
172 gif->ColorMap_ofs = 0;
180static void Gif_free(DilloGif *gif)
184 _MSG(
"Gif_free: gif=%p\n", gif);
187 if (gif->spill_lines != NULL) {
188 for (i = 0; i < gif->num_spill_lines_max; i++)
189 dFree(gif->spill_lines[i]);
190 dFree(gif->spill_lines);
206 Gif_close(Client->
CbData, Client);
215static void Gif_write(DilloGif *gif,
void *Buf,
uint_t BufSize)
221 if (!Buf || BufSize == 0)
224 buf = ((
uchar_t *) Buf) + gif->Start_Ofs;
225 bufsize = BufSize - gif->Start_Ofs;
227 _MSG(
"Gif_write: %u bytes\n", BufSize);
230 bytes_consumed = Gif_process_bytes(gif, buf,
bufsize, Buf);
232 if (bytes_consumed < 1)
234 gif->Start_Ofs += bytes_consumed;
236 _MSG(
"exit Gif_write, bufsize=%ld\n", (
long)
bufsize);
244 _MSG(
"Gif_close: destroy gif %p\n", gif);
260static inline size_t Gif_data_blocks(
const uchar_t *Buf,
size_t BSize)
267 if (BSize <= (
size_t)(Buf[0] + 1))
284static inline size_t Gif_do_generic_ext(
const uchar_t *Buf,
size_t BSize)
287 size_t Size = Buf[0] + 1,
296 DSize = Gif_data_blocks(Buf + Size, BSize - Size);
300 return Size <= BSize ? Size : 0;
307 Gif_do_gc_ext(DilloGif *gif,
const uchar_t *Buf,
size_t BSize)
310 size_t Size = Buf[0] + 2;
313 if (BSize < 6 || Size > BSize)
320 gif->disposal = (Buf[0] >> 2) & 0x7;
321 gif->inputFlag = (Buf[0] >> 1) & 0x1;
324 gif->delayTime = LM_to_uint(Buf[1], Buf[2]);
329 gif->transparent = Buf[3];
334#define App_Ext (0xff)
335#define Cmt_Ext (0xfe)
337#define Txt_Ext (0x01)
344static size_t Gif_do_extension(DilloGif *gif,
uint_t Label,
350 return Gif_do_gc_ext(gif, buf, BSize);
353 return Gif_data_blocks(buf, BSize);
358 return Gif_do_generic_ext(buf, BSize);
368static void Gif_lwz_init(DilloGif *gif)
370 gif->num_spill_lines_max = 1;
371 gif->spill_lines =
dMalloc(
sizeof(
uchar_t *) * gif->num_spill_lines_max);
373 gif->spill_lines[0] =
dMalloc(gif->Width);
374 gif->bits_in_window = 0;
380 gif->last_code = (1 << gif->input_code_size) + 1;
381 memset(gif->code_and_byte, 0,
382 (1 + gif->last_code) *
sizeof(gif->code_and_byte[0]));
383 gif->code_size = gif->input_code_size + 1;
393 if (gif->Flags & INTERLACE) {
406 if (gif->y >= gif->Height) {
425 if (gif->y < gif->Height)
433static void Gif_literal(DilloGif *gif,
uint_t code)
435 gif->linebuf[gif->line_index++] = code;
436 if (gif->line_index >= gif->Width) {
437 Gif_emit_line(gif, gif->linebuf);
440 gif->length[gif->last_code + 1] = 2;
441 gif->code_and_byte[gif->last_code + 1] = (code << 8);
442 gif->code_and_byte[gif->last_code] |= code;
449static void Gif_sequence(DilloGif *gif,
uint_t code)
451 uint_t o_index, o_size, orig_code;
452 uint_t sequence_length = gif->length[code];
453 uint_t line_index = gif->line_index;
455 int spill_line_index = gif->spill_line_index;
458 gif->length[gif->last_code + 1] = sequence_length + 1;
459 gif->code_and_byte[gif->last_code + 1] = (code << 8);
464 if (line_index + sequence_length <= gif->Width) {
467 o_index = line_index + sequence_length;
468 o_size = sequence_length - 1;
470 num_spill_lines = (line_index + sequence_length - 1) /
472 o_index = (line_index + sequence_length - 1) % gif->Width + 1;
473 if (num_spill_lines > gif->num_spill_lines_max) {
475 spill_line_index = gif->num_spill_lines_max;
476 gif->num_spill_lines_max = num_spill_lines << 1;
477 gif->spill_lines =
dRealloc(gif->spill_lines,
478 gif->num_spill_lines_max *
481 for (; spill_line_index < gif->num_spill_lines_max;
483 gif->spill_lines[spill_line_index] =
486 spill_line_index = num_spill_lines - 1;
487 obuf = gif->spill_lines[spill_line_index];
490 gif->line_index = o_index;
494 last_byte_ptr = obuf + o_index - 1;
499 while (sequence_length > 1) {
500 sequence_length -= o_size;
503 for (; o_size > 0 && o_index > 0; o_size--) {
504 uint_t code_and_byte = gif->code_and_byte[code];
506 _MSG(
"%d ", gif->code_and_byte[code] & 255);
508 obuf[--o_index] = code_and_byte & 255;
509 code = code_and_byte >> 8;
513 if (spill_line_index > 0) {
515 obuf = gif->spill_lines[spill_line_index];
519 o_size = sequence_length - 1;
521 o_index = gif->Width;
527 obuf[--o_index] = code;
528 gif->code_and_byte[gif->last_code] |= code;
531 if (orig_code == gif->last_code) {
532 *last_byte_ptr = code;
533 _MSG(
" fixed (%d)!", code);
538 if (gif->line_index >= gif->Width) {
539 Gif_emit_line(gif, gif->linebuf);
542 if (num_spill_lines) {
544 Gif_emit_line(gif, gif->linebuf);
545 for (spill_line_index = 0;
546 spill_line_index < num_spill_lines - (gif->line_index ? 1 : 0);
548 Gif_emit_line(gif, gif->spill_lines[spill_line_index]);
550 if (num_spill_lines) {
555 gif->spill_lines[num_spill_lines - 1] = gif->linebuf;
558 gif->spill_line_index = spill_line_index;
571static int Gif_process_code(DilloGif *gif,
uint_t code,
uint_t clear_code)
580 if (code < clear_code) {
583 Gif_literal(gif, code);
585 }
else if (code >= clear_code + 2) {
587 if (code > gif->last_code)
589 Gif_sequence(gif, code);
591 }
else if (code == clear_code) {
605static int Gif_decode(DilloGif *gif,
const uchar_t *buf,
size_t bsize)
623 packet_size = gif->packet_size;
625 bits_in_window = gif->bits_in_window;
626 code_size = gif->code_size;
627 code_mask = (1 << code_size) - 1;
628 clear_code = 1 << gif->input_code_size;
641 packet_size -= lwz_bytes;
642 for (; lwz_bytes > 0; lwz_bytes--) {
650 while (bits_in_window >= code_size) {
653 code = (
window >> (32 - bits_in_window)) & code_mask;
655 _MSG(
"code = %d, ", code);
657 bits_in_window -= code_size;
658 switch (Gif_process_code(gif, code, clear_code)) {
663 if ((gif->last_code & code_mask) == 0) {
664 if (gif->last_code == (1 << MAX_LWZ_BITS))
668 code_mask = (1 << code_size) - 1;
674 gif->last_code = clear_code + 1;
675 code_size = gif->input_code_size + 1;
676 code_mask = (1 << code_size) - 1;
682 MSG(
"Gif_decode: error!\n");
697 if (!(packet_size = *buf++)) {
704 gif->packet_size = packet_size;
706 gif->bits_in_window = bits_in_window;
707 gif->code_size = code_size;
718static int Gif_check_sig(DilloGif *gif,
const uchar_t *ibuf,
int ibsize)
723 if (memcmp(ibuf,
"GIF87a", 6) != 0 &&
724 memcmp(ibuf,
"GIF89a", 6) != 0) {
740 Gif_do_color_table(DilloGif *gif,
void *Buf,
741 const uchar_t *buf,
size_t bsize,
size_t CT_Size)
743 size_t Size = 3 * (1 << (1 + CT_Size));
749 gif->NumColors = (1 << (1 + CT_Size));
757static size_t Gif_get_descriptor(DilloGif *gif,
void *Buf,
770 if (Flags & LOCALCOLORMAP) {
771 mysize = Gif_do_color_table(
772 gif, Buf, buf + 7, (
size_t)bsize - 7, Flags & (
size_t)0x7);
780 gif->ColorResolution = (((buf[4] & 0x70) >> 3) + 1);
794static size_t Gif_do_img_desc(DilloGif *gif,
void *Buf,
795 const uchar_t *buf,
size_t bsize)
803 gif->Width = LM_to_uint(buf[4], buf[5]);
804 gif->Height = LM_to_uint(buf[6], buf[7]);
807 if (gif->Width <= 0 || gif->Height <= 0 ||
809 MSG(
"Gif_do_img_desc: suspicious image size request %u x %u\n",
810 gif->Width, gif->Height);
823 gif->Flags |= Flags & INTERLACE;
827 if (Flags & LOCALCOLORMAP) {
828 size_t LSize = Gif_do_color_table(
829 gif, Buf, buf, bsize, Flags & (
size_t)0x7);
840 gif->input_code_size = *buf++;
841 if (gif->input_code_size > 8) {
847 gif->spill_line_index = 0;
848 gif->linebuf =
dMalloc(gif->Width);
850 if (gif->ColorMap_ofs) {
852 (
uchar_t *) Buf + gif->ColorMap_ofs,
853 gif->NumColors, 256, gif->transparent);
859#define Img_Desc (0x2c)
860#define Trailer (0x3B)
885static size_t GIF_Block(DilloGif * gif,
void *Buf,
886 const uchar_t *buf,
size_t bsize)
888 size_t Size = 0, mysize;
893 while (gif->state == 2) {
906 mysize = Gif_do_extension(gif, C, buf, bsize);
923 mysize = Gif_do_img_desc(gif, Buf, buf, bsize);
939 MSG (
"gif.c::GIF_Block: Error, 0x%x found\n", *(buf-1));
963static size_t Gif_process_bytes(DilloGif *gif,
const uchar_t *ibuf,
969 switch (gif->state) {
971 mysize = Gif_check_sig(gif, ibuf, tmp_bufsize);
974 tmp_bufsize -= mysize;
980 mysize = Gif_get_descriptor(gif, Buf, ibuf, tmp_bufsize);
983 tmp_bufsize -= mysize;
992 mysize = GIF_Block(gif, Buf, ibuf, (
size_t)tmp_bufsize);
995 tmp_bufsize -= mysize;
1003 mysize = Gif_decode(gif, ibuf, (
size_t)tmp_bufsize);
1007 tmp_bufsize -= mysize;
1015 _MSG(
"Gif_process_bytes: final state %d, %ld bytes consumed\n",
1016 gif->state, (
long)(
bufsize - tmp_bufsize));
void a_Dicache_set_parms(DilloUrl *url, int version, DilloImage *Image, uint_t width, uint_t height, DilloImgType type, double gamma)
Set image's width, height & type.
void a_Dicache_close(DilloUrl *url, int version, CacheClient_t *Client)
Implement the close method of the decoding process.
void a_Dicache_write(DilloUrl *url, int version, const uchar_t *buf, uint_t Y)
Implement the write method (Write a scan line into the Dicache entry) buf: row buffer Y : row number.
void a_Dicache_set_cmap(DilloUrl *url, int version, int bg_color, const uchar_t *cmap, uint_t num_colors, int num_colors_max, int bg_index)
Implement the set_cmap method for the Image.
void * dMalloc(size_t size)
void * dRealloc(void *mem, size_t size)
static void error(char *msg)
static Fl_Window * window
Data structure for cache clients.
void * CbData
Client function data.
uint_t BufSize
Valid size of cache-data.
void * Buf
Pointer to cache-data.
int32_t bg_color
Background color.