annotate src/gif.c @ 2104:3e7e5395f0bc

non-ASCII keybindings Alexander Voigt has kindly done some testing, and it seems that this makes bindings to most keys on a German keyboard possible -- except those that need AltGr don't work yet.
author corvid <corvid@lavabit.com>
date Thu, 23 Jun 2011 19:24:11 +0000
parents 796ee3ef6426
children
rev   line source
0
6ee11bf9e3ea Initial revision
jcid
parents:
diff changeset
1 /*
6ee11bf9e3ea Initial revision
jcid
parents:
diff changeset
2 * File: gif.c
6ee11bf9e3ea Initial revision
jcid
parents:
diff changeset
3 *
6ee11bf9e3ea Initial revision
jcid
parents:
diff changeset
4 * Copyright (C) 1997 Raph Levien <raph@acm.org>
35
d9e7b35430de Updated copyright lines
jcid
parents: 0
diff changeset
5 * Copyright (C) 2000-2007 Jorge Arellano Cid <jcid@dillo.org>
0
6ee11bf9e3ea Initial revision
jcid
parents:
diff changeset
6 *
6ee11bf9e3ea Initial revision
jcid
parents:
diff changeset
7 * This program is free software; you can redistribute it and/or modify
6ee11bf9e3ea Initial revision
jcid
parents:
diff changeset
8 * it under the terms of the GNU General Public License as published by
6ee11bf9e3ea Initial revision
jcid
parents:
diff changeset
9 * the Free Software Foundation; either version 3 of the License, or
6ee11bf9e3ea Initial revision
jcid
parents:
diff changeset
10 * (at your option) any later version.
6ee11bf9e3ea Initial revision
jcid
parents:
diff changeset
11 */
6ee11bf9e3ea Initial revision
jcid
parents:
diff changeset
12
6ee11bf9e3ea Initial revision
jcid
parents:
diff changeset
13 /*
6ee11bf9e3ea Initial revision
jcid
parents:
diff changeset
14 * The GIF decoder for dillo. It is responsible for decoding GIF data
6ee11bf9e3ea Initial revision
jcid
parents:
diff changeset
15 * and transferring it to the dicache.
6ee11bf9e3ea Initial revision
jcid
parents:
diff changeset
16 */
6ee11bf9e3ea Initial revision
jcid
parents:
diff changeset
17
6ee11bf9e3ea Initial revision
jcid
parents:
diff changeset
18
6ee11bf9e3ea Initial revision
jcid
parents:
diff changeset
19 /* Notes 13 Oct 1997 --RLL
6ee11bf9e3ea Initial revision
jcid
parents:
diff changeset
20 *
6ee11bf9e3ea Initial revision
jcid
parents:
diff changeset
21 * Today, just for the hell of it, I implemented a new decoder from
6ee11bf9e3ea Initial revision
jcid
parents:
diff changeset
22 * scratch. It's oriented around pushing bytes, while the old decoder
6ee11bf9e3ea Initial revision
jcid
parents:
diff changeset
23 * was based around reads which may suspend. There were basically
6ee11bf9e3ea Initial revision
jcid
parents:
diff changeset
24 * three motivations.
6ee11bf9e3ea Initial revision
jcid
parents:
diff changeset
25 *
6ee11bf9e3ea Initial revision
jcid
parents:
diff changeset
26 * 1. To increase the speed.
6ee11bf9e3ea Initial revision
jcid
parents:
diff changeset
27 *
6ee11bf9e3ea Initial revision
jcid
parents:
diff changeset
28 * 2. To fix some bugs I had seen, most likely due to suspension.
6ee11bf9e3ea Initial revision
jcid
parents:
diff changeset
29 *
6ee11bf9e3ea Initial revision
jcid
parents:
diff changeset
30 * 3. To make sure that the code had no buffer overruns or the like.
6ee11bf9e3ea Initial revision
jcid
parents:
diff changeset
31 *
6ee11bf9e3ea Initial revision
jcid
parents:
diff changeset
32 * 4. So that the code could be released under a freer license.
6ee11bf9e3ea Initial revision
jcid
parents:
diff changeset
33 *
6ee11bf9e3ea Initial revision
jcid
parents:
diff changeset
34 * Let's see how we did on speed. I used a large image for testing
6ee11bf9e3ea Initial revision
jcid
parents:
diff changeset
35 * (fvwm95-2.gif).
6ee11bf9e3ea Initial revision
jcid
parents:
diff changeset
36 *
6ee11bf9e3ea Initial revision
jcid
parents:
diff changeset
37 * The old decoder spent a total of about 1.04 seconds decoding the
6ee11bf9e3ea Initial revision
jcid
parents:
diff changeset
38 * image. Another .58 seconds went into Image_line, almost
6ee11bf9e3ea Initial revision
jcid
parents:
diff changeset
39 * entirely conversion from colormap to RGB.
6ee11bf9e3ea Initial revision
jcid
parents:
diff changeset
40 *
6ee11bf9e3ea Initial revision
jcid
parents:
diff changeset
41 * The new decoder spent a total of 0.46 seconds decoding the image.
6ee11bf9e3ea Initial revision
jcid
parents:
diff changeset
42 * However, the time for Image_line went up to 1.01 seconds.
6ee11bf9e3ea Initial revision
jcid
parents:
diff changeset
43 * Thus, even though the decoder seems to be about twice as fast,
6ee11bf9e3ea Initial revision
jcid
parents:
diff changeset
44 * the net gain is pretty minimal. Could this be because of cache
6ee11bf9e3ea Initial revision
jcid
parents:
diff changeset
45 * effects?
6ee11bf9e3ea Initial revision
jcid
parents:
diff changeset
46 *
6ee11bf9e3ea Initial revision
jcid
parents:
diff changeset
47 * Lessons learned: The first, which I keep learning over and over, is
6ee11bf9e3ea Initial revision
jcid
parents:
diff changeset
48 * not to try to optimize too much. It doesn't work. Just keep things
6ee11bf9e3ea Initial revision
jcid
parents:
diff changeset
49 * simple.
6ee11bf9e3ea Initial revision
jcid
parents:
diff changeset
50 *
6ee11bf9e3ea Initial revision
jcid
parents:
diff changeset
51 * Second, it seems that the colormap to RGB conversion is really a
6ee11bf9e3ea Initial revision
jcid
parents:
diff changeset
52 * significant part of the overall time. It's possible that going
6ee11bf9e3ea Initial revision
jcid
parents:
diff changeset
53 * directly to 16 bits would help, but that's optimization again :)
6ee11bf9e3ea Initial revision
jcid
parents:
diff changeset
54 */
6ee11bf9e3ea Initial revision
jcid
parents:
diff changeset
55
6ee11bf9e3ea Initial revision
jcid
parents:
diff changeset
56
368
2242da885677 - s/todo:/TODO:/g
jcid
parents: 359
diff changeset
57 /* TODO:
0
6ee11bf9e3ea Initial revision
jcid
parents:
diff changeset
58 * + Make sure to handle error cases gracefully (including aborting the
6ee11bf9e3ea Initial revision
jcid
parents:
diff changeset
59 * connection, if necessary).
6ee11bf9e3ea Initial revision
jcid
parents:
diff changeset
60 */
6ee11bf9e3ea Initial revision
jcid
parents:
diff changeset
61
6ee11bf9e3ea Initial revision
jcid
parents:
diff changeset
62 #include <config.h>
6ee11bf9e3ea Initial revision
jcid
parents:
diff changeset
63 #ifdef ENABLE_GIF
6ee11bf9e3ea Initial revision
jcid
parents:
diff changeset
64
6ee11bf9e3ea Initial revision
jcid
parents:
diff changeset
65 #include <stdio.h> /* for sprintf */
6ee11bf9e3ea Initial revision
jcid
parents:
diff changeset
66 #include <string.h> /* for memcpy and memmove */
6ee11bf9e3ea Initial revision
jcid
parents:
diff changeset
67
6ee11bf9e3ea Initial revision
jcid
parents:
diff changeset
68 #include "msg.h"
6ee11bf9e3ea Initial revision
jcid
parents:
diff changeset
69 #include "image.hh"
6ee11bf9e3ea Initial revision
jcid
parents:
diff changeset
70 #include "cache.h"
6ee11bf9e3ea Initial revision
jcid
parents:
diff changeset
71 #include "dicache.h"
6ee11bf9e3ea Initial revision
jcid
parents:
diff changeset
72
6ee11bf9e3ea Initial revision
jcid
parents:
diff changeset
73 #define INTERLACE 0x40
6ee11bf9e3ea Initial revision
jcid
parents:
diff changeset
74 #define LOCALCOLORMAP 0x80
6ee11bf9e3ea Initial revision
jcid
parents:
diff changeset
75
6ee11bf9e3ea Initial revision
jcid
parents:
diff changeset
76 #define LM_to_uint(a,b) ((((uchar_t)b)<<8)|((uchar_t)a))
6ee11bf9e3ea Initial revision
jcid
parents:
diff changeset
77
6ee11bf9e3ea Initial revision
jcid
parents:
diff changeset
78 #define MAXCOLORMAPSIZE 256
6ee11bf9e3ea Initial revision
jcid
parents:
diff changeset
79 #define MAX_LWZ_BITS 12
6ee11bf9e3ea Initial revision
jcid
parents:
diff changeset
80
6ee11bf9e3ea Initial revision
jcid
parents:
diff changeset
81
6ee11bf9e3ea Initial revision
jcid
parents:
diff changeset
82 typedef struct _DilloGif {
6ee11bf9e3ea Initial revision
jcid
parents:
diff changeset
83 DilloImage *Image;
6ee11bf9e3ea Initial revision
jcid
parents:
diff changeset
84 DilloUrl *url;
6ee11bf9e3ea Initial revision
jcid
parents:
diff changeset
85 int version;
6ee11bf9e3ea Initial revision
jcid
parents:
diff changeset
86
6ee11bf9e3ea Initial revision
jcid
parents:
diff changeset
87 int state;
6ee11bf9e3ea Initial revision
jcid
parents:
diff changeset
88 size_t Start_Ofs;
6ee11bf9e3ea Initial revision
jcid
parents:
diff changeset
89 uint_t Flags;
6ee11bf9e3ea Initial revision
jcid
parents:
diff changeset
90
6ee11bf9e3ea Initial revision
jcid
parents:
diff changeset
91 uchar_t input_code_size;
6ee11bf9e3ea Initial revision
jcid
parents:
diff changeset
92 uchar_t *linebuf;
6ee11bf9e3ea Initial revision
jcid
parents:
diff changeset
93 int pass;
6ee11bf9e3ea Initial revision
jcid
parents:
diff changeset
94
6ee11bf9e3ea Initial revision
jcid
parents:
diff changeset
95 uint_t y;
6ee11bf9e3ea Initial revision
jcid
parents:
diff changeset
96
6ee11bf9e3ea Initial revision
jcid
parents:
diff changeset
97 /* state for lwz_read_byte */
6ee11bf9e3ea Initial revision
jcid
parents:
diff changeset
98 int code_size;
6ee11bf9e3ea Initial revision
jcid
parents:
diff changeset
99
6ee11bf9e3ea Initial revision
jcid
parents:
diff changeset
100 /* The original GifScreen from giftopnm */
6ee11bf9e3ea Initial revision
jcid
parents:
diff changeset
101 uint_t Width;
6ee11bf9e3ea Initial revision
jcid
parents:
diff changeset
102 uint_t Height;
6ee11bf9e3ea Initial revision
jcid
parents:
diff changeset
103 size_t ColorMap_ofs;
6ee11bf9e3ea Initial revision
jcid
parents:
diff changeset
104 uint_t ColorResolution;
6ee11bf9e3ea Initial revision
jcid
parents:
diff changeset
105 uint_t NumColors;
6ee11bf9e3ea Initial revision
jcid
parents:
diff changeset
106 int Background;
6ee11bf9e3ea Initial revision
jcid
parents:
diff changeset
107 uint_t spill_line_index;
6ee11bf9e3ea Initial revision
jcid
parents:
diff changeset
108 #if 0
6ee11bf9e3ea Initial revision
jcid
parents:
diff changeset
109 uint_t AspectRatio; /* AspectRatio (not used) */
6ee11bf9e3ea Initial revision
jcid
parents:
diff changeset
110 #endif
6ee11bf9e3ea Initial revision
jcid
parents:
diff changeset
111
6ee11bf9e3ea Initial revision
jcid
parents:
diff changeset
112 /* Gif89 extensions */
6ee11bf9e3ea Initial revision
jcid
parents:
diff changeset
113 int transparent;
6ee11bf9e3ea Initial revision
jcid
parents:
diff changeset
114 #if 0
6ee11bf9e3ea Initial revision
jcid
parents:
diff changeset
115 /* None are used: */
6ee11bf9e3ea Initial revision
jcid
parents:
diff changeset
116 int delayTime;
6ee11bf9e3ea Initial revision
jcid
parents:
diff changeset
117 int inputFlag;
6ee11bf9e3ea Initial revision
jcid
parents:
diff changeset
118 int disposal;
6ee11bf9e3ea Initial revision
jcid
parents:
diff changeset
119 #endif
6ee11bf9e3ea Initial revision
jcid
parents:
diff changeset
120
6ee11bf9e3ea Initial revision
jcid
parents:
diff changeset
121 /* state for the new push-oriented decoder */
6ee11bf9e3ea Initial revision
jcid
parents:
diff changeset
122 int packet_size; /* The amount of the data block left to process */
6ee11bf9e3ea Initial revision
jcid
parents:
diff changeset
123 uint_t window;
6ee11bf9e3ea Initial revision
jcid
parents:
diff changeset
124 int bits_in_window;
6ee11bf9e3ea Initial revision
jcid
parents:
diff changeset
125 uint_t last_code; /* Last "compressed" code in the look up table */
6ee11bf9e3ea Initial revision
jcid
parents:
diff changeset
126 uint_t line_index;
6ee11bf9e3ea Initial revision
jcid
parents:
diff changeset
127 uchar_t **spill_lines;
6ee11bf9e3ea Initial revision
jcid
parents:
diff changeset
128 int num_spill_lines_max;
6ee11bf9e3ea Initial revision
jcid
parents:
diff changeset
129 int length[(1 << MAX_LWZ_BITS) + 1];
6ee11bf9e3ea Initial revision
jcid
parents:
diff changeset
130 int code_and_byte[(1 << MAX_LWZ_BITS) + 1];
6ee11bf9e3ea Initial revision
jcid
parents:
diff changeset
131 } DilloGif;
6ee11bf9e3ea Initial revision
jcid
parents:
diff changeset
132
6ee11bf9e3ea Initial revision
jcid
parents:
diff changeset
133 /* Some invariants:
6ee11bf9e3ea Initial revision
jcid
parents:
diff changeset
134 *
6ee11bf9e3ea Initial revision
jcid
parents:
diff changeset
135 * last_code <= code_mask
6ee11bf9e3ea Initial revision
jcid
parents:
diff changeset
136 *
6ee11bf9e3ea Initial revision
jcid
parents:
diff changeset
137 * code_and_byte is stored packed: (code << 8) | byte
6ee11bf9e3ea Initial revision
jcid
parents:
diff changeset
138 */
6ee11bf9e3ea Initial revision
jcid
parents:
diff changeset
139
6ee11bf9e3ea Initial revision
jcid
parents:
diff changeset
140
6ee11bf9e3ea Initial revision
jcid
parents:
diff changeset
141 /*
6ee11bf9e3ea Initial revision
jcid
parents:
diff changeset
142 * Forward declarations
6ee11bf9e3ea Initial revision
jcid
parents:
diff changeset
143 */
6ee11bf9e3ea Initial revision
jcid
parents:
diff changeset
144 static void Gif_write(DilloGif *gif, void *Buf, uint_t BufSize);
6ee11bf9e3ea Initial revision
jcid
parents:
diff changeset
145 static void Gif_close(DilloGif *gif, CacheClient_t *Client);
6ee11bf9e3ea Initial revision
jcid
parents:
diff changeset
146 static size_t Gif_process_bytes(DilloGif *gif, const uchar_t *buf,
6ee11bf9e3ea Initial revision
jcid
parents:
diff changeset
147 int bufsize, void *Buf);
6ee11bf9e3ea Initial revision
jcid
parents:
diff changeset
148
6ee11bf9e3ea Initial revision
jcid
parents:
diff changeset
149
6ee11bf9e3ea Initial revision
jcid
parents:
diff changeset
150 /*
6ee11bf9e3ea Initial revision
jcid
parents:
diff changeset
151 * Create a new gif structure for decoding a gif into a RGB buffer
6ee11bf9e3ea Initial revision
jcid
parents:
diff changeset
152 */
874
6828b4d19d69 Set dicache as MIME dispatcher for image/{gif,jpg,png}. +refactor and cleanups
Jorge Arellano Cid <jcid@dillo.org>
parents: 768
diff changeset
153 void *a_Gif_new(DilloImage *Image, DilloUrl *url, int version)
0
6ee11bf9e3ea Initial revision
jcid
parents:
diff changeset
154 {
6ee11bf9e3ea Initial revision
jcid
parents:
diff changeset
155 DilloGif *gif = dMalloc(sizeof(DilloGif));
1094
7401c51915da Silence the last image-debugging messages
Jorge Arellano Cid <jcid@dillo.org>
parents: 1092
diff changeset
156 _MSG("a_Gif_new: gif=%p\n", gif);
0
6ee11bf9e3ea Initial revision
jcid
parents:
diff changeset
157
6ee11bf9e3ea Initial revision
jcid
parents:
diff changeset
158 gif->Image = Image;
6ee11bf9e3ea Initial revision
jcid
parents:
diff changeset
159 gif->url = url;
6ee11bf9e3ea Initial revision
jcid
parents:
diff changeset
160 gif->version = version;
6ee11bf9e3ea Initial revision
jcid
parents:
diff changeset
161
6ee11bf9e3ea Initial revision
jcid
parents:
diff changeset
162 gif->Flags = 0;
6ee11bf9e3ea Initial revision
jcid
parents:
diff changeset
163 gif->state = 0;
6ee11bf9e3ea Initial revision
jcid
parents:
diff changeset
164 gif->Start_Ofs = 0;
6ee11bf9e3ea Initial revision
jcid
parents:
diff changeset
165 gif->linebuf = NULL;
6ee11bf9e3ea Initial revision
jcid
parents:
diff changeset
166 gif->Background = -1;
6ee11bf9e3ea Initial revision
jcid
parents:
diff changeset
167 gif->transparent = -1;
6ee11bf9e3ea Initial revision
jcid
parents:
diff changeset
168 gif->num_spill_lines_max = 0;
6ee11bf9e3ea Initial revision
jcid
parents:
diff changeset
169 gif->spill_lines = NULL;
6ee11bf9e3ea Initial revision
jcid
parents:
diff changeset
170 gif->window = 0;
6ee11bf9e3ea Initial revision
jcid
parents:
diff changeset
171 gif->packet_size = 0;
6ee11bf9e3ea Initial revision
jcid
parents:
diff changeset
172 gif->ColorMap_ofs = 0;
6ee11bf9e3ea Initial revision
jcid
parents:
diff changeset
173
6ee11bf9e3ea Initial revision
jcid
parents:
diff changeset
174 return gif;
6ee11bf9e3ea Initial revision
jcid
parents:
diff changeset
175 }
6ee11bf9e3ea Initial revision
jcid
parents:
diff changeset
176
6ee11bf9e3ea Initial revision
jcid
parents:
diff changeset
177 /*
1085
d6767b7bdf93 Fix a memory leak when stopping an image-decoding process
Jorge Arellano Cid <jcid@dillo.org>
parents: 1050
diff changeset
178 * Free the gif-decoding data structure.
d6767b7bdf93 Fix a memory leak when stopping an image-decoding process
Jorge Arellano Cid <jcid@dillo.org>
parents: 1050
diff changeset
179 */
d6767b7bdf93 Fix a memory leak when stopping an image-decoding process
Jorge Arellano Cid <jcid@dillo.org>
parents: 1050
diff changeset
180 static void Gif_free(DilloGif *gif)
d6767b7bdf93 Fix a memory leak when stopping an image-decoding process
Jorge Arellano Cid <jcid@dillo.org>
parents: 1050
diff changeset
181 {
d6767b7bdf93 Fix a memory leak when stopping an image-decoding process
Jorge Arellano Cid <jcid@dillo.org>
parents: 1050
diff changeset
182 int i;
d6767b7bdf93 Fix a memory leak when stopping an image-decoding process
Jorge Arellano Cid <jcid@dillo.org>
parents: 1050
diff changeset
183
1094
7401c51915da Silence the last image-debugging messages
Jorge Arellano Cid <jcid@dillo.org>
parents: 1092
diff changeset
184 _MSG("Gif_free: gif=%p\n", gif);
1085
d6767b7bdf93 Fix a memory leak when stopping an image-decoding process
Jorge Arellano Cid <jcid@dillo.org>
parents: 1050
diff changeset
185
d6767b7bdf93 Fix a memory leak when stopping an image-decoding process
Jorge Arellano Cid <jcid@dillo.org>
parents: 1050
diff changeset
186 dFree(gif->linebuf);
d6767b7bdf93 Fix a memory leak when stopping an image-decoding process
Jorge Arellano Cid <jcid@dillo.org>
parents: 1050
diff changeset
187 if (gif->spill_lines != NULL) {
d6767b7bdf93 Fix a memory leak when stopping an image-decoding process
Jorge Arellano Cid <jcid@dillo.org>
parents: 1050
diff changeset
188 for (i = 0; i < gif->num_spill_lines_max; i++)
d6767b7bdf93 Fix a memory leak when stopping an image-decoding process
Jorge Arellano Cid <jcid@dillo.org>
parents: 1050
diff changeset
189 dFree(gif->spill_lines[i]);
d6767b7bdf93 Fix a memory leak when stopping an image-decoding process
Jorge Arellano Cid <jcid@dillo.org>
parents: 1050
diff changeset
190 dFree(gif->spill_lines);
d6767b7bdf93 Fix a memory leak when stopping an image-decoding process
Jorge Arellano Cid <jcid@dillo.org>
parents: 1050
diff changeset
191 }
d6767b7bdf93 Fix a memory leak when stopping an image-decoding process
Jorge Arellano Cid <jcid@dillo.org>
parents: 1050
diff changeset
192 dFree(gif);
d6767b7bdf93 Fix a memory leak when stopping an image-decoding process
Jorge Arellano Cid <jcid@dillo.org>
parents: 1050
diff changeset
193 }
d6767b7bdf93 Fix a memory leak when stopping an image-decoding process
Jorge Arellano Cid <jcid@dillo.org>
parents: 1050
diff changeset
194
d6767b7bdf93 Fix a memory leak when stopping an image-decoding process
Jorge Arellano Cid <jcid@dillo.org>
parents: 1050
diff changeset
195 /*
0
6ee11bf9e3ea Initial revision
jcid
parents:
diff changeset
196 * This function is a cache client, it receives data from the cache
6ee11bf9e3ea Initial revision
jcid
parents:
diff changeset
197 * and dispatches it to the appropriate gif-processing functions
6ee11bf9e3ea Initial revision
jcid
parents:
diff changeset
198 */
1085
d6767b7bdf93 Fix a memory leak when stopping an image-decoding process
Jorge Arellano Cid <jcid@dillo.org>
parents: 1050
diff changeset
199 void a_Gif_callback(int Op, void *data)
0
6ee11bf9e3ea Initial revision
jcid
parents:
diff changeset
200 {
1085
d6767b7bdf93 Fix a memory leak when stopping an image-decoding process
Jorge Arellano Cid <jcid@dillo.org>
parents: 1050
diff changeset
201 if (Op == CA_Send) {
d6767b7bdf93 Fix a memory leak when stopping an image-decoding process
Jorge Arellano Cid <jcid@dillo.org>
parents: 1050
diff changeset
202 CacheClient_t *Client = data;
d6767b7bdf93 Fix a memory leak when stopping an image-decoding process
Jorge Arellano Cid <jcid@dillo.org>
parents: 1050
diff changeset
203 Gif_write(Client->CbData, Client->Buf, Client->BufSize);
d6767b7bdf93 Fix a memory leak when stopping an image-decoding process
Jorge Arellano Cid <jcid@dillo.org>
parents: 1050
diff changeset
204 } else if (Op == CA_Close) {
d6767b7bdf93 Fix a memory leak when stopping an image-decoding process
Jorge Arellano Cid <jcid@dillo.org>
parents: 1050
diff changeset
205 CacheClient_t *Client = data;
0
6ee11bf9e3ea Initial revision
jcid
parents:
diff changeset
206 Gif_close(Client->CbData, Client);
1085
d6767b7bdf93 Fix a memory leak when stopping an image-decoding process
Jorge Arellano Cid <jcid@dillo.org>
parents: 1050
diff changeset
207 } else if (Op == CA_Abort) {
d6767b7bdf93 Fix a memory leak when stopping an image-decoding process
Jorge Arellano Cid <jcid@dillo.org>
parents: 1050
diff changeset
208 Gif_free(data);
d6767b7bdf93 Fix a memory leak when stopping an image-decoding process
Jorge Arellano Cid <jcid@dillo.org>
parents: 1050
diff changeset
209 }
0
6ee11bf9e3ea Initial revision
jcid
parents:
diff changeset
210 }
6ee11bf9e3ea Initial revision
jcid
parents:
diff changeset
211
6ee11bf9e3ea Initial revision
jcid
parents:
diff changeset
212 /*
6ee11bf9e3ea Initial revision
jcid
parents:
diff changeset
213 * Receive and process new chunks of GIF image data
6ee11bf9e3ea Initial revision
jcid
parents:
diff changeset
214 */
6ee11bf9e3ea Initial revision
jcid
parents:
diff changeset
215 static void Gif_write(DilloGif *gif, void *Buf, uint_t BufSize)
6ee11bf9e3ea Initial revision
jcid
parents:
diff changeset
216 {
6ee11bf9e3ea Initial revision
jcid
parents:
diff changeset
217 uchar_t *buf;
6ee11bf9e3ea Initial revision
jcid
parents:
diff changeset
218 int bufsize, bytes_consumed;
6ee11bf9e3ea Initial revision
jcid
parents:
diff changeset
219
6ee11bf9e3ea Initial revision
jcid
parents:
diff changeset
220 /* Sanity checks */
6ee11bf9e3ea Initial revision
jcid
parents:
diff changeset
221 if (!Buf || !gif->Image || BufSize == 0)
6ee11bf9e3ea Initial revision
jcid
parents:
diff changeset
222 return;
6ee11bf9e3ea Initial revision
jcid
parents:
diff changeset
223
6ee11bf9e3ea Initial revision
jcid
parents:
diff changeset
224 buf = ((uchar_t *) Buf) + gif->Start_Ofs;
6ee11bf9e3ea Initial revision
jcid
parents:
diff changeset
225 bufsize = BufSize - gif->Start_Ofs;
6ee11bf9e3ea Initial revision
jcid
parents:
diff changeset
226
359
b9142bae5429 - Switched from DEBUG_MSG to MSG.
jcid
parents: 335
diff changeset
227 _MSG("Gif_write: %u bytes\n", BufSize);
0
6ee11bf9e3ea Initial revision
jcid
parents:
diff changeset
228
6ee11bf9e3ea Initial revision
jcid
parents:
diff changeset
229 /* Process the bytes in the input buffer. */
6ee11bf9e3ea Initial revision
jcid
parents:
diff changeset
230 bytes_consumed = Gif_process_bytes(gif, buf, bufsize, Buf);
6ee11bf9e3ea Initial revision
jcid
parents:
diff changeset
231
6ee11bf9e3ea Initial revision
jcid
parents:
diff changeset
232 if (bytes_consumed < 1)
6ee11bf9e3ea Initial revision
jcid
parents:
diff changeset
233 return;
6ee11bf9e3ea Initial revision
jcid
parents:
diff changeset
234 gif->Start_Ofs += bytes_consumed;
6ee11bf9e3ea Initial revision
jcid
parents:
diff changeset
235
359
b9142bae5429 - Switched from DEBUG_MSG to MSG.
jcid
parents: 335
diff changeset
236 _MSG("exit Gif_write, bufsize=%ld\n", (long)bufsize);
0
6ee11bf9e3ea Initial revision
jcid
parents:
diff changeset
237 }
6ee11bf9e3ea Initial revision
jcid
parents:
diff changeset
238
6ee11bf9e3ea Initial revision
jcid
parents:
diff changeset
239 /*
6ee11bf9e3ea Initial revision
jcid
parents:
diff changeset
240 * Finish the decoding process (and free the memory)
6ee11bf9e3ea Initial revision
jcid
parents:
diff changeset
241 */
6ee11bf9e3ea Initial revision
jcid
parents:
diff changeset
242 static void Gif_close(DilloGif *gif, CacheClient_t *Client)
6ee11bf9e3ea Initial revision
jcid
parents:
diff changeset
243 {
768
eeb44d8bf3a0 Make now-unused debug messages silent.
Jorge Arellano Cid <jcid@dillo.org>
parents: 741
diff changeset
244 _MSG("Gif_close: destroy gif %p\n", gif);
0
6ee11bf9e3ea Initial revision
jcid
parents:
diff changeset
245 a_Dicache_close(gif->url, gif->version, Client);
1085
d6767b7bdf93 Fix a memory leak when stopping an image-decoding process
Jorge Arellano Cid <jcid@dillo.org>
parents: 1050
diff changeset
246 Gif_free(gif);
0
6ee11bf9e3ea Initial revision
jcid
parents:
diff changeset
247 }
6ee11bf9e3ea Initial revision
jcid
parents:
diff changeset
248
6ee11bf9e3ea Initial revision
jcid
parents:
diff changeset
249
6ee11bf9e3ea Initial revision
jcid
parents:
diff changeset
250 /* --- GIF Extensions ----------------------------------------------------- */
6ee11bf9e3ea Initial revision
jcid
parents:
diff changeset
251
6ee11bf9e3ea Initial revision
jcid
parents:
diff changeset
252 /*
6ee11bf9e3ea Initial revision
jcid
parents:
diff changeset
253 * This reads a sequence of GIF data blocks.. and ignores them!
6ee11bf9e3ea Initial revision
jcid
parents:
diff changeset
254 * Buf points to the first data block.
6ee11bf9e3ea Initial revision
jcid
parents:
diff changeset
255 *
6ee11bf9e3ea Initial revision
jcid
parents:
diff changeset
256 * Return Value
6ee11bf9e3ea Initial revision
jcid
parents:
diff changeset
257 * 0 = There wasn't enough bytes read yet to read the whole datablock
6ee11bf9e3ea Initial revision
jcid
parents:
diff changeset
258 * otherwise the size of the data blocks
6ee11bf9e3ea Initial revision
jcid
parents:
diff changeset
259 */
6ee11bf9e3ea Initial revision
jcid
parents:
diff changeset
260 static inline size_t Gif_data_blocks(const uchar_t *Buf, size_t BSize)
6ee11bf9e3ea Initial revision
jcid
parents:
diff changeset
261 {
6ee11bf9e3ea Initial revision
jcid
parents:
diff changeset
262 size_t Size = 0;
6ee11bf9e3ea Initial revision
jcid
parents:
diff changeset
263
6ee11bf9e3ea Initial revision
jcid
parents:
diff changeset
264 if (BSize < 1)
6ee11bf9e3ea Initial revision
jcid
parents:
diff changeset
265 return 0;
6ee11bf9e3ea Initial revision
jcid
parents:
diff changeset
266 while (Buf[0]) {
6ee11bf9e3ea Initial revision
jcid
parents:
diff changeset
267 if (BSize <= (size_t)(Buf[0] + 1))
6ee11bf9e3ea Initial revision
jcid
parents:
diff changeset
268 return 0;
6ee11bf9e3ea Initial revision
jcid
parents:
diff changeset
269 Size += Buf[0] + 1;
6ee11bf9e3ea Initial revision
jcid
parents:
diff changeset
270 BSize -= Buf[0] + 1;
6ee11bf9e3ea Initial revision
jcid
parents:
diff changeset
271 Buf += Buf[0] + 1;
6ee11bf9e3ea Initial revision
jcid
parents:
diff changeset
272 }
6ee11bf9e3ea Initial revision
jcid
parents:
diff changeset
273 return Size + 1;
6ee11bf9e3ea Initial revision
jcid
parents:
diff changeset
274 }
6ee11bf9e3ea Initial revision
jcid
parents:
diff changeset
275
6ee11bf9e3ea Initial revision
jcid
parents:
diff changeset
276 /*
6ee11bf9e3ea Initial revision
jcid
parents:
diff changeset
277 * This is a GIF extension. We ignore it with this routine.
6ee11bf9e3ea Initial revision
jcid
parents:
diff changeset
278 * Buffer points to just after the extension label.
6ee11bf9e3ea Initial revision
jcid
parents:
diff changeset
279 *
6ee11bf9e3ea Initial revision
jcid
parents:
diff changeset
280 * Return Value
6ee11bf9e3ea Initial revision
jcid
parents:
diff changeset
281 * 0 -- block not processed
6ee11bf9e3ea Initial revision
jcid
parents:
diff changeset
282 * otherwise the size of the extension label.
6ee11bf9e3ea Initial revision
jcid
parents:
diff changeset
283 */
6ee11bf9e3ea Initial revision
jcid
parents:
diff changeset
284 static inline size_t Gif_do_generic_ext(const uchar_t *Buf, size_t BSize)
6ee11bf9e3ea Initial revision
jcid
parents:
diff changeset
285 {
6ee11bf9e3ea Initial revision
jcid
parents:
diff changeset
286 size_t Size = Buf[0] + 1, DSize;
6ee11bf9e3ea Initial revision
jcid
parents:
diff changeset
287
6ee11bf9e3ea Initial revision
jcid
parents:
diff changeset
288 /* The Block size (the first byte) is supposed to be a specific size
6ee11bf9e3ea Initial revision
jcid
parents:
diff changeset
289 * for each extension... we don't check.
6ee11bf9e3ea Initial revision
jcid
parents:
diff changeset
290 */
6ee11bf9e3ea Initial revision
jcid
parents:
diff changeset
291
6ee11bf9e3ea Initial revision
jcid
parents:
diff changeset
292 if (Buf[0] > BSize)
6ee11bf9e3ea Initial revision
jcid
parents:
diff changeset
293 return 0;
6ee11bf9e3ea Initial revision
jcid
parents:
diff changeset
294 DSize = Gif_data_blocks(Buf + Size, BSize - Size);
6ee11bf9e3ea Initial revision
jcid
parents:
diff changeset
295 if (!DSize)
6ee11bf9e3ea Initial revision
jcid
parents:
diff changeset
296 return 0;
6ee11bf9e3ea Initial revision
jcid
parents:
diff changeset
297 Size += DSize;
6ee11bf9e3ea Initial revision
jcid
parents:
diff changeset
298 return Size <= BSize ? Size : 0;
6ee11bf9e3ea Initial revision
jcid
parents:
diff changeset
299 }
6ee11bf9e3ea Initial revision
jcid
parents:
diff changeset
300
6ee11bf9e3ea Initial revision
jcid
parents:
diff changeset
301 /*
6ee11bf9e3ea Initial revision
jcid
parents:
diff changeset
302 * ?
6ee11bf9e3ea Initial revision
jcid
parents:
diff changeset
303 */
6ee11bf9e3ea Initial revision
jcid
parents:
diff changeset
304 static inline size_t
6ee11bf9e3ea Initial revision
jcid
parents:
diff changeset
305 Gif_do_gc_ext(DilloGif *gif, const uchar_t *Buf, size_t BSize)
6ee11bf9e3ea Initial revision
jcid
parents:
diff changeset
306 {
6ee11bf9e3ea Initial revision
jcid
parents:
diff changeset
307 /* Graphic Control Extension */
6ee11bf9e3ea Initial revision
jcid
parents:
diff changeset
308 size_t Size = Buf[0] + 2;
6ee11bf9e3ea Initial revision
jcid
parents:
diff changeset
309 uint_t Flags;
6ee11bf9e3ea Initial revision
jcid
parents:
diff changeset
310
6ee11bf9e3ea Initial revision
jcid
parents:
diff changeset
311 if (Size > BSize)
6ee11bf9e3ea Initial revision
jcid
parents:
diff changeset
312 return 0;
6ee11bf9e3ea Initial revision
jcid
parents:
diff changeset
313 Buf++;
6ee11bf9e3ea Initial revision
jcid
parents:
diff changeset
314 Flags = Buf[0];
6ee11bf9e3ea Initial revision
jcid
parents:
diff changeset
315
6ee11bf9e3ea Initial revision
jcid
parents:
diff changeset
316 /* The packed fields */
6ee11bf9e3ea Initial revision
jcid
parents:
diff changeset
317 #if 0
6ee11bf9e3ea Initial revision
jcid
parents:
diff changeset
318 gif->disposal = (Buf[0] >> 2) & 0x7;
6ee11bf9e3ea Initial revision
jcid
parents:
diff changeset
319 gif->inputFlag = (Buf[0] >> 1) & 0x1;
6ee11bf9e3ea Initial revision
jcid
parents:
diff changeset
320
6ee11bf9e3ea Initial revision
jcid
parents:
diff changeset
321 /* Delay time */
6ee11bf9e3ea Initial revision
jcid
parents:
diff changeset
322 gif->delayTime = LM_to_uint(Buf[1], Buf[2]);
6ee11bf9e3ea Initial revision
jcid
parents:
diff changeset
323 #endif
6ee11bf9e3ea Initial revision
jcid
parents:
diff changeset
324
6ee11bf9e3ea Initial revision
jcid
parents:
diff changeset
325 /* Transparent color index, may not be valid (unless flag is set) */
6ee11bf9e3ea Initial revision
jcid
parents:
diff changeset
326 if ((Flags & 0x1)) {
6ee11bf9e3ea Initial revision
jcid
parents:
diff changeset
327 gif->transparent = Buf[3];
6ee11bf9e3ea Initial revision
jcid
parents:
diff changeset
328 }
6ee11bf9e3ea Initial revision
jcid
parents:
diff changeset
329 return Size;
6ee11bf9e3ea Initial revision
jcid
parents:
diff changeset
330 }
6ee11bf9e3ea Initial revision
jcid
parents:
diff changeset
331
6ee11bf9e3ea Initial revision
jcid
parents:
diff changeset
332 #define App_Ext (0xff)
6ee11bf9e3ea Initial revision
jcid
parents:
diff changeset
333 #define Cmt_Ext (0xfe)
6ee11bf9e3ea Initial revision
jcid
parents:
diff changeset
334 #define GC_Ext (0xf9)
6ee11bf9e3ea Initial revision
jcid
parents:
diff changeset
335 #define Txt_Ext (0x01)
6ee11bf9e3ea Initial revision
jcid
parents:
diff changeset
336
6ee11bf9e3ea Initial revision
jcid
parents:
diff changeset
337 /*
6ee11bf9e3ea Initial revision
jcid
parents:
diff changeset
338 * ?
6ee11bf9e3ea Initial revision
jcid
parents:
diff changeset
339 * Return value:
6ee11bf9e3ea Initial revision
jcid
parents:
diff changeset
340 * TRUE when the extension is over
6ee11bf9e3ea Initial revision
jcid
parents:
diff changeset
341 */
6ee11bf9e3ea Initial revision
jcid
parents:
diff changeset
342 static size_t Gif_do_extension(DilloGif *gif, uint_t Label,
6ee11bf9e3ea Initial revision
jcid
parents:
diff changeset
343 const uchar_t *buf,
6ee11bf9e3ea Initial revision
jcid
parents:
diff changeset
344 size_t BSize)
6ee11bf9e3ea Initial revision
jcid
parents:
diff changeset
345 {
6ee11bf9e3ea Initial revision
jcid
parents:
diff changeset
346 switch (Label) {
6ee11bf9e3ea Initial revision
jcid
parents:
diff changeset
347 case GC_Ext: /* Graphics extension */
6ee11bf9e3ea Initial revision
jcid
parents:
diff changeset
348 return Gif_do_gc_ext(gif, buf, BSize);
6ee11bf9e3ea Initial revision
jcid
parents:
diff changeset
349
6ee11bf9e3ea Initial revision
jcid
parents:
diff changeset
350 case Cmt_Ext: /* Comment extension */
6ee11bf9e3ea Initial revision
jcid
parents:
diff changeset
351 return Gif_data_blocks(buf, BSize);
6ee11bf9e3ea Initial revision
jcid
parents:
diff changeset
352
6ee11bf9e3ea Initial revision
jcid
parents:
diff changeset
353 case Txt_Ext: /* Plain text Extension */
6ee11bf9e3ea Initial revision
jcid
parents:
diff changeset
354 case App_Ext: /* Application Extension */
6ee11bf9e3ea Initial revision
jcid
parents:
diff changeset
355 default:
6ee11bf9e3ea Initial revision
jcid
parents:
diff changeset
356 return Gif_do_generic_ext(buf, BSize); /*Ignore Extension */
6ee11bf9e3ea Initial revision
jcid
parents:
diff changeset
357 }
6ee11bf9e3ea Initial revision
jcid
parents:
diff changeset
358 }
6ee11bf9e3ea Initial revision
jcid
parents:
diff changeset
359
6ee11bf9e3ea Initial revision
jcid
parents:
diff changeset
360 /* --- General Image Decoder ----------------------------------------------- */
6ee11bf9e3ea Initial revision
jcid
parents:
diff changeset
361 /* Here begins the new push-oriented decoder. */
6ee11bf9e3ea Initial revision
jcid
parents:
diff changeset
362
6ee11bf9e3ea Initial revision
jcid
parents:
diff changeset
363 /*
6ee11bf9e3ea Initial revision
jcid
parents:
diff changeset
364 * ?
6ee11bf9e3ea Initial revision
jcid
parents:
diff changeset
365 */
6ee11bf9e3ea Initial revision
jcid
parents:
diff changeset
366 static void Gif_lwz_init(DilloGif *gif)
6ee11bf9e3ea Initial revision
jcid
parents:
diff changeset
367 {
6ee11bf9e3ea Initial revision
jcid
parents:
diff changeset
368 gif->num_spill_lines_max = 1;
6ee11bf9e3ea Initial revision
jcid
parents:
diff changeset
369 gif->spill_lines = dMalloc(sizeof(uchar_t *) * gif->num_spill_lines_max);
6ee11bf9e3ea Initial revision
jcid
parents:
diff changeset
370
6ee11bf9e3ea Initial revision
jcid
parents:
diff changeset
371 gif->spill_lines[0] = dMalloc(gif->Width);
6ee11bf9e3ea Initial revision
jcid
parents:
diff changeset
372 gif->bits_in_window = 0;
6ee11bf9e3ea Initial revision
jcid
parents:
diff changeset
373
6ee11bf9e3ea Initial revision
jcid
parents:
diff changeset
374 /* First code in table = clear_code +1
6ee11bf9e3ea Initial revision
jcid
parents:
diff changeset
375 * Last code in table = first code in table
6ee11bf9e3ea Initial revision
jcid
parents:
diff changeset
376 * clear_code = (1<< input code size)
6ee11bf9e3ea Initial revision
jcid
parents:
diff changeset
377 */
6ee11bf9e3ea Initial revision
jcid
parents:
diff changeset
378 gif->last_code = (1 << gif->input_code_size) + 1;
6ee11bf9e3ea Initial revision
jcid
parents:
diff changeset
379 memset(gif->code_and_byte, 0,
6ee11bf9e3ea Initial revision
jcid
parents:
diff changeset
380 (1 + gif->last_code) * sizeof(gif->code_and_byte[0]));
6ee11bf9e3ea Initial revision
jcid
parents:
diff changeset
381 gif->code_size = gif->input_code_size + 1;
6ee11bf9e3ea Initial revision
jcid
parents:
diff changeset
382 gif->line_index = 0;
6ee11bf9e3ea Initial revision
jcid
parents:
diff changeset
383 }
6ee11bf9e3ea Initial revision
jcid
parents:
diff changeset
384
6ee11bf9e3ea Initial revision
jcid
parents:
diff changeset
385 /*
6ee11bf9e3ea Initial revision
jcid
parents:
diff changeset
386 * Send the image line to the dicache, also handling the interlacing.
6ee11bf9e3ea Initial revision
jcid
parents:
diff changeset
387 */
6ee11bf9e3ea Initial revision
jcid
parents:
diff changeset
388 static void Gif_emit_line(DilloGif *gif, const uchar_t *linebuf)
6ee11bf9e3ea Initial revision
jcid
parents:
diff changeset
389 {
1050
6a270ab021ce Remove unused parameter in a_Dicache_write()
corvid <corvid@lavabit.com>
parents: 991
diff changeset
390 a_Dicache_write(gif->url, gif->version, linebuf, gif->y);
0
6ee11bf9e3ea Initial revision
jcid
parents:
diff changeset
391 if (gif->Flags & INTERLACE) {
6ee11bf9e3ea Initial revision
jcid
parents:
diff changeset
392 switch (gif->pass) {
6ee11bf9e3ea Initial revision
jcid
parents:
diff changeset
393 case 0:
6ee11bf9e3ea Initial revision
jcid
parents:
diff changeset
394 case 1:
6ee11bf9e3ea Initial revision
jcid
parents:
diff changeset
395 gif->y += 8;
6ee11bf9e3ea Initial revision
jcid
parents:
diff changeset
396 break;
6ee11bf9e3ea Initial revision
jcid
parents:
diff changeset
397 case 2:
6ee11bf9e3ea Initial revision
jcid
parents:
diff changeset
398 gif->y += 4;
6ee11bf9e3ea Initial revision
jcid
parents:
diff changeset
399 break;
6ee11bf9e3ea Initial revision
jcid
parents:
diff changeset
400 case 3:
6ee11bf9e3ea Initial revision
jcid
parents:
diff changeset
401 gif->y += 2;
6ee11bf9e3ea Initial revision
jcid
parents:
diff changeset
402 break;
6ee11bf9e3ea Initial revision
jcid
parents:
diff changeset
403 }
6ee11bf9e3ea Initial revision
jcid
parents:
diff changeset
404 if (gif->y >= gif->Height) {
6ee11bf9e3ea Initial revision
jcid
parents:
diff changeset
405 gif->pass++;
6ee11bf9e3ea Initial revision
jcid
parents:
diff changeset
406 switch (gif->pass) {
6ee11bf9e3ea Initial revision
jcid
parents:
diff changeset
407 case 1:
6ee11bf9e3ea Initial revision
jcid
parents:
diff changeset
408 gif->y = 4;
6ee11bf9e3ea Initial revision
jcid
parents:
diff changeset
409 break;
6ee11bf9e3ea Initial revision
jcid
parents:
diff changeset
410 case 2:
6ee11bf9e3ea Initial revision
jcid
parents:
diff changeset
411 gif->y = 2;
6ee11bf9e3ea Initial revision
jcid
parents:
diff changeset
412 break;
6ee11bf9e3ea Initial revision
jcid
parents:
diff changeset
413 case 3:
6ee11bf9e3ea Initial revision
jcid
parents:
diff changeset
414 gif->y = 1;
6ee11bf9e3ea Initial revision
jcid
parents:
diff changeset
415 break;
6ee11bf9e3ea Initial revision
jcid
parents:
diff changeset
416 default:
6ee11bf9e3ea Initial revision
jcid
parents:
diff changeset
417 /* arriving here is an error in the input image. */
6ee11bf9e3ea Initial revision
jcid
parents:
diff changeset
418 gif->y = 0;
6ee11bf9e3ea Initial revision
jcid
parents:
diff changeset
419 break;
6ee11bf9e3ea Initial revision
jcid
parents:
diff changeset
420 }
6ee11bf9e3ea Initial revision
jcid
parents:
diff changeset
421 }
6ee11bf9e3ea Initial revision
jcid
parents:
diff changeset
422 } else {
6ee11bf9e3ea Initial revision
jcid
parents:
diff changeset
423 if (gif->y < gif->Height)
6ee11bf9e3ea Initial revision
jcid
parents:
diff changeset
424 gif->y++;
6ee11bf9e3ea Initial revision
jcid
parents:
diff changeset
425 }
6ee11bf9e3ea Initial revision
jcid
parents:
diff changeset
426 }
6ee11bf9e3ea Initial revision
jcid
parents:
diff changeset
427
6ee11bf9e3ea Initial revision
jcid
parents:
diff changeset
428 /*
6ee11bf9e3ea Initial revision
jcid
parents:
diff changeset
429 * Decode the packetized lwz bytes
6ee11bf9e3ea Initial revision
jcid
parents:
diff changeset
430 */
6ee11bf9e3ea Initial revision
jcid
parents:
diff changeset
431 static void Gif_literal(DilloGif *gif, uint_t code)
6ee11bf9e3ea Initial revision
jcid
parents:
diff changeset
432 {
6ee11bf9e3ea Initial revision
jcid
parents:
diff changeset
433 gif->linebuf[gif->line_index++] = code;
6ee11bf9e3ea Initial revision
jcid
parents:
diff changeset
434 if (gif->line_index >= gif->Width) {
6ee11bf9e3ea Initial revision
jcid
parents:
diff changeset
435 Gif_emit_line(gif, gif->linebuf);
6ee11bf9e3ea Initial revision
jcid
parents:
diff changeset
436 gif->line_index = 0;
6ee11bf9e3ea Initial revision
jcid
parents:
diff changeset
437 }
6ee11bf9e3ea Initial revision
jcid
parents:
diff changeset
438 gif->length[gif->last_code + 1] = 2;
6ee11bf9e3ea Initial revision
jcid
parents:
diff changeset
439 gif->code_and_byte[gif->last_code + 1] = (code << 8);
6ee11bf9e3ea Initial revision
jcid
parents:
diff changeset
440 gif->code_and_byte[gif->last_code] |= code;
6ee11bf9e3ea Initial revision
jcid
parents:
diff changeset
441 }
6ee11bf9e3ea Initial revision
jcid
parents:
diff changeset
442
6ee11bf9e3ea Initial revision
jcid
parents:
diff changeset
443 /*
6ee11bf9e3ea Initial revision
jcid
parents:
diff changeset
444 * ?
6ee11bf9e3ea Initial revision
jcid
parents:
diff changeset
445 */
6ee11bf9e3ea Initial revision
jcid
parents:
diff changeset
446 /* Profiling reveals over half the GIF time is spent here: */
6ee11bf9e3ea Initial revision
jcid
parents:
diff changeset
447 static void Gif_sequence(DilloGif *gif, uint_t code)
6ee11bf9e3ea Initial revision
jcid
parents:
diff changeset
448 {
6ee11bf9e3ea Initial revision
jcid
parents:
diff changeset
449 uint_t o_index, o_size, orig_code;
6ee11bf9e3ea Initial revision
jcid
parents:
diff changeset
450 uint_t sequence_length = gif->length[code];
6ee11bf9e3ea Initial revision
jcid
parents:
diff changeset
451 uint_t line_index = gif->line_index;
6ee11bf9e3ea Initial revision
jcid
parents:
diff changeset
452 int num_spill_lines;
6ee11bf9e3ea Initial revision
jcid
parents:
diff changeset
453 int spill_line_index = gif->spill_line_index;
6ee11bf9e3ea Initial revision
jcid
parents:
diff changeset
454 uchar_t *last_byte_ptr, *obuf;
6ee11bf9e3ea Initial revision
jcid
parents:
diff changeset
455
6ee11bf9e3ea Initial revision
jcid
parents:
diff changeset
456 gif->length[gif->last_code + 1] = sequence_length + 1;
6ee11bf9e3ea Initial revision
jcid
parents:
diff changeset
457 gif->code_and_byte[gif->last_code + 1] = (code << 8);
6ee11bf9e3ea Initial revision
jcid
parents:
diff changeset
458
6ee11bf9e3ea Initial revision
jcid
parents:
diff changeset
459 /* We're going to traverse the sequence backwards. Thus,
6ee11bf9e3ea Initial revision
jcid
parents:
diff changeset
460 * we need to allocate spill lines if the sequence won't
6ee11bf9e3ea Initial revision
jcid
parents:
diff changeset
461 * fit entirely within the present scan line. */
6ee11bf9e3ea Initial revision
jcid
parents:
diff changeset
462 if (line_index + sequence_length <= gif->Width) {
6ee11bf9e3ea Initial revision
jcid
parents:
diff changeset
463 num_spill_lines = 0;
6ee11bf9e3ea Initial revision
jcid
parents:
diff changeset
464 obuf = gif->linebuf;
6ee11bf9e3ea Initial revision
jcid
parents:
diff changeset
465 o_index = line_index + sequence_length;
6ee11bf9e3ea Initial revision
jcid
parents:
diff changeset
466 o_size = sequence_length - 1;
6ee11bf9e3ea Initial revision
jcid
parents:
diff changeset
467 } else {
6ee11bf9e3ea Initial revision
jcid
parents:
diff changeset
468 num_spill_lines = (line_index + sequence_length - 1) /
6ee11bf9e3ea Initial revision
jcid
parents:
diff changeset
469 gif->Width;
6ee11bf9e3ea Initial revision
jcid
parents:
diff changeset
470 o_index = (line_index + sequence_length - 1) % gif->Width + 1;
6ee11bf9e3ea Initial revision
jcid
parents:
diff changeset
471 if (num_spill_lines > gif->num_spill_lines_max) {
6ee11bf9e3ea Initial revision
jcid
parents:
diff changeset
472 /* Allocate more spill lines. */
6ee11bf9e3ea Initial revision
jcid
parents:
diff changeset
473 spill_line_index = gif->num_spill_lines_max;
6ee11bf9e3ea Initial revision
jcid
parents:
diff changeset
474 gif->num_spill_lines_max = num_spill_lines << 1;
6ee11bf9e3ea Initial revision
jcid
parents:
diff changeset
475 gif->spill_lines = dRealloc(gif->spill_lines,
6ee11bf9e3ea Initial revision
jcid
parents:
diff changeset
476 gif->num_spill_lines_max *
6ee11bf9e3ea Initial revision
jcid
parents:
diff changeset
477 sizeof(uchar_t *));
6ee11bf9e3ea Initial revision
jcid
parents:
diff changeset
478
6ee11bf9e3ea Initial revision
jcid
parents:
diff changeset
479 for (; spill_line_index < gif->num_spill_lines_max;
6ee11bf9e3ea Initial revision
jcid
parents:
diff changeset
480 spill_line_index++)
6ee11bf9e3ea Initial revision
jcid
parents:
diff changeset
481 gif->spill_lines[spill_line_index] =
6ee11bf9e3ea Initial revision
jcid
parents:
diff changeset
482 dMalloc(gif->Width);
6ee11bf9e3ea Initial revision
jcid
parents:
diff changeset
483 }
6ee11bf9e3ea Initial revision
jcid
parents:
diff changeset
484 spill_line_index = num_spill_lines - 1;
6ee11bf9e3ea Initial revision
jcid
parents:
diff changeset
485 obuf = gif->spill_lines[spill_line_index];
6ee11bf9e3ea Initial revision
jcid
parents:
diff changeset
486 o_size = o_index;
6ee11bf9e3ea Initial revision
jcid
parents:
diff changeset
487 }
6ee11bf9e3ea Initial revision
jcid
parents:
diff changeset
488 gif->line_index = o_index; /* for afterwards */
6ee11bf9e3ea Initial revision
jcid
parents:
diff changeset
489
6ee11bf9e3ea Initial revision
jcid
parents:
diff changeset
490 /* for fixing up later if last_code == code */
6ee11bf9e3ea Initial revision
jcid
parents:
diff changeset
491 orig_code = code;
6ee11bf9e3ea Initial revision
jcid
parents:
diff changeset
492 last_byte_ptr = obuf + o_index - 1;
6ee11bf9e3ea Initial revision
jcid
parents:
diff changeset
493
6ee11bf9e3ea Initial revision
jcid
parents:
diff changeset
494 /* spill lines are allocated, and we are clear to
6ee11bf9e3ea Initial revision
jcid
parents:
diff changeset
495 * write. This loop does not write the first byte of
6ee11bf9e3ea Initial revision
jcid
parents:
diff changeset
496 * the sequence, however (last byte traversed). */
6ee11bf9e3ea Initial revision
jcid
parents:
diff changeset
497 while (sequence_length > 1) {
6ee11bf9e3ea Initial revision
jcid
parents:
diff changeset
498 sequence_length -= o_size;
6ee11bf9e3ea Initial revision
jcid
parents:
diff changeset
499 /* Write o_size bytes to
6ee11bf9e3ea Initial revision
jcid
parents:
diff changeset
500 * obuf[o_index - o_size..o_index). */
6ee11bf9e3ea Initial revision
jcid
parents:
diff changeset
501 for (; o_size > 0 && o_index > 0; o_size--) {
6ee11bf9e3ea Initial revision
jcid
parents:
diff changeset
502 uint_t code_and_byte = gif->code_and_byte[code];
6ee11bf9e3ea Initial revision
jcid
parents:
diff changeset
503
359
b9142bae5429 - Switched from DEBUG_MSG to MSG.
jcid
parents: 335
diff changeset
504 _MSG("%d ", gif->code_and_byte[code] & 255);
0
6ee11bf9e3ea Initial revision
jcid
parents:
diff changeset
505
6ee11bf9e3ea Initial revision
jcid
parents:
diff changeset
506 obuf[--o_index] = code_and_byte & 255;
6ee11bf9e3ea Initial revision
jcid
parents:
diff changeset
507 code = code_and_byte >> 8;
6ee11bf9e3ea Initial revision
jcid
parents:
diff changeset
508 }
6ee11bf9e3ea Initial revision
jcid
parents:
diff changeset
509 /* Prepare for writing to next line. */
6ee11bf9e3ea Initial revision
jcid
parents:
diff changeset
510 if (o_index == 0) {
6ee11bf9e3ea Initial revision
jcid
parents:
diff changeset
511 if (spill_line_index > 0) {
6ee11bf9e3ea Initial revision
jcid
parents:
diff changeset
512 spill_line_index--;
6ee11bf9e3ea Initial revision
jcid
parents:
diff changeset
513 obuf = gif->spill_lines[spill_line_index];
6ee11bf9e3ea Initial revision
jcid
parents:
diff changeset
514 o_size = gif->Width;
6ee11bf9e3ea Initial revision
jcid
parents:
diff changeset
515 } else {
6ee11bf9e3ea Initial revision
jcid
parents:
diff changeset
516 obuf = gif->linebuf;
6ee11bf9e3ea Initial revision
jcid
parents:
diff changeset
517 o_size = sequence_length - 1;
6ee11bf9e3ea Initial revision
jcid
parents:
diff changeset
518 }
6ee11bf9e3ea Initial revision
jcid
parents:
diff changeset
519 o_index = gif->Width;
6ee11bf9e3ea Initial revision
jcid
parents:
diff changeset
520 }
6ee11bf9e3ea Initial revision
jcid
parents:
diff changeset
521 }
6ee11bf9e3ea Initial revision
jcid
parents:
diff changeset
522 /* Ok, now we write the first byte of the sequence. */
6ee11bf9e3ea Initial revision
jcid
parents:
diff changeset
523 /* We are sure that the code is literal. */
359
b9142bae5429 - Switched from DEBUG_MSG to MSG.
jcid
parents: 335
diff changeset
524 _MSG("%d", code);
0
6ee11bf9e3ea Initial revision
jcid
parents:
diff changeset
525 obuf[--o_index] = code;
6ee11bf9e3ea Initial revision
jcid
parents:
diff changeset
526 gif->code_and_byte[gif->last_code] |= code;
6ee11bf9e3ea Initial revision
jcid
parents:
diff changeset
527
6ee11bf9e3ea Initial revision
jcid
parents:
diff changeset
528 /* Fix up the output if the original code was last_code. */
6ee11bf9e3ea Initial revision
jcid
parents:
diff changeset
529 if (orig_code == gif->last_code) {
6ee11bf9e3ea Initial revision
jcid
parents:
diff changeset
530 *last_byte_ptr = code;
359
b9142bae5429 - Switched from DEBUG_MSG to MSG.
jcid
parents: 335
diff changeset
531 _MSG(" fixed (%d)!", code);
0
6ee11bf9e3ea Initial revision
jcid
parents:
diff changeset
532 }
359
b9142bae5429 - Switched from DEBUG_MSG to MSG.
jcid
parents: 335
diff changeset
533 _MSG("\n");
0
6ee11bf9e3ea Initial revision
jcid
parents:
diff changeset
534
6ee11bf9e3ea Initial revision
jcid
parents:
diff changeset
535 /* Output any full lines. */
6ee11bf9e3ea Initial revision
jcid
parents:
diff changeset
536 if (gif->line_index >= gif->Width) {
6ee11bf9e3ea Initial revision
jcid
parents:
diff changeset
537 Gif_emit_line(gif, gif->linebuf);
6ee11bf9e3ea Initial revision
jcid
parents:
diff changeset
538 gif->line_index = 0;
6ee11bf9e3ea Initial revision
jcid
parents:
diff changeset
539 }
6ee11bf9e3ea Initial revision
jcid
parents:
diff changeset
540 if (num_spill_lines) {
6ee11bf9e3ea Initial revision
jcid
parents:
diff changeset
541 if (gif->line_index)
6ee11bf9e3ea Initial revision
jcid
parents:
diff changeset
542 Gif_emit_line(gif, gif->linebuf);
6ee11bf9e3ea Initial revision
jcid
parents:
diff changeset
543 for (spill_line_index = 0;
6ee11bf9e3ea Initial revision
jcid
parents:
diff changeset
544 spill_line_index < num_spill_lines - (gif->line_index ? 1 : 0);
6ee11bf9e3ea Initial revision
jcid
parents:
diff changeset
545 spill_line_index++)
6ee11bf9e3ea Initial revision
jcid
parents:
diff changeset
546 Gif_emit_line(gif, gif->spill_lines[spill_line_index]);
6ee11bf9e3ea Initial revision
jcid
parents:
diff changeset
547 }
6ee11bf9e3ea Initial revision
jcid
parents:
diff changeset
548 if (num_spill_lines) {
6ee11bf9e3ea Initial revision
jcid
parents:
diff changeset
549 /* Swap the last spill line with the gif line, using
6ee11bf9e3ea Initial revision
jcid
parents:
diff changeset
550 * linebuf as the swap temporary. */
6ee11bf9e3ea Initial revision
jcid
parents:
diff changeset
551 uchar_t *linebuf = gif->spill_lines[num_spill_lines - 1];
6ee11bf9e3ea Initial revision
jcid
parents:
diff changeset
552
6ee11bf9e3ea Initial revision
jcid
parents:
diff changeset
553 gif->spill_lines[num_spill_lines - 1] = gif->linebuf;
6ee11bf9e3ea Initial revision
jcid
parents:
diff changeset
554 gif->linebuf = linebuf;
6ee11bf9e3ea Initial revision
jcid
parents:
diff changeset
555 }
6ee11bf9e3ea Initial revision
jcid
parents:
diff changeset
556 gif->spill_line_index = spill_line_index;
6ee11bf9e3ea Initial revision
jcid
parents:
diff changeset
557 }
6ee11bf9e3ea Initial revision
jcid
parents:
diff changeset
558
6ee11bf9e3ea Initial revision
jcid
parents:
diff changeset
559 /*
6ee11bf9e3ea Initial revision
jcid
parents:
diff changeset
560 * ?
6ee11bf9e3ea Initial revision
jcid
parents:
diff changeset
561 *
6ee11bf9e3ea Initial revision
jcid
parents:
diff changeset
562 * Return Value:
6ee11bf9e3ea Initial revision
jcid
parents:
diff changeset
563 * 2 -- quit
6ee11bf9e3ea Initial revision
jcid
parents:
diff changeset
564 * 1 -- new last code needs to be done
6ee11bf9e3ea Initial revision
jcid
parents:
diff changeset
565 * 0 -- okay, but reset the code table
6ee11bf9e3ea Initial revision
jcid
parents:
diff changeset
566 * < 0 on error
6ee11bf9e3ea Initial revision
jcid
parents:
diff changeset
567 * -1 if the decompression code was not in the lookup table
6ee11bf9e3ea Initial revision
jcid
parents:
diff changeset
568 */
6ee11bf9e3ea Initial revision
jcid
parents:
diff changeset
569 static int Gif_process_code(DilloGif *gif, uint_t code, uint_t clear_code)
6ee11bf9e3ea Initial revision
jcid
parents:
diff changeset
570 {
6ee11bf9e3ea Initial revision
jcid
parents:
diff changeset
571
6ee11bf9e3ea Initial revision
jcid
parents:
diff changeset
572 /* A short table describing what to do with the code:
6ee11bf9e3ea Initial revision
jcid
parents:
diff changeset
573 * code < clear_code : This is uncompressed, raw data
6ee11bf9e3ea Initial revision
jcid
parents:
diff changeset
574 * code== clear_code : Reset the decompression table
6ee11bf9e3ea Initial revision
jcid
parents:
diff changeset
575 * code== clear_code+1: End of data stream
6ee11bf9e3ea Initial revision
jcid
parents:
diff changeset
576 * code > clear_code+1: Compressed code; look up in table
6ee11bf9e3ea Initial revision
jcid
parents:
diff changeset
577 */
6ee11bf9e3ea Initial revision
jcid
parents:
diff changeset
578 if (code < clear_code) {
6ee11bf9e3ea Initial revision
jcid
parents:
diff changeset
579 /* a literal code. */
359
b9142bae5429 - Switched from DEBUG_MSG to MSG.
jcid
parents: 335
diff changeset
580 _MSG("literal\n");
0
6ee11bf9e3ea Initial revision
jcid
parents:
diff changeset
581 Gif_literal(gif, code);
6ee11bf9e3ea Initial revision
jcid
parents:
diff changeset
582 return 1;
6ee11bf9e3ea Initial revision
jcid
parents:
diff changeset
583 } else if (code >= clear_code + 2) {
6ee11bf9e3ea Initial revision
jcid
parents:
diff changeset
584 /* a sequence code. */
6ee11bf9e3ea Initial revision
jcid
parents:
diff changeset
585 if (code > gif->last_code)
6ee11bf9e3ea Initial revision
jcid
parents:
diff changeset
586 return -1;
6ee11bf9e3ea Initial revision
jcid
parents:
diff changeset
587 Gif_sequence(gif, code);
6ee11bf9e3ea Initial revision
jcid
parents:
diff changeset
588 return 1;
6ee11bf9e3ea Initial revision
jcid
parents:
diff changeset
589 } else if (code == clear_code) {
6ee11bf9e3ea Initial revision
jcid
parents:
diff changeset
590 /* clear code. Resets the whole table */
359
b9142bae5429 - Switched from DEBUG_MSG to MSG.
jcid
parents: 335
diff changeset
591 _MSG("clear\n");
0
6ee11bf9e3ea Initial revision
jcid
parents:
diff changeset
592 return 0;
6ee11bf9e3ea Initial revision
jcid
parents:
diff changeset
593 } else {
6ee11bf9e3ea Initial revision
jcid
parents:
diff changeset
594 /* end code. */
359
b9142bae5429 - Switched from DEBUG_MSG to MSG.
jcid
parents: 335
diff changeset
595 _MSG("end\n");
0
6ee11bf9e3ea Initial revision
jcid
parents:
diff changeset
596 return 2;
6ee11bf9e3ea Initial revision
jcid
parents:
diff changeset
597 }
6ee11bf9e3ea Initial revision
jcid
parents:
diff changeset
598 }
6ee11bf9e3ea Initial revision
jcid
parents:
diff changeset
599
6ee11bf9e3ea Initial revision
jcid
parents:
diff changeset
600 /*
6ee11bf9e3ea Initial revision
jcid
parents:
diff changeset
601 * ?
6ee11bf9e3ea Initial revision
jcid
parents:
diff changeset
602 */
6ee11bf9e3ea Initial revision
jcid
parents:
diff changeset
603 static int Gif_decode(DilloGif *gif, const uchar_t *buf, size_t bsize)
6ee11bf9e3ea Initial revision
jcid
parents:
diff changeset
604 {
6ee11bf9e3ea Initial revision
jcid
parents:
diff changeset
605 /*
6ee11bf9e3ea Initial revision
jcid
parents:
diff changeset
606 * Data block processing. The image stuff is a series of data blocks.
6ee11bf9e3ea Initial revision
jcid
parents:
diff changeset
607 * Each data block is 1 to 256 bytes long. The first byte is the length
6ee11bf9e3ea Initial revision
jcid
parents:
diff changeset
608 * of the data block. 0 == the last data block.
6ee11bf9e3ea Initial revision
jcid
parents:
diff changeset
609 */
6ee11bf9e3ea Initial revision
jcid
parents:
diff changeset
610 size_t bufsize, packet_size;
6ee11bf9e3ea Initial revision
jcid
parents:
diff changeset
611 uint_t clear_code;
6ee11bf9e3ea Initial revision
jcid
parents:
diff changeset
612 uint_t window;
6ee11bf9e3ea Initial revision
jcid
parents:
diff changeset
613 int bits_in_window;
6ee11bf9e3ea Initial revision
jcid
parents:
diff changeset
614 uint_t code;
6ee11bf9e3ea Initial revision
jcid
parents:
diff changeset
615 int code_size;
6ee11bf9e3ea Initial revision
jcid
parents:
diff changeset
616 uint_t code_mask;
6ee11bf9e3ea Initial revision
jcid
parents:
diff changeset
617
6ee11bf9e3ea Initial revision
jcid
parents:
diff changeset
618 bufsize = bsize;
6ee11bf9e3ea Initial revision
jcid
parents:
diff changeset
619
6ee11bf9e3ea Initial revision
jcid
parents:
diff changeset
620 /* Want to get all inner loop state into local variables. */
6ee11bf9e3ea Initial revision
jcid
parents:
diff changeset
621 packet_size = gif->packet_size;
6ee11bf9e3ea Initial revision
jcid
parents:
diff changeset
622 window = gif->window;
6ee11bf9e3ea Initial revision
jcid
parents:
diff changeset
623 bits_in_window = gif->bits_in_window;
6ee11bf9e3ea Initial revision
jcid
parents:
diff changeset
624 code_size = gif->code_size;
6ee11bf9e3ea Initial revision
jcid
parents:
diff changeset
625 code_mask = (1 << code_size) - 1;
6ee11bf9e3ea Initial revision
jcid
parents:
diff changeset
626 clear_code = 1 << gif->input_code_size;
6ee11bf9e3ea Initial revision
jcid
parents:
diff changeset
627
6ee11bf9e3ea Initial revision
jcid
parents:
diff changeset
628 /* If packet size == 0, we are at the start of a data block.
6ee11bf9e3ea Initial revision
jcid
parents:
diff changeset
629 * The first byte of the data block indicates how big it is (0 == last
6ee11bf9e3ea Initial revision
jcid
parents:
diff changeset
630 * datablock)
6ee11bf9e3ea Initial revision
jcid
parents:
diff changeset
631 * packet size is set to this size; it indicates how much of the data block
6ee11bf9e3ea Initial revision
jcid
parents:
diff changeset
632 * we have left to process.
6ee11bf9e3ea Initial revision
jcid
parents:
diff changeset
633 */
6ee11bf9e3ea Initial revision
jcid
parents:
diff changeset
634 while (bufsize > 0) {
6ee11bf9e3ea Initial revision
jcid
parents:
diff changeset
635 /* lwz_bytes is the number of remaining lwz bytes in the packet. */
6ee11bf9e3ea Initial revision
jcid
parents:
diff changeset
636 int lwz_bytes = MIN(packet_size, bufsize);
6ee11bf9e3ea Initial revision
jcid
parents:
diff changeset
637
6ee11bf9e3ea Initial revision
jcid
parents:
diff changeset
638 bufsize -= lwz_bytes;
6ee11bf9e3ea Initial revision
jcid
parents:
diff changeset
639 packet_size -= lwz_bytes;
6ee11bf9e3ea Initial revision
jcid
parents:
diff changeset
640 for (; lwz_bytes > 0; lwz_bytes--) {
6ee11bf9e3ea Initial revision
jcid
parents:
diff changeset
641 /* printf ("%d ", *buf) would print the depacketized lwz stream. */
6ee11bf9e3ea Initial revision
jcid
parents:
diff changeset
642
6ee11bf9e3ea Initial revision
jcid
parents:
diff changeset
643 /* Push the byte onto the "end" of the window (MSB). The low order
6ee11bf9e3ea Initial revision
jcid
parents:
diff changeset
644 * bits always come first in the LZW stream. */
6ee11bf9e3ea Initial revision
jcid
parents:
diff changeset
645 window = (window >> 8) | (*buf++ << 24);
6ee11bf9e3ea Initial revision
jcid
parents:
diff changeset
646 bits_in_window += 8;
6ee11bf9e3ea Initial revision
jcid
parents:
diff changeset
647
6ee11bf9e3ea Initial revision
jcid
parents:
diff changeset
648 while (bits_in_window >= code_size) {
6ee11bf9e3ea Initial revision
jcid
parents:
diff changeset
649 /* Extract the code. The code is code_size (3 to 12) bits long,
6ee11bf9e3ea Initial revision
jcid
parents:
diff changeset
650 * at the start of the window */
6ee11bf9e3ea Initial revision
jcid
parents:
diff changeset
651 code = (window >> (32 - bits_in_window)) & code_mask;
6ee11bf9e3ea Initial revision
jcid
parents:
diff changeset
652
359
b9142bae5429 - Switched from DEBUG_MSG to MSG.
jcid
parents: 335
diff changeset
653 _MSG("code = %d, ", code);
0
6ee11bf9e3ea Initial revision
jcid
parents:
diff changeset
654
6ee11bf9e3ea Initial revision
jcid
parents:
diff changeset
655 bits_in_window -= code_size;
6ee11bf9e3ea Initial revision
jcid
parents:
diff changeset
656 switch (Gif_process_code(gif, code, clear_code)) {
6ee11bf9e3ea Initial revision
jcid
parents:
diff changeset
657 case 1: /* Increment last code */
6ee11bf9e3ea Initial revision
jcid
parents:
diff changeset
658 gif->last_code++;
6ee11bf9e3ea Initial revision
jcid
parents:
diff changeset
659 /*gif->code_and_byte[gif->last_code+1]=0; */
6ee11bf9e3ea Initial revision
jcid
parents:
diff changeset
660
6ee11bf9e3ea Initial revision
jcid
parents:
diff changeset
661 if ((gif->last_code & code_mask) == 0) {
6ee11bf9e3ea Initial revision
jcid
parents:
diff changeset
662 if (gif->last_code == (1 << MAX_LWZ_BITS))
6ee11bf9e3ea Initial revision
jcid
parents:
diff changeset
663 gif->last_code--;
6ee11bf9e3ea Initial revision
jcid
parents:
diff changeset
664 else {
6ee11bf9e3ea Initial revision
jcid
parents:
diff changeset
665 code_size++;
6ee11bf9e3ea Initial revision
jcid
parents:
diff changeset
666 code_mask = (1 << code_size) - 1;
6ee11bf9e3ea Initial revision
jcid
parents:
diff changeset
667 }
6ee11bf9e3ea Initial revision
jcid
parents:
diff changeset
668 }
6ee11bf9e3ea Initial revision
jcid
parents:
diff changeset
669 break;
6ee11bf9e3ea Initial revision
jcid
parents:
diff changeset
670
6ee11bf9e3ea Initial revision
jcid
parents:
diff changeset
671 case 0: /* Reset codes size and mask */
6ee11bf9e3ea Initial revision
jcid
parents:
diff changeset
672 gif->last_code = clear_code + 1;
6ee11bf9e3ea Initial revision
jcid
parents:
diff changeset
673 code_size = gif->input_code_size + 1;
6ee11bf9e3ea Initial revision
jcid
parents:
diff changeset
674 code_mask = (1 << code_size) - 1;
6ee11bf9e3ea Initial revision
jcid
parents:
diff changeset
675 break;
6ee11bf9e3ea Initial revision
jcid
parents:
diff changeset
676
6ee11bf9e3ea Initial revision
jcid
parents:
diff changeset
677 case 2: /* End code... consume remaining data chunks..? */
6ee11bf9e3ea Initial revision
jcid
parents:
diff changeset
678 goto error; /* Could clean up better? */
6ee11bf9e3ea Initial revision
jcid
parents:
diff changeset
679 default:
6ee11bf9e3ea Initial revision
jcid
parents:
diff changeset
680 printf("dillo_gif_decode: error!\n");
6ee11bf9e3ea Initial revision
jcid
parents:
diff changeset
681 goto error;
6ee11bf9e3ea Initial revision
jcid
parents:
diff changeset
682 }
6ee11bf9e3ea Initial revision
jcid
parents:
diff changeset
683 }
6ee11bf9e3ea Initial revision
jcid
parents:
diff changeset
684 }
6ee11bf9e3ea Initial revision
jcid
parents:
diff changeset
685
6ee11bf9e3ea Initial revision
jcid
parents:
diff changeset
686 /* We reach here if
6ee11bf9e3ea Initial revision
jcid
parents:
diff changeset
687 * a) We have reached the end of the data block;
6ee11bf9e3ea Initial revision
jcid
parents:
diff changeset
688 * b) we ran out of data before reaching the end of the data block
6ee11bf9e3ea Initial revision
jcid
parents:
diff changeset
689 */
6ee11bf9e3ea Initial revision
jcid
parents:
diff changeset
690 if (bufsize <= 0)
6ee11bf9e3ea Initial revision
jcid
parents:
diff changeset
691 break; /* We are out of data; */
6ee11bf9e3ea Initial revision
jcid
parents:
diff changeset
692
6ee11bf9e3ea Initial revision
jcid
parents:
diff changeset
693 /* Start of new data block */
6ee11bf9e3ea Initial revision
jcid
parents:
diff changeset
694 bufsize--;
6ee11bf9e3ea Initial revision
jcid
parents:
diff changeset
695 if (!(packet_size = *buf++)) {
6ee11bf9e3ea Initial revision
jcid
parents:
diff changeset
696 /* This is the "block terminator" -- the last data block */
6ee11bf9e3ea Initial revision
jcid
parents:
diff changeset
697 gif->state = 999; /* BUG: should Go back to getting GIF blocks. */
6ee11bf9e3ea Initial revision
jcid
parents:
diff changeset
698 break;
6ee11bf9e3ea Initial revision
jcid
parents:
diff changeset
699 }
6ee11bf9e3ea Initial revision
jcid
parents:
diff changeset
700 }
6ee11bf9e3ea Initial revision
jcid
parents:
diff changeset
701
6ee11bf9e3ea Initial revision
jcid
parents:
diff changeset
702 gif->packet_size = packet_size;
6ee11bf9e3ea Initial revision
jcid
parents:
diff changeset
703 gif->window = window;
6ee11bf9e3ea Initial revision
jcid
parents:
diff changeset
704 gif->bits_in_window = bits_in_window;
6ee11bf9e3ea Initial revision
jcid
parents:
diff changeset
705 gif->code_size = code_size;
6ee11bf9e3ea Initial revision
jcid
parents:
diff changeset
706 return bsize - bufsize;
6ee11bf9e3ea Initial revision
jcid
parents:
diff changeset
707
6ee11bf9e3ea Initial revision
jcid
parents:
diff changeset
708 error:
6ee11bf9e3ea Initial revision
jcid
parents:
diff changeset
709 gif->state = 999;
6ee11bf9e3ea Initial revision
jcid
parents:
diff changeset
710 return bsize - bufsize;
6ee11bf9e3ea Initial revision
jcid
parents:
diff changeset
711 }
6ee11bf9e3ea Initial revision
jcid
parents:
diff changeset
712
6ee11bf9e3ea Initial revision
jcid
parents:
diff changeset
713 /*
6ee11bf9e3ea Initial revision
jcid
parents:
diff changeset
714 * ?
6ee11bf9e3ea Initial revision
jcid
parents:
diff changeset
715 */
6ee11bf9e3ea Initial revision
jcid
parents:
diff changeset
716 static int Gif_check_sig(DilloGif *gif, const uchar_t *ibuf, int ibsize)
6ee11bf9e3ea Initial revision
jcid
parents:
diff changeset
717 {
6ee11bf9e3ea Initial revision
jcid
parents:
diff changeset
718 /* at beginning of file - read magic number */
6ee11bf9e3ea Initial revision
jcid
parents:
diff changeset
719 if (ibsize < 6)
6ee11bf9e3ea Initial revision
jcid
parents:
diff changeset
720 return 0;
144
6ce351bab868 - Added a warning message for false GIF files.
jcid
parents: 35
diff changeset
721 if (memcmp(ibuf, "GIF87a", 6) != 0 &&
6ce351bab868 - Added a warning message for false GIF files.
jcid
parents: 35
diff changeset
722 memcmp(ibuf, "GIF89a", 6) != 0) {
6ce351bab868 - Added a warning message for false GIF files.
jcid
parents: 35
diff changeset
723 MSG_WARN("\"%s\" is not a GIF file.\n", URL_STR(gif->url));
0
6ee11bf9e3ea Initial revision
jcid
parents:
diff changeset
724 gif->state = 999;
6ee11bf9e3ea Initial revision
jcid
parents:
diff changeset
725 return 6;
6ee11bf9e3ea Initial revision
jcid
parents:
diff changeset
726 }
6ee11bf9e3ea Initial revision
jcid
parents:
diff changeset
727 gif->state = 1;
6ee11bf9e3ea Initial revision
jcid
parents:
diff changeset
728 return 6;
6ee11bf9e3ea Initial revision
jcid
parents:
diff changeset
729 }
6ee11bf9e3ea Initial revision
jcid
parents:
diff changeset
730
6ee11bf9e3ea Initial revision
jcid
parents:
diff changeset
731 /* Read the color map
6ee11bf9e3ea Initial revision
jcid
parents:
diff changeset
732 *
6ee11bf9e3ea Initial revision
jcid
parents:
diff changeset
733 * Implements, from the spec:
6ee11bf9e3ea Initial revision
jcid
parents:
diff changeset
734 * Global Color Table
6ee11bf9e3ea Initial revision
jcid
parents:
diff changeset
735 * Local Color Table
6ee11bf9e3ea Initial revision
jcid
parents:
diff changeset
736 */
6ee11bf9e3ea Initial revision
jcid
parents:
diff changeset
737 static inline size_t
6ee11bf9e3ea Initial revision
jcid
parents:
diff changeset
738 Gif_do_color_table(DilloGif *gif, void *Buf,
6ee11bf9e3ea Initial revision
jcid
parents:
diff changeset
739 const uchar_t *buf, size_t bsize, size_t CT_Size)
6ee11bf9e3ea Initial revision
jcid
parents:
diff changeset
740 {
6ee11bf9e3ea Initial revision
jcid
parents:
diff changeset
741 size_t Size = 3 * (1 << (1 + CT_Size));
6ee11bf9e3ea Initial revision
jcid
parents:
diff changeset
742
6ee11bf9e3ea Initial revision
jcid
parents:
diff changeset
743 if (Size > bsize)
6ee11bf9e3ea Initial revision
jcid
parents:
diff changeset
744 return 0;
6ee11bf9e3ea Initial revision
jcid
parents:
diff changeset
745
6ee11bf9e3ea Initial revision
jcid
parents:
diff changeset
746 gif->ColorMap_ofs = (ulong_t) buf - (ulong_t) Buf;
6ee11bf9e3ea Initial revision
jcid
parents:
diff changeset
747 gif->NumColors = (1 << (1 + CT_Size));
6ee11bf9e3ea Initial revision
jcid
parents:
diff changeset
748 return Size;
6ee11bf9e3ea Initial revision
jcid
parents:
diff changeset
749 }
6ee11bf9e3ea Initial revision
jcid
parents:
diff changeset
750
6ee11bf9e3ea Initial revision
jcid
parents:
diff changeset
751 /*
6ee11bf9e3ea Initial revision
jcid
parents:
diff changeset
752 * This implements, from the spec:
6ee11bf9e3ea Initial revision
jcid
parents:
diff changeset
753 * <Logical Screen> ::= Logical Screen Descriptor [Global Color Table]
6ee11bf9e3ea Initial revision
jcid
parents:
diff changeset
754 */
6ee11bf9e3ea Initial revision
jcid
parents:
diff changeset
755 static size_t Gif_get_descriptor(DilloGif *gif, void *Buf,
6ee11bf9e3ea Initial revision
jcid
parents:
diff changeset
756 const uchar_t *buf, int bsize)
6ee11bf9e3ea Initial revision
jcid
parents:
diff changeset
757 {
6ee11bf9e3ea Initial revision
jcid
parents:
diff changeset
758
6ee11bf9e3ea Initial revision
jcid
parents:
diff changeset
759 /* screen descriptor */
6ee11bf9e3ea Initial revision
jcid
parents:
diff changeset
760 size_t Size = 7, /* Size of descriptor */
6ee11bf9e3ea Initial revision
jcid
parents:
diff changeset
761 mysize; /* Size of color table */
6ee11bf9e3ea Initial revision
jcid
parents:
diff changeset
762 uchar_t Flags;
6ee11bf9e3ea Initial revision
jcid
parents:
diff changeset
763
6ee11bf9e3ea Initial revision
jcid
parents:
diff changeset
764 if (bsize < 7)
6ee11bf9e3ea Initial revision
jcid
parents:
diff changeset
765 return 0;
6ee11bf9e3ea Initial revision
jcid
parents:
diff changeset
766 Flags = buf[4];
6ee11bf9e3ea Initial revision
jcid
parents:
diff changeset
767
6ee11bf9e3ea Initial revision
jcid
parents:
diff changeset
768 if (Flags & LOCALCOLORMAP) {
6ee11bf9e3ea Initial revision
jcid
parents:
diff changeset
769 mysize = Gif_do_color_table(
6ee11bf9e3ea Initial revision
jcid
parents:
diff changeset
770 gif, Buf, buf + 7, (size_t)bsize - 7, Flags & (size_t)0x7);
6ee11bf9e3ea Initial revision
jcid
parents:
diff changeset
771 if (!mysize)
6ee11bf9e3ea Initial revision
jcid
parents:
diff changeset
772 return 0;
6ee11bf9e3ea Initial revision
jcid
parents:
diff changeset
773 Size += mysize; /* Size of the color table that follows */
6ee11bf9e3ea Initial revision
jcid
parents:
diff changeset
774 gif->Background = buf[5];
6ee11bf9e3ea Initial revision
jcid
parents:
diff changeset
775 }
6ee11bf9e3ea Initial revision
jcid
parents:
diff changeset
776 /* gif->Width = LM_to_uint(buf[0], buf[1]);
6ee11bf9e3ea Initial revision
jcid
parents:
diff changeset
777 gif->Height = LM_to_uint(buf[2], buf[3]); */
6ee11bf9e3ea Initial revision
jcid
parents:
diff changeset
778 gif->ColorResolution = (((buf[4] & 0x70) >> 3) + 1);
6ee11bf9e3ea Initial revision
jcid
parents:
diff changeset
779 /* gif->AspectRatio = buf[6]; */
6ee11bf9e3ea Initial revision
jcid
parents:
diff changeset
780
6ee11bf9e3ea Initial revision
jcid
parents:
diff changeset
781 return Size;
6ee11bf9e3ea Initial revision
jcid
parents:
diff changeset
782 }
6ee11bf9e3ea Initial revision
jcid
parents:
diff changeset
783
6ee11bf9e3ea Initial revision
jcid
parents:
diff changeset
784 /*
6ee11bf9e3ea Initial revision
jcid
parents:
diff changeset
785 * This implements, from the spec:
6ee11bf9e3ea Initial revision
jcid
parents:
diff changeset
786 * <Table-Based Image> ::= Image Descriptor [Local Color Table] Image Data
6ee11bf9e3ea Initial revision
jcid
parents:
diff changeset
787 *
6ee11bf9e3ea Initial revision
jcid
parents:
diff changeset
788 * ('Buf' points to just after the Image separator)
6ee11bf9e3ea Initial revision
jcid
parents:
diff changeset
789 * we should probably just check that the local stuff is consistent
6ee11bf9e3ea Initial revision
jcid
parents:
diff changeset
790 * with the stuff at the header. For now, we punt...
6ee11bf9e3ea Initial revision
jcid
parents:
diff changeset
791 */
6ee11bf9e3ea Initial revision
jcid
parents:
diff changeset
792 static size_t Gif_do_img_desc(DilloGif *gif, void *Buf,
6ee11bf9e3ea Initial revision
jcid
parents:
diff changeset
793 const uchar_t *buf, size_t bsize)
6ee11bf9e3ea Initial revision
jcid
parents:
diff changeset
794 {
6ee11bf9e3ea Initial revision
jcid
parents:
diff changeset
795 uchar_t Flags;
6ee11bf9e3ea Initial revision
jcid
parents:
diff changeset
796 size_t Size = 9 + 1; /* image descriptor size + first byte of image data */
6ee11bf9e3ea Initial revision
jcid
parents:
diff changeset
797
6ee11bf9e3ea Initial revision
jcid
parents:
diff changeset
798 if (bsize < 10)
6ee11bf9e3ea Initial revision
jcid
parents:
diff changeset
799 return 0;
6ee11bf9e3ea Initial revision
jcid
parents:
diff changeset
800
6ee11bf9e3ea Initial revision
jcid
parents:
diff changeset
801 gif->Width = LM_to_uint(buf[4], buf[5]);
6ee11bf9e3ea Initial revision
jcid
parents:
diff changeset
802 gif->Height = LM_to_uint(buf[6], buf[7]);
1180
e02128d96c8a Added image size sanity checks
Jorge Arellano Cid <jcid@dillo.org>
parents: 1094
diff changeset
803
e02128d96c8a Added image size sanity checks
Jorge Arellano Cid <jcid@dillo.org>
parents: 1094
diff changeset
804 /* check max image size */
1199
81c2d1c2e0f0 Image size sanity checks (part 1)
Jorge Arellano Cid <jcid@dillo.org>
parents: 1180
diff changeset
805 if (gif->Width <= 0 || gif->Height <= 0 ||
1202
f77f7973534e use IMAGE_MAX_AREA instead of IMAGE_MAX_W and IMAGE_MAX_H
Johannes Hofmann <Johannes.Hofmann@gmx.de>
parents: 1199
diff changeset
806 gif->Width > IMAGE_MAX_AREA / gif->Height) {
1964
7c7ff4d0202b clearer MSG for suspicious image size
corvid <corvid@lavabit.com>
parents: 1699
diff changeset
807 MSG("Gif_do_img_desc: suspicious image size request %u x %u\n",
1180
e02128d96c8a Added image size sanity checks
Jorge Arellano Cid <jcid@dillo.org>
parents: 1094
diff changeset
808 gif->Width, gif->Height);
e02128d96c8a Added image size sanity checks
Jorge Arellano Cid <jcid@dillo.org>
parents: 1094
diff changeset
809 gif->state = 999;
e02128d96c8a Added image size sanity checks
Jorge Arellano Cid <jcid@dillo.org>
parents: 1094
diff changeset
810 return 0;
e02128d96c8a Added image size sanity checks
Jorge Arellano Cid <jcid@dillo.org>
parents: 1094
diff changeset
811 }
e02128d96c8a Added image size sanity checks
Jorge Arellano Cid <jcid@dillo.org>
parents: 1094
diff changeset
812
0
6ee11bf9e3ea Initial revision
jcid
parents:
diff changeset
813 a_Dicache_set_parms(gif->url, gif->version, gif->Image,
6ee11bf9e3ea Initial revision
jcid
parents:
diff changeset
814 gif->Width, gif->Height, DILLO_IMG_TYPE_INDEXED);
6ee11bf9e3ea Initial revision
jcid
parents:
diff changeset
815
6ee11bf9e3ea Initial revision
jcid
parents:
diff changeset
816 Flags = buf[8];
6ee11bf9e3ea Initial revision
jcid
parents:
diff changeset
817
6ee11bf9e3ea Initial revision
jcid
parents:
diff changeset
818 gif->Flags |= Flags & INTERLACE;
6ee11bf9e3ea Initial revision
jcid
parents:
diff changeset
819 gif->pass = 0;
6ee11bf9e3ea Initial revision
jcid
parents:
diff changeset
820 bsize -= 9;
6ee11bf9e3ea Initial revision
jcid
parents:
diff changeset
821 buf += 9;
6ee11bf9e3ea Initial revision
jcid
parents:
diff changeset
822 if (Flags & LOCALCOLORMAP) {
6ee11bf9e3ea Initial revision
jcid
parents:
diff changeset
823 size_t LSize = Gif_do_color_table(
6ee11bf9e3ea Initial revision
jcid
parents:
diff changeset
824 gif, Buf, buf, bsize, Flags & (size_t)0x7);
6ee11bf9e3ea Initial revision
jcid
parents:
diff changeset
825
6ee11bf9e3ea Initial revision
jcid
parents:
diff changeset
826 if (!LSize)
6ee11bf9e3ea Initial revision
jcid
parents:
diff changeset
827 return 0;
6ee11bf9e3ea Initial revision
jcid
parents:
diff changeset
828 Size += LSize;
6ee11bf9e3ea Initial revision
jcid
parents:
diff changeset
829 buf += LSize;
6ee11bf9e3ea Initial revision
jcid
parents:
diff changeset
830 bsize -= LSize;
6ee11bf9e3ea Initial revision
jcid
parents:
diff changeset
831 }
6ee11bf9e3ea Initial revision
jcid
parents:
diff changeset
832 /* Finally, get the first byte of the LZW image data */
6ee11bf9e3ea Initial revision
jcid
parents:
diff changeset
833 if (bsize < 1)
6ee11bf9e3ea Initial revision
jcid
parents:
diff changeset
834 return 0;
6ee11bf9e3ea Initial revision
jcid
parents:
diff changeset
835 gif->input_code_size = *buf++;
6ee11bf9e3ea Initial revision
jcid
parents:
diff changeset
836 if (gif->input_code_size > 8) {
6ee11bf9e3ea Initial revision
jcid
parents:
diff changeset
837 gif->state = 999;
6ee11bf9e3ea Initial revision
jcid
parents:
diff changeset
838 return Size;
6ee11bf9e3ea Initial revision
jcid
parents:
diff changeset
839 }
6ee11bf9e3ea Initial revision
jcid
parents:
diff changeset
840 gif->y = 0;
6ee11bf9e3ea Initial revision
jcid
parents:
diff changeset
841 Gif_lwz_init(gif);
6ee11bf9e3ea Initial revision
jcid
parents:
diff changeset
842 gif->spill_line_index = 0;
2083
796ee3ef6426 Don't allocate gif->linebuf so soon.
corvid <corvid@lavabit.com>
parents: 1964
diff changeset
843 gif->linebuf = dMalloc(gif->Width);
0
6ee11bf9e3ea Initial revision
jcid
parents:
diff changeset
844 gif->state = 3; /*Process the lzw data next */
6ee11bf9e3ea Initial revision
jcid
parents:
diff changeset
845 if (gif->Image && gif->ColorMap_ofs) {
6ee11bf9e3ea Initial revision
jcid
parents:
diff changeset
846 a_Dicache_set_cmap(gif->url, gif->version, gif->Image,
6ee11bf9e3ea Initial revision
jcid
parents:
diff changeset
847 (uchar_t *) Buf + gif->ColorMap_ofs,
6ee11bf9e3ea Initial revision
jcid
parents:
diff changeset
848 gif->NumColors, 256, gif->transparent);
6ee11bf9e3ea Initial revision
jcid
parents:
diff changeset
849 }
6ee11bf9e3ea Initial revision
jcid
parents:
diff changeset
850 return Size;
6ee11bf9e3ea Initial revision
jcid
parents:
diff changeset
851 }
6ee11bf9e3ea Initial revision
jcid
parents:
diff changeset
852
6ee11bf9e3ea Initial revision
jcid
parents:
diff changeset
853 /* --- Top level data block processors ------------------------------------ */
6ee11bf9e3ea Initial revision
jcid
parents:
diff changeset
854 #define Img_Desc (0x2c)
6ee11bf9e3ea Initial revision
jcid
parents:
diff changeset
855 #define Trailer (0x3B)
6ee11bf9e3ea Initial revision
jcid
parents:
diff changeset
856 #define Ext_Id (0x21)
6ee11bf9e3ea Initial revision
jcid
parents:
diff changeset
857
6ee11bf9e3ea Initial revision
jcid
parents:
diff changeset
858 /*
6ee11bf9e3ea Initial revision
jcid
parents:
diff changeset
859 * This identifies which kind of GIF blocks are next, and processes them.
6ee11bf9e3ea Initial revision
jcid
parents:
diff changeset
860 * It returns if there isn't enough data to process the next blocks, or if
6ee11bf9e3ea Initial revision
jcid
parents:
diff changeset
861 * the next block is the lzw data (which is streamed differently)
6ee11bf9e3ea Initial revision
jcid
parents:
diff changeset
862 *
6ee11bf9e3ea Initial revision
jcid
parents:
diff changeset
863 * This implements, from the spec, <Data>* Trailer
6ee11bf9e3ea Initial revision
jcid
parents:
diff changeset
864 * <Data> ::= <Graphic Block> | <Special-Purpose Block>
6ee11bf9e3ea Initial revision
jcid
parents:
diff changeset
865 * <Special-Purpose Block> ::= Application Extension | Comment Extension
6ee11bf9e3ea Initial revision
jcid
parents:
diff changeset
866 * <Graphic Block> ::= [Graphic Control Extension] <Graphic-Rendering Block>
6ee11bf9e3ea Initial revision
jcid
parents:
diff changeset
867 * <Graphic-Rendering Block> ::= <Table-Based Image> | Plain Text Extension
6ee11bf9e3ea Initial revision
jcid
parents:
diff changeset
868 *
6ee11bf9e3ea Initial revision
jcid
parents:
diff changeset
869 * <Data>* --> GIF_Block
6ee11bf9e3ea Initial revision
jcid
parents:
diff changeset
870 * <Data> --> while (...)
6ee11bf9e3ea Initial revision
jcid
parents:
diff changeset
871 * <Special-Purpose Block> --> Gif_do_extension
6ee11bf9e3ea Initial revision
jcid
parents:
diff changeset
872 * Graphic Control Extension --> Gif_do_extension
6ee11bf9e3ea Initial revision
jcid
parents:
diff changeset
873 * Plain Text Extension --> Gif_do_extension
6ee11bf9e3ea Initial revision
jcid
parents:
diff changeset
874 * <Table-Based Image> --> Gif_do_img_desc
6ee11bf9e3ea Initial revision
jcid
parents:
diff changeset
875 *
6ee11bf9e3ea Initial revision
jcid
parents:
diff changeset
876 * Return Value
6ee11bf9e3ea Initial revision
jcid
parents:
diff changeset
877 * 0 if not enough data is present, otherwise the number of bytes
6ee11bf9e3ea Initial revision
jcid
parents:
diff changeset
878 * "consumed"
6ee11bf9e3ea Initial revision
jcid
parents:
diff changeset
879 */
6ee11bf9e3ea Initial revision
jcid
parents:
diff changeset
880 static size_t GIF_Block(DilloGif * gif, void *Buf,
6ee11bf9e3ea Initial revision
jcid
parents:
diff changeset
881 const uchar_t *buf, size_t bsize)
6ee11bf9e3ea Initial revision
jcid
parents:
diff changeset
882 {
6ee11bf9e3ea Initial revision
jcid
parents:
diff changeset
883 size_t Size = 0, mysize;
6ee11bf9e3ea Initial revision
jcid
parents:
diff changeset
884 uchar_t C;
6ee11bf9e3ea Initial revision
jcid
parents:
diff changeset
885
6ee11bf9e3ea Initial revision
jcid
parents:
diff changeset
886 if (bsize < 1)
6ee11bf9e3ea Initial revision
jcid
parents:
diff changeset
887 return 0;
6ee11bf9e3ea Initial revision
jcid
parents:
diff changeset
888 while (gif->state == 2) {
6ee11bf9e3ea Initial revision
jcid
parents:
diff changeset
889 if (bsize < 1)
6ee11bf9e3ea Initial revision
jcid
parents:
diff changeset
890 return Size;
6ee11bf9e3ea Initial revision
jcid
parents:
diff changeset
891 bsize--;
6ee11bf9e3ea Initial revision
jcid
parents:
diff changeset
892 switch (*buf++) {
6ee11bf9e3ea Initial revision
jcid
parents:
diff changeset
893 case Ext_Id:
6ee11bf9e3ea Initial revision
jcid
parents:
diff changeset
894 /* get the extension type */
6ee11bf9e3ea Initial revision
jcid
parents:
diff changeset
895 if (bsize < 2)
6ee11bf9e3ea Initial revision
jcid
parents:
diff changeset
896 return Size;
6ee11bf9e3ea Initial revision
jcid
parents:
diff changeset
897
6ee11bf9e3ea Initial revision
jcid
parents:
diff changeset
898 /* Have the extension block intepreted. */
6ee11bf9e3ea Initial revision
jcid
parents:
diff changeset
899 C = *buf++;
6ee11bf9e3ea Initial revision
jcid
parents:
diff changeset
900 bsize--;
6ee11bf9e3ea Initial revision
jcid
parents:
diff changeset
901 mysize = Gif_do_extension(gif, C, buf, bsize);
6ee11bf9e3ea Initial revision
jcid
parents:
diff changeset
902
6ee11bf9e3ea Initial revision
jcid
parents:
diff changeset
903 if (!mysize)
6ee11bf9e3ea Initial revision
jcid
parents:
diff changeset
904 /* Not all of the extension is there.. quit until more data
6ee11bf9e3ea Initial revision
jcid
parents:
diff changeset
905 * arrives */
6ee11bf9e3ea Initial revision
jcid
parents:
diff changeset
906 return Size;
6ee11bf9e3ea Initial revision
jcid
parents:
diff changeset
907
6ee11bf9e3ea Initial revision
jcid
parents:
diff changeset
908 bsize -= mysize;
6ee11bf9e3ea Initial revision
jcid
parents:
diff changeset
909 buf += mysize;
6ee11bf9e3ea Initial revision
jcid
parents:
diff changeset
910
6ee11bf9e3ea Initial revision
jcid
parents:
diff changeset
911 /* Increment the amount consumed by the extension introducer
6ee11bf9e3ea Initial revision
jcid
parents:
diff changeset
912 * and id, and extension block size */
6ee11bf9e3ea Initial revision
jcid
parents:
diff changeset
913 Size += mysize + 2;
6ee11bf9e3ea Initial revision
jcid
parents:
diff changeset
914 /* Do more GIF Blocks */
6ee11bf9e3ea Initial revision
jcid
parents:
diff changeset
915 continue;
6ee11bf9e3ea Initial revision
jcid
parents:
diff changeset
916
6ee11bf9e3ea Initial revision
jcid
parents:
diff changeset
917 case Img_Desc: /* Image descriptor */
6ee11bf9e3ea Initial revision
jcid
parents:
diff changeset
918 mysize = Gif_do_img_desc(gif, Buf, buf, bsize);
6ee11bf9e3ea Initial revision
jcid
parents:
diff changeset
919 if (!mysize)
6ee11bf9e3ea Initial revision
jcid
parents:
diff changeset
920 return Size;
6ee11bf9e3ea Initial revision
jcid
parents:
diff changeset
921
6ee11bf9e3ea Initial revision
jcid
parents:
diff changeset
922 /* Increment the amount consumed by the Image Separator and the
6ee11bf9e3ea Initial revision
jcid
parents:
diff changeset
923 * Resultant blocks */
6ee11bf9e3ea Initial revision
jcid
parents:
diff changeset
924 Size += 1 + mysize;
6ee11bf9e3ea Initial revision
jcid
parents:
diff changeset
925 return Size;
6ee11bf9e3ea Initial revision
jcid
parents:
diff changeset
926
6ee11bf9e3ea Initial revision
jcid
parents:
diff changeset
927 case Trailer:
6ee11bf9e3ea Initial revision
jcid
parents:
diff changeset
928 gif->state = 999; /* BUG: should close the rest of the file */
6ee11bf9e3ea Initial revision
jcid
parents:
diff changeset
929 return Size + 1;
6ee11bf9e3ea Initial revision
jcid
parents:
diff changeset
930 break; /* GIF terminator */
6ee11bf9e3ea Initial revision
jcid
parents:
diff changeset
931
6ee11bf9e3ea Initial revision
jcid
parents:
diff changeset
932 default: /* Unknown */
6ee11bf9e3ea Initial revision
jcid
parents:
diff changeset
933 /* gripe and complain */
6ee11bf9e3ea Initial revision
jcid
parents:
diff changeset
934 MSG ("gif.c::GIF_Block: Error, 0x%x found\n", *(buf-1));
6ee11bf9e3ea Initial revision
jcid
parents:
diff changeset
935 gif->state = 999;
6ee11bf9e3ea Initial revision
jcid
parents:
diff changeset
936 return Size + 1;
6ee11bf9e3ea Initial revision
jcid
parents:
diff changeset
937 }
6ee11bf9e3ea Initial revision
jcid
parents:
diff changeset
938 }
6ee11bf9e3ea Initial revision
jcid
parents:
diff changeset
939 return Size;
6ee11bf9e3ea Initial revision
jcid
parents:
diff changeset
940 }
6ee11bf9e3ea Initial revision
jcid
parents:
diff changeset
941
6ee11bf9e3ea Initial revision
jcid
parents:
diff changeset
942
6ee11bf9e3ea Initial revision
jcid
parents:
diff changeset
943 /*
6ee11bf9e3ea Initial revision
jcid
parents:
diff changeset
944 * Process some bytes from the input gif stream. It's a state machine.
6ee11bf9e3ea Initial revision
jcid
parents:
diff changeset
945 *
6ee11bf9e3ea Initial revision
jcid
parents:
diff changeset
946 * From the GIF spec:
6ee11bf9e3ea Initial revision
jcid
parents:
diff changeset
947 * <GIF Data Stream> ::= Header <Logical Screen> <Data>* Trailer
6ee11bf9e3ea Initial revision
jcid
parents:
diff changeset
948 *
6ee11bf9e3ea Initial revision
jcid
parents:
diff changeset
949 * <GIF Data Stream> --> Gif_process_bytes
6ee11bf9e3ea Initial revision
jcid
parents:
diff changeset
950 * Header --> State 0
6ee11bf9e3ea Initial revision
jcid
parents:
diff changeset
951 * <Logical Screen> --> State 1
6ee11bf9e3ea Initial revision
jcid
parents:
diff changeset
952 * <Data>* --> State 2
6ee11bf9e3ea Initial revision
jcid
parents:
diff changeset
953 * Trailer --> State > 3
6ee11bf9e3ea Initial revision
jcid
parents:
diff changeset
954 *
6ee11bf9e3ea Initial revision
jcid
parents:
diff changeset
955 * State == 3 is special... this is inside of <Data> but all of the stuff in
6ee11bf9e3ea Initial revision
jcid
parents:
diff changeset
956 * there has been gotten and set up. So we stream it outside.
6ee11bf9e3ea Initial revision
jcid
parents:
diff changeset
957 */
6ee11bf9e3ea Initial revision
jcid
parents:
diff changeset
958 static size_t Gif_process_bytes(DilloGif *gif, const uchar_t *ibuf,
6ee11bf9e3ea Initial revision
jcid
parents:
diff changeset
959 int bufsize, void *Buf)
6ee11bf9e3ea Initial revision
jcid
parents:
diff changeset
960 {
6ee11bf9e3ea Initial revision
jcid
parents:
diff changeset
961 int tmp_bufsize = bufsize;
6ee11bf9e3ea Initial revision
jcid
parents:
diff changeset
962 size_t mysize;
6ee11bf9e3ea Initial revision
jcid
parents:
diff changeset
963
6ee11bf9e3ea Initial revision
jcid
parents:
diff changeset
964 switch (gif->state) {
6ee11bf9e3ea Initial revision
jcid
parents:
diff changeset
965 case 0:
6ee11bf9e3ea Initial revision
jcid
parents:
diff changeset
966 mysize = Gif_check_sig(gif, ibuf, tmp_bufsize);
6ee11bf9e3ea Initial revision
jcid
parents:
diff changeset
967 if (!mysize)
6ee11bf9e3ea Initial revision
jcid
parents:
diff changeset
968 break;
6ee11bf9e3ea Initial revision
jcid
parents:
diff changeset
969 tmp_bufsize -= mysize;
6ee11bf9e3ea Initial revision
jcid
parents:
diff changeset
970 ibuf += mysize;
6ee11bf9e3ea Initial revision
jcid
parents:
diff changeset
971 if (gif->state != 1)
6ee11bf9e3ea Initial revision
jcid
parents:
diff changeset
972 break;
6ee11bf9e3ea Initial revision
jcid
parents:
diff changeset
973
6ee11bf9e3ea Initial revision
jcid
parents:
diff changeset
974 case 1:
6ee11bf9e3ea Initial revision
jcid
parents:
diff changeset
975 mysize = Gif_get_descriptor(gif, Buf, ibuf, tmp_bufsize);
6ee11bf9e3ea Initial revision
jcid
parents:
diff changeset
976 if (!mysize)
6ee11bf9e3ea Initial revision
jcid
parents:
diff changeset
977 break;
6ee11bf9e3ea Initial revision
jcid
parents:
diff changeset
978 tmp_bufsize -= mysize;
6ee11bf9e3ea Initial revision
jcid
parents:
diff changeset
979 ibuf += mysize;
6ee11bf9e3ea Initial revision
jcid
parents:
diff changeset
980 gif->state = 2;
6ee11bf9e3ea Initial revision
jcid
parents:
diff changeset
981
6ee11bf9e3ea Initial revision
jcid
parents:
diff changeset
982 case 2:
6ee11bf9e3ea Initial revision
jcid
parents:
diff changeset
983 /* Ok, this loop construction looks weird. It implements the <Data>* of
6ee11bf9e3ea Initial revision
jcid
parents:
diff changeset
984 * the GIF grammar. All sorts of stuff is allocated to set up for the
6ee11bf9e3ea Initial revision
jcid
parents:
diff changeset
985 * decode part (state ==2) and then there is the actual decode part (3)
6ee11bf9e3ea Initial revision
jcid
parents:
diff changeset
986 */
6ee11bf9e3ea Initial revision
jcid
parents:
diff changeset
987 mysize = GIF_Block(gif, Buf, ibuf, (size_t)tmp_bufsize);
6ee11bf9e3ea Initial revision
jcid
parents:
diff changeset
988 if (!mysize)
6ee11bf9e3ea Initial revision
jcid
parents:
diff changeset
989 break;
6ee11bf9e3ea Initial revision
jcid
parents:
diff changeset
990 tmp_bufsize -= mysize;
6ee11bf9e3ea Initial revision
jcid
parents:
diff changeset
991 ibuf += mysize;
6ee11bf9e3ea Initial revision
jcid
parents:
diff changeset
992 if (gif->state != 3)
6ee11bf9e3ea Initial revision
jcid
parents:
diff changeset
993 break;
6ee11bf9e3ea Initial revision
jcid
parents:
diff changeset
994
6ee11bf9e3ea Initial revision
jcid
parents:
diff changeset
995 case 3:
6ee11bf9e3ea Initial revision
jcid
parents:
diff changeset
996 /* get an image byte */
6ee11bf9e3ea Initial revision
jcid
parents:
diff changeset
997 /* The users sees all of this stuff */
6ee11bf9e3ea Initial revision
jcid
parents:
diff changeset
998 mysize = Gif_decode(gif, ibuf, (size_t)tmp_bufsize);
6ee11bf9e3ea Initial revision
jcid
parents:
diff changeset
999 if (mysize == 0)
6ee11bf9e3ea Initial revision
jcid
parents:
diff changeset
1000 break;
6ee11bf9e3ea Initial revision
jcid
parents:
diff changeset
1001 ibuf += mysize;
6ee11bf9e3ea Initial revision
jcid
parents:
diff changeset
1002 tmp_bufsize -= mysize;
6ee11bf9e3ea Initial revision
jcid
parents:
diff changeset
1003
6ee11bf9e3ea Initial revision
jcid
parents:
diff changeset
1004 default:
6ee11bf9e3ea Initial revision
jcid
parents:
diff changeset
1005 /* error - just consume all input */
6ee11bf9e3ea Initial revision
jcid
parents:
diff changeset
1006 tmp_bufsize = 0;
6ee11bf9e3ea Initial revision
jcid
parents:
diff changeset
1007 break;
6ee11bf9e3ea Initial revision
jcid
parents:
diff changeset
1008 }
6ee11bf9e3ea Initial revision
jcid
parents:
diff changeset
1009
359
b9142bae5429 - Switched from DEBUG_MSG to MSG.
jcid
parents: 335
diff changeset
1010 _MSG("Gif_process_bytes: final state %d, %ld bytes consumed\n",
b9142bae5429 - Switched from DEBUG_MSG to MSG.
jcid
parents: 335
diff changeset
1011 gif->state, (long)(bufsize - tmp_bufsize));
0
6ee11bf9e3ea Initial revision
jcid
parents:
diff changeset
1012
6ee11bf9e3ea Initial revision
jcid
parents:
diff changeset
1013 return bufsize - tmp_bufsize;
6ee11bf9e3ea Initial revision
jcid
parents:
diff changeset
1014 }
6ee11bf9e3ea Initial revision
jcid
parents:
diff changeset
1015
874
6828b4d19d69 Set dicache as MIME dispatcher for image/{gif,jpg,png}. +refactor and cleanups
Jorge Arellano Cid <jcid@dillo.org>
parents: 768
diff changeset
1016 #else /* ENABLE_GIF */
6828b4d19d69 Set dicache as MIME dispatcher for image/{gif,jpg,png}. +refactor and cleanups
Jorge Arellano Cid <jcid@dillo.org>
parents: 768
diff changeset
1017
6828b4d19d69 Set dicache as MIME dispatcher for image/{gif,jpg,png}. +refactor and cleanups
Jorge Arellano Cid <jcid@dillo.org>
parents: 768
diff changeset
1018 void *a_Gif_new() { return 0; }
6828b4d19d69 Set dicache as MIME dispatcher for image/{gif,jpg,png}. +refactor and cleanups
Jorge Arellano Cid <jcid@dillo.org>
parents: 768
diff changeset
1019 void a_Gif_callback() { return; }
6828b4d19d69 Set dicache as MIME dispatcher for image/{gif,jpg,png}. +refactor and cleanups
Jorge Arellano Cid <jcid@dillo.org>
parents: 768
diff changeset
1020
0
6ee11bf9e3ea Initial revision
jcid
parents:
diff changeset
1021 #endif /* ENABLE_GIF */