65 }
66
67 /* These macro help to ensure that we only take part of frame that fits into
68 logical screen. */
69
70 /* Ensure that p belongs to [pmin, pmax) interval. Returns fixed point (if fix is needed) */
71 #define FIX_POINT(p, pmin, pmax) ( ((p) < (pmin)) ? (pmin) : (((p) > (pmax)) ? (pmax) : (p)))
72 /* Ensures that line starting at point p does not exceed boundary pmax.
73 Returns fixed length (if fix is needed) */
74 #define FIX_LENGTH(p, len, pmax) ( ((p) + (len)) > (pmax) ? ((pmax) - (p)) : (len))
75
76 int
77 SplashDecodeGif(Splash * splash, GifFileType * gif)
78 {
79 int stride;
80 int bufferSize;
81 byte_t *pBitmapBits, *pOldBitmapBits;
82 int i, j;
83 int imageIndex;
84 int cx, cy, cw, ch; /* clamped coordinates */
85 int numLines;
86 int numPassLines;
87
88 if (DGifSlurp(gif) == GIF_ERROR) {
89 return 0;
90 }
91
92 SplashCleanup(splash);
93
94 if (!SAFE_TO_ALLOC(gif->SWidth, splash->imageFormat.depthBytes)) {
95 return 0;
96 }
97 stride = gif->SWidth * splash->imageFormat.depthBytes;
98 if (splash->byteAlignment > 1)
99 stride =
100 (stride + splash->byteAlignment - 1) & ~(splash->byteAlignment - 1);
101
102 if (!SAFE_TO_ALLOC(gif->SHeight, stride)) {
103 return 0;
104 }
105
106 if (!SAFE_TO_ALLOC(gif->ImageCount, sizeof(SplashImage*))) {
196 (pExtension[1] | (((int)pExtension[2]) << 8)) - 1;
197 }
198 }
199 break;
200 }
201 default:
202 break;
203 }
204 }
205
206 if (colorMap) {
207 for (i = 0; i < colorCount; i++) {
208 colorMapBuf[i] = MAKE_QUAD_GIF(colorMap->Colors[i], 0xff);
209 }
210 }
211 {
212
213 byte_t *pSrc = image->RasterBits;
214 ImageFormat srcFormat;
215 ImageRect srcRect, dstRect;
216
217 srcFormat.colorMap = colorMapBuf;
218 srcFormat.depthBytes = 1;
219 srcFormat.byteOrder = BYTE_ORDER_NATIVE;
220 srcFormat.transparentColor = transparentColor;
221 srcFormat.fixedBits = QUAD_ALPHA_MASK; // fixed 100% alpha
222 srcFormat.premultiplied = 0;
223
224 /* Number of source lines for current pass */
225 numPassLines = desc->Height;
226 /* Number of lines that fits to dest buffer */
227 numLines = ch;
228
229 initRect(&srcRect, 0, 0, desc->Width, numLines, 1,
230 desc->Width, pSrc, &srcFormat);
231
232 if (numLines > 0) {
233 initRect(&dstRect, cx, cy, cw,
234 numLines , 1, stride, pBitmapBits, &splash->imageFormat);
235
236 pSrc += convertRect(&srcRect, &dstRect, CVT_ALPHATEST);
237 }
238 // skip extra source data
239 pSrc += (numPassLines - numLines) * srcRect.stride;
240 }
241
242 // now dispose of the previous frame correctly
243
244 splash->frames[imageIndex].bitmapBits =
245 (rgbquad_t *) malloc(bufferSize); // bufferSize is safe (checked above)
246 if (!splash->frames[imageIndex].bitmapBits) {
247 free(pBitmapBits);
248 free(pOldBitmapBits);
249 /* Assuming that callee will take care of splash frames we have already allocated */
250 return 0;
251 }
252 memcpy(splash->frames[imageIndex].bitmapBits, pBitmapBits, bufferSize);
253
254 SplashInitFrameShape(splash, imageIndex);
255
256 splash->frames[imageIndex].delay = frameDelay * 10; // 100ths of second to milliseconds
257 switch (disposeMethod) {
258 case GIF_DISPOSE_LEAVE:
259 memcpy(pOldBitmapBits, pBitmapBits, bufferSize);
260 break;
279 case GIF_DISPOSE_RESTORE:
280 {
281 int lineSize = cw * splash->imageFormat.depthBytes;
282 if (lineSize > 0) {
283 int lineOffset = cx * splash->imageFormat.depthBytes;
284 int lineIndex = cy * stride + lineOffset;
285 for (j=0; j<ch; j++) {
286 memcpy(pBitmapBits + lineIndex, pOldBitmapBits + lineIndex,
287 lineSize);
288 lineIndex += stride;
289 }
290 }
291 }
292 break;
293 }
294 }
295
296 free(pBitmapBits);
297 free(pOldBitmapBits);
298
299 DGifCloseFile(gif, NULL);
300
301 return 1;
302 }
303
304 int
305 SplashDecodeGifStream(Splash * splash, SplashStream * stream)
306 {
307 GifFileType *gif = DGifOpen((void *) stream, SplashStreamGifInputFunc, NULL);
308
309 if (!gif)
310 return 0;
311 return SplashDecodeGif(splash, gif);
312 }
|
65 }
66
67 /* These macro help to ensure that we only take part of frame that fits into
68 logical screen. */
69
70 /* Ensure that p belongs to [pmin, pmax) interval. Returns fixed point (if fix is needed) */
71 #define FIX_POINT(p, pmin, pmax) ( ((p) < (pmin)) ? (pmin) : (((p) > (pmax)) ? (pmax) : (p)))
72 /* Ensures that line starting at point p does not exceed boundary pmax.
73 Returns fixed length (if fix is needed) */
74 #define FIX_LENGTH(p, len, pmax) ( ((p) + (len)) > (pmax) ? ((pmax) - (p)) : (len))
75
76 int
77 SplashDecodeGif(Splash * splash, GifFileType * gif)
78 {
79 int stride;
80 int bufferSize;
81 byte_t *pBitmapBits, *pOldBitmapBits;
82 int i, j;
83 int imageIndex;
84 int cx, cy, cw, ch; /* clamped coordinates */
85 const int interlacedOffset[] = { 0, 4, 2, 1, 0 }; /* The way Interlaced image should. */
86 const int interlacedJumps[] = { 8, 8, 4, 2, 1 }; /* be read - offsets and jumps... */
87
88 if (DGifSlurp(gif) == GIF_ERROR) {
89 return 0;
90 }
91
92 SplashCleanup(splash);
93
94 if (!SAFE_TO_ALLOC(gif->SWidth, splash->imageFormat.depthBytes)) {
95 return 0;
96 }
97 stride = gif->SWidth * splash->imageFormat.depthBytes;
98 if (splash->byteAlignment > 1)
99 stride =
100 (stride + splash->byteAlignment - 1) & ~(splash->byteAlignment - 1);
101
102 if (!SAFE_TO_ALLOC(gif->SHeight, stride)) {
103 return 0;
104 }
105
106 if (!SAFE_TO_ALLOC(gif->ImageCount, sizeof(SplashImage*))) {
196 (pExtension[1] | (((int)pExtension[2]) << 8)) - 1;
197 }
198 }
199 break;
200 }
201 default:
202 break;
203 }
204 }
205
206 if (colorMap) {
207 for (i = 0; i < colorCount; i++) {
208 colorMapBuf[i] = MAKE_QUAD_GIF(colorMap->Colors[i], 0xff);
209 }
210 }
211 {
212
213 byte_t *pSrc = image->RasterBits;
214 ImageFormat srcFormat;
215 ImageRect srcRect, dstRect;
216 int pass = 4, npass = 5;
217
218 #if GIFLIB_MAJOR < 5
219 /* Interlaced gif support is broken in giflib < 5
220 so we need to work around this */
221 if (desc->Interlace) {
222 pass = 0;
223 npass = 4;
224 }
225 #endif
226
227 srcFormat.colorMap = colorMapBuf;
228 srcFormat.depthBytes = 1;
229 srcFormat.byteOrder = BYTE_ORDER_NATIVE;
230 srcFormat.transparentColor = transparentColor;
231 srcFormat.fixedBits = QUAD_ALPHA_MASK; // fixed 100% alpha
232 srcFormat.premultiplied = 0;
233
234 for (; pass < npass; ++pass) {
235 int jump = interlacedJumps[pass];
236 int ofs = interlacedOffset[pass];
237 /* Number of source lines for current pass */
238 int numPassLines = (desc->Height + jump - ofs - 1) / jump;
239 /* Number of lines that fits to dest buffer */
240 int numLines = (ch + jump - ofs - 1) / jump;
241
242 initRect(&srcRect, 0, 0, desc->Width, numLines, 1,
243 desc->Width, pSrc, &srcFormat);
244
245 if (numLines > 0) {
246 initRect(&dstRect, cx, cy + ofs, cw,
247 numLines , jump, stride, pBitmapBits, &splash->imageFormat);
248
249 pSrc += convertRect(&srcRect, &dstRect, CVT_ALPHATEST);
250 }
251 // skip extra source data
252 pSrc += (numPassLines - numLines) * srcRect.stride;
253 }
254 }
255
256 // now dispose of the previous frame correctly
257
258 splash->frames[imageIndex].bitmapBits =
259 (rgbquad_t *) malloc(bufferSize); // bufferSize is safe (checked above)
260 if (!splash->frames[imageIndex].bitmapBits) {
261 free(pBitmapBits);
262 free(pOldBitmapBits);
263 /* Assuming that callee will take care of splash frames we have already allocated */
264 return 0;
265 }
266 memcpy(splash->frames[imageIndex].bitmapBits, pBitmapBits, bufferSize);
267
268 SplashInitFrameShape(splash, imageIndex);
269
270 splash->frames[imageIndex].delay = frameDelay * 10; // 100ths of second to milliseconds
271 switch (disposeMethod) {
272 case GIF_DISPOSE_LEAVE:
273 memcpy(pOldBitmapBits, pBitmapBits, bufferSize);
274 break;
293 case GIF_DISPOSE_RESTORE:
294 {
295 int lineSize = cw * splash->imageFormat.depthBytes;
296 if (lineSize > 0) {
297 int lineOffset = cx * splash->imageFormat.depthBytes;
298 int lineIndex = cy * stride + lineOffset;
299 for (j=0; j<ch; j++) {
300 memcpy(pBitmapBits + lineIndex, pOldBitmapBits + lineIndex,
301 lineSize);
302 lineIndex += stride;
303 }
304 }
305 }
306 break;
307 }
308 }
309
310 free(pBitmapBits);
311 free(pOldBitmapBits);
312
313 #if GIFLIB_MAJOR > 5 || (GIFLIB_MAJOR == 5 && GIFLIB_MINOR >= 1)
314 if (DGifCloseFile(gif, NULL) == GIF_ERROR) {
315 return 0;
316 }
317 #else
318 DGifCloseFile(gif);
319 #endif
320
321 return 1;
322 }
323
324 int
325 SplashDecodeGifStream(Splash * splash, SplashStream * stream)
326 {
327 #if GIFLIB_MAJOR >= 5
328 GifFileType *gif = DGifOpen((void *) stream, SplashStreamGifInputFunc, NULL);
329 #else
330 GifFileType *gif = DGifOpen((void *) stream, SplashStreamGifInputFunc);
331 #endif
332
333 if (!gif)
334 return 0;
335 return SplashDecodeGif(splash, gif);
336 }
|