r4422 dynis - /branches/dynis/libnsgif/libnsgif.c
by netsurf@semichrome.net
Author: dynis
Date: Sun Jun 22 12:17:04 2008
New Revision: 4422
URL: http://source.netsurf-browser.org?rev=4422&view=rev
Log:
Added consistency in the way block-data is skipped; corrected a buffering error that was causing some gif images to throw errors
Modified:
branches/dynis/libnsgif/libnsgif.c
Modified: branches/dynis/libnsgif/libnsgif.c
URL: http://source.netsurf-browser.org/branches/dynis/libnsgif/libnsgif.c?rev=...
==============================================================================
--- branches/dynis/libnsgif/libnsgif.c (original)
+++ branches/dynis/libnsgif/libnsgif.c Sun Jun 22 12:17:04 2008
@@ -450,24 +450,27 @@
else
gif_data += (3 + extension_size);
- /* Skip all the sub-blocks
- */
- while (gif_data[0] != 0x00)
- gif_data += gif_data[0] + 1;
- gif_data++;
+ /* Repeatedly skip blocks until we get a zero block or run out of data
+ * This library does not process this data
+ */
+ block_size = 0;
+ while (block_size != 1) {
+ block_size = gif_data[0] + 1;
+ if ((gif_bytes -= block_size) < 0)
+ return GIF_INSUFFICIENT_FRAME_DATA;
+ gif_data += block_size;
+ }
}
/* Check if we've finished
*/
- gif_bytes = (gif_end - gif_data);
- if (gif_bytes < 1)
+ if ((gif_bytes = (gif_end - gif_data)) < 1)
return GIF_INSUFFICIENT_FRAME_DATA;
- else
- if (gif_data[0] == GIF_TRAILER) {
- gif->buffer_position = gif_data - gif->gif_data;
- gif->frame_count = frame + 1;
- return 1;
- }
+ else if (gif_data[0] == GIF_TRAILER) {
+ gif->buffer_position = gif_data - gif->gif_data;
+ gif->frame_count = frame + 1;
+ return 1;
+ }
/* If we're not done, there should be an image descriptor
*/
@@ -549,8 +552,6 @@
*/
block_size = 0;
while (block_size != 1) {
- /* Skip the block data
- */
block_size = gif_data[0] + 1;
if ((gif_bytes -= block_size) < 0)
return GIF_INSUFFICIENT_FRAME_DATA;
@@ -700,17 +701,24 @@
gif_data += 2;
else
gif_data += (3 + extension_size);
-
- /* Skip all the sub-blocks
- */
- while (gif_data[0] != 0x00)
- gif_data += gif_data[0] + 1;
- gif_data++;
+
+ /* Repeatedly skip blocks until we get a zero block or run out of data
+ * This library does not process this data
+ */
+ block_size = 0;
+ while (block_size != 1) {
+ block_size = gif_data[0] + 1;
+ if ((gif_bytes -= block_size) < 0) {
+ return_value = GIF_INSUFFICIENT_FRAME_DATA;
+ goto gif_decode_frame_exit;
+ }
+ gif_data += block_size;
+ }
}
/* Ensure we have enough data for the 10-byte image descriptor + 1-byte gif trailer
*/
- if ((gif_bytes = (gif_end - gif_data)) < 12) {
+ if (gif_bytes < 12) {
return_value = GIF_INSUFFICIENT_FRAME_DATA;
break;
}
@@ -876,8 +884,6 @@
gif_data = gif->gif_data + gif->buffer_size;
block_size = 0;
while (block_size != 1) {
- /* Skip the block data
- */
block_size = gif_data[0] + 1;
if ((gif_bytes -= block_size) < 0) {
return_value = GIF_INSUFFICIENT_FRAME_DATA;
@@ -887,12 +893,12 @@
}
}
gif_decode_frame_exit:
-
/* Check for end of data
*/
+ gif->buffer_position++;
gif_bytes = gif->buffer_size - gif->buffer_position;
+ gif_data = gif->gif_data + gif->buffer_position;
more_images &= !((gif_bytes < 1) || (gif_data[0] == GIF_TRAILER));
- gif->buffer_position++;
}
/* Check if we should test for optimisation
14 years, 11 months
r4420 bursa - /branches/dynis/libnsgif/examples/decode_gif.c
by netsurf@semichrome.net
Author: bursa
Date: Sun Jun 22 10:52:42 2008
New Revision: 4420
URL: http://source.netsurf-browser.org?rev=4420&view=rev
Log:
Try and display the GIF anyway if an error code is returned.
Modified:
branches/dynis/libnsgif/examples/decode_gif.c
Modified: branches/dynis/libnsgif/examples/decode_gif.c
URL: http://source.netsurf-browser.org/branches/dynis/libnsgif/examples/decode...
==============================================================================
--- branches/dynis/libnsgif/examples/decode_gif.c (original)
+++ branches/dynis/libnsgif/examples/decode_gif.c Sun Jun 22 10:52:42 2008
@@ -27,7 +27,7 @@
#include <libnsgif.h>
char *load_file(const char *path, size_t *data_size);
-void die(const char *context, int code);
+void warning(const char *context, int code);
void *bitmap_create(int width, int height);
void bitmap_set_opaque(void *bitmap, bool opaque);
bool bitmap_test_opaque(void *bitmap);
@@ -70,7 +70,7 @@
do {
code = gif_initialise(&gif, &bitmap_callbacks);
if (code != 0 && code != 1)
- die("gif_initialise", code);
+ warning("gif_initialise", code);
} while (code != 1);
printf("P3\n");
@@ -90,7 +90,7 @@
code = gif_decode_frame(&gif, i, &bitmap_callbacks);
if (code != 0)
- die("gif_decode_frame", code);
+ warning("gif_decode_frame", code);
printf("# frame %u:\n", i);
image = (char *) gif.frame_image;
@@ -150,7 +150,7 @@
}
-void die(const char *context, int code)
+void warning(const char *context, int code)
{
fprintf(stderr, "%s failed: ", context);
switch (code)
@@ -175,7 +175,6 @@
break;
}
fprintf(stderr, "\n");
- exit(EXIT_FAILURE);
}
14 years, 11 months
r4419 dynis - /branches/dynis/libnsgif/libnsgif.c
by netsurf@semichrome.net
Author: dynis
Date: Sun Jun 22 03:34:13 2008
New Revision: 4419
URL: http://source.netsurf-browser.org?rev=4419&view=rev
Log:
Updated references to a #define variable that is now uppercase
Modified:
branches/dynis/libnsgif/libnsgif.c
Modified: branches/dynis/libnsgif/libnsgif.c
URL: http://source.netsurf-browser.org/branches/dynis/libnsgif/libnsgif.c?rev=...
==============================================================================
--- branches/dynis/libnsgif/libnsgif.c (original)
+++ branches/dynis/libnsgif/libnsgif.c Sun Jun 22 03:34:13 2008
@@ -368,7 +368,7 @@
/* Check if we've finished
*/
- if ((gif_bytes > 0) && (gif_data[0] == gif_trailer)) return 1;
+ if ((gif_bytes > 0) && (gif_data[0] == GIF_TRAILER)) return 1;
/* Check if we have enough data
* The shortest block of data is a 4-byte comment extension + 1-byte block terminator + 1-byte gif trailer
@@ -463,7 +463,7 @@
if (gif_bytes < 1)
return GIF_INSUFFICIENT_FRAME_DATA;
else
- if (gif_data[0] == gif_trailer) {
+ if (gif_data[0] == GIF_TRAILER) {
gif->buffer_position = gif_data - gif->gif_data;
gif->frame_count = frame + 1;
return 1;
@@ -785,7 +785,7 @@
if (gif_bytes < 1) {
return_value = GIF_INSUFFICIENT_FRAME_DATA;
break;
- } else if (gif_data[0] == gif_trailer) {
+ } else if (gif_data[0] == GIF_TRAILER) {
return_value = 1;
break;
}
@@ -800,7 +800,7 @@
break;
/* If we only have the 1-byte LZW code size + 1-byte gif trailer, we're finished
*/
- } else if ((gif_bytes = 2) && (gif_data[1] == gif_trailer)) {
+ } else if ((gif_bytes = 2) && (gif_data[1] == GIF_TRAILER)) {
return_value = 1;
break;
}
14 years, 11 months
r4418 dynis - /branches/dynis/libnsgif/libnsgif.c
by netsurf@semichrome.net
Author: dynis
Date: Sun Jun 22 03:30:04 2008
New Revision: 4418
URL: http://source.netsurf-browser.org?rev=4418&view=rev
Log:
Corrected support for GIF comment extension and frames without image data
Modified:
branches/dynis/libnsgif/libnsgif.c
Modified: branches/dynis/libnsgif/libnsgif.c
URL: http://source.netsurf-browser.org/branches/dynis/libnsgif/libnsgif.c?rev=...
==============================================================================
--- branches/dynis/libnsgif/libnsgif.c (original)
+++ branches/dynis/libnsgif/libnsgif.c Sun Jun 22 03:30:04 2008
@@ -396,6 +396,7 @@
start off with one frame allocated so we can always use realloc.
*/
gif->frames[frame].frame_pointer = gif->buffer_position;
+ gif->frames[frame].display = false;
gif->frames[frame].virgin = true;
gif->frames[frame].frame_delay = 100;
gif->frames[frame].redraw_required = false;
@@ -439,8 +440,15 @@
}
/* Move to the first sub-block
- */
- gif_data += 2;
+ * Skip 3 bytes for extension introducer, label, and extension size fields
+ * Skip the extension size itself
+ * The special case here is the comment extension (0xfe) because it has no
+ * size field and therefore extension size is not skipped either
+ */
+ if (gif_data[1] == 0xfe)
+ gif_data += 2;
+ else
+ gif_data += (3 + extension_size);
/* Skip all the sub-blocks
*/
@@ -553,6 +561,7 @@
*/
gif->buffer_position = gif_data - gif->gif_data;
gif->frame_count = frame + 1;
+ gif->frames[frame].display = true;
more_images &= !((gif_bytes < 1) || (gif_data[0] == GIF_TRAILER));
}
@@ -573,6 +582,8 @@
GIF_DATA_ERROR for GIF error (invalid frame header)
GIF_INSUFFICIENT_DATA for insufficient data to do anything
0 for successful decoding
+ If a frame does not contain any image data, 0 is returned and
+ gif->current_error is set to GIF_FRAME_NO_DISPLAY
*/
int gif_decode_frame(struct gif_animation *gif, unsigned int frame, gif_bitmap_callback_vt *bitmap_callbacks) {
unsigned int index = 0;
@@ -594,6 +605,14 @@
register int colour;
bool more_images = true;
+ /* Ensure this frame is supposed to be decoded
+ */
+ gif->current_error = 0;
+ if (gif->frames[frame].display == false) {
+ gif->current_error = GIF_FRAME_NO_DISPLAY;
+ return 0;
+ }
+
/* Ensure we have a frame to decode
*/
if (frame > gif->frame_count_partial)
@@ -672,8 +691,15 @@
}
/* Move to the first sub-block
- */
- gif_data += 2;
+ * Skip 3 bytes for extension introducer, label, and extension size fields
+ * Skip the extension size itself
+ * The special case here is the comment extension (0xfe) because it has no
+ * size field and therefore extension size is not skipped either
+ */
+ if (gif_data[1] == 0xfe)
+ gif_data += 2;
+ else
+ gif_data += (3 + extension_size);
/* Skip all the sub-blocks
*/
14 years, 11 months
r4417 dynis - /branches/dynis/libnsgif/libnsgif.c
by netsurf@semichrome.net
Author: dynis
Date: Sun Jun 22 03:28:01 2008
New Revision: 4417
URL: http://source.netsurf-browser.org?rev=4417&view=rev
Log:
Improved data-verification when initialising and decoding frames
Modified:
branches/dynis/libnsgif/libnsgif.c
Modified: branches/dynis/libnsgif/libnsgif.c
URL: http://source.netsurf-browser.org/branches/dynis/libnsgif/libnsgif.c?rev=...
==============================================================================
--- branches/dynis/libnsgif/libnsgif.c (original)
+++ branches/dynis/libnsgif/libnsgif.c Sun Jun 22 03:28:01 2008
@@ -120,17 +120,17 @@
unsigned int index;
int return_value;
- /* Check for sufficient data to be a GIF (6-byte header + 7-byte logical screen descriptor)
- */
- if (gif->buffer_size < 13) return GIF_INSUFFICIENT_DATA;
-
- /* Get our current processing position
- */
- gif_data = gif->gif_data + gif->buffer_position;
-
/* the gif format is thoroughly documented; a full description
* can be found at http://www.w3.org/Graphics/GIF/spec-gif89a.txt
*/
+
+ /* Check for sufficient data to be a GIF (6-byte header + 7-byte logical screen descriptor)
+ */
+ if (gif->buffer_size < 13) return GIF_INSUFFICIENT_DATA;
+
+ /* Get our current processing position
+ */
+ gif_data = gif->gif_data + gif->buffer_position;
/* See if we should initialise the GIF
*/
@@ -219,6 +219,16 @@
know if we've processed it
*/
gif->global_colour_table[0] = 0xaa000000;
+
+ /* Check if the GIF has no frame data (13-byte header + 1-byte termination block)
+ * Although generally useless, the GIF specification does not expressly prohibit this
+ */
+ if (gif->buffer_size == 14) {
+ if (gif_data[0] == GIF_TRAILER)
+ return 1;
+ else
+ return GIF_INSUFFICIENT_DATA;
+ }
/* Initialise enough workspace for 4 frames initially
*/
@@ -356,10 +366,14 @@
gif_end = (unsigned char *)(gif->gif_data + gif->buffer_size);
gif_bytes = (gif_end - gif_data);
- /* Check we have enough data for at least the header, or if we've finished
- */
- if ((gif_bytes > 0) && (gif_data[0] == GIF_TRAILER)) return 1;
- if (gif_bytes < 11) return -1;
+ /* Check if we've finished
+ */
+ if ((gif_bytes > 0) && (gif_data[0] == gif_trailer)) return 1;
+
+ /* Check if we have enough data
+ * The shortest block of data is a 4-byte comment extension + 1-byte block terminator + 1-byte gif trailer
+ */
+ if (gif_bytes < 6) return GIF_INSUFFICIENT_FRAME_DATA;
/* We could theoretically get some junk data that gives us millions of frames, so
we ensure that we don't have a silly number
@@ -397,11 +411,6 @@
*/
while (more_images) {
- /* Ensure we have some data
- */
- if ((gif_end - gif_data) < 10)
- return GIF_INSUFFICIENT_FRAME_DATA;
-
/* Decode the extensions
*/
background_action = 0;
@@ -409,11 +418,6 @@
/* Get the extension size
*/
extension_size = gif_data[2];
-
- /* Check we've enough data for the extension then header
- */
- if ((gif_end - gif_data) < (int)(extension_size + 13))
- return GIF_INSUFFICIENT_FRAME_DATA;
/* Graphic control extension - store the frame delay.
*/
@@ -424,13 +428,14 @@
/* Application extension - handle NETSCAPE2.0 looping
*/
- } else if ((gif_data[1] == 0xff) &&
- (gif_data[2] == 0x0b) &&
+ } else if (gif_data[1] == 0xff) {
+ if (gif_bytes < 18) return GIF_INSUFFICIENT_FRAME_DATA;
+ if ((gif_data[2] == 0x0b) &&
(strncmp((const char *) gif_data + 3,
"NETSCAPE2.0", 11) == 0) &&
(gif_data[14] == 0x03) &&
- (gif_data[15] == 0x01)) {
- gif->loop_count = gif_data[16] | (gif_data[17] << 8);
+ (gif_data[15] == 0x01))
+ gif->loop_count = gif_data[16] | (gif_data[17] << 8);
}
/* Move to the first sub-block
@@ -439,14 +444,24 @@
/* Skip all the sub-blocks
*/
- while (gif_data[0] != 0x00) {
+ while (gif_data[0] != 0x00)
gif_data += gif_data[0] + 1;
- if ((gif_end - gif_data) < 10) return GIF_INSUFFICIENT_FRAME_DATA;
- }
gif_data++;
}
- /* We must have at least one image descriptor
+ /* Check if we've finished
+ */
+ gif_bytes = (gif_end - gif_data);
+ if (gif_bytes < 1)
+ return GIF_INSUFFICIENT_FRAME_DATA;
+ else
+ if (gif_data[0] == gif_trailer) {
+ gif->buffer_position = gif_data - gif->gif_data;
+ gif->frame_count = frame + 1;
+ return 1;
+ }
+
+ /* If we're not done, there should be an image descriptor
*/
if (gif_data[0] != 0x2c) return GIF_FRAME_DATA_ERROR;
@@ -515,13 +530,14 @@
if (gif_data[0] > GIF_MAX_LZW)
return GIF_DATA_ERROR;
- /* Move our data onwards
+ /* Move our pointer to the actual image data
*/
gif_data++;
if (--gif_bytes < 0)
return GIF_INSUFFICIENT_FRAME_DATA;
/* Repeatedly skip blocks until we get a zero block or run out of data
+ * These blocks of image data are processed later by gif_decode_frame()
*/
block_size = 0;
while (block_size != 1) {
@@ -535,6 +551,8 @@
/* Check for end of data
*/
+ gif->buffer_position = gif_data - gif->gif_data;
+ gif->frame_count = frame + 1;
more_images &= !((gif_bytes < 1) || (gif_data[0] == GIF_TRAILER));
}
@@ -542,11 +560,8 @@
*/
if (gif_bytes < 1)
return GIF_INSUFFICIENT_FRAME_DATA;
- else {
- gif->buffer_position = gif_data - gif->gif_data;
- gif->frame_count = frame + 1;
+ else
if (gif_data[0] == GIF_TRAILER) return 1;
- }
return 0;
}
@@ -606,10 +621,10 @@
gif_end = gif->gif_data + gif->buffer_size;
gif_bytes = (gif_end - gif_data);
- /* Check we have enough data for the header
- */
- if (gif_bytes < 9)
- return GIF_INSUFFICIENT_DATA;
+ /* Check if we have enough data
+ * The shortest block of data is a 10-byte image descriptor + 1-byte gif trailer
+ */
+ if (gif_bytes < 12) return GIF_INSUFFICIENT_FRAME_DATA;
/* Clear the previous frame totally. We can't just pretend we've got a smaller
sprite and clear what we need as some frames have multiple images which would
@@ -628,20 +643,13 @@
*/
save_buffer_position = gif->buffer_position;
gif->buffer_position = gif_data - gif->gif_data;
+ gif_data = gif->gif_data + gif->buffer_position;
/* We've got to do this more than one time if we've got multiple images
*/
while (more_images) {
background_action = 0;
- /* Ensure we have some data
- */
- gif_data = gif->gif_data + gif->buffer_position;
- if ((gif_end - gif_data) < 10) {
- return_value = GIF_INSUFFICIENT_FRAME_DATA;
- break;
- }
-
/* Decode the extensions
*/
while (gif_data[0] == 0x21) {
@@ -650,35 +658,35 @@
*/
extension_size = gif_data[2];
- /* Check we've enough data for the extension then header
- */
- if ((gif_end - gif_data) < (int)(extension_size + 13)) {
- return_value = GIF_INSUFFICIENT_FRAME_DATA;
- break;
- }
-
/* Graphic control extension - store the frame delay.
*/
if (gif_data[1] == 0xf9) {
+ if (gif_bytes < 7) {
+ return_value = GIF_INSUFFICIENT_FRAME_DATA;
+ break;
+ }
flags = gif_data[3];
if (flags & 0x01) transparency_index = gif_data[6];
background_action = ((flags & 0x1c) >> 2);
more_images = false;
}
+
/* Move to the first sub-block
*/
gif_data += 2;
/* Skip all the sub-blocks
*/
- while (gif_data[0] != 0x00) {
+ while (gif_data[0] != 0x00)
gif_data += gif_data[0] + 1;
- if ((gif_end - gif_data) < 10) {
- return_value = GIF_INSUFFICIENT_FRAME_DATA;
- break;
- }
- }
gif_data++;
+ }
+
+ /* Ensure we have enough data for the 10-byte image descriptor + 1-byte gif trailer
+ */
+ if ((gif_bytes = (gif_end - gif_data)) < 12) {
+ return_value = GIF_INSUFFICIENT_FRAME_DATA;
+ break;
}
/* 10-byte Image Descriptor is:
@@ -718,10 +726,10 @@
colour_table_size = 2 << (flags & 0x07);
interlace = flags & 0x40;
- /* Move through our data
+ /* Move our pointer to the colour table or image data (if no colour table is given)
*/
gif_data += 10;
- gif_bytes = (int)(gif_end - gif_data);
+ gif_bytes = (gif_end - gif_data);
/* Set up the colour table
*/
@@ -741,14 +749,36 @@
} else {
gif_data += 3 * colour_table_size;
}
- gif_bytes = (int)(gif_end - gif_data);
+ gif_bytes = (gif_end - gif_data);
} else {
colour_table = gif->global_colour_table;
}
+ /* Check if we've finished
+ */
+ if (gif_bytes < 1) {
+ return_value = GIF_INSUFFICIENT_FRAME_DATA;
+ break;
+ } else if (gif_data[0] == gif_trailer) {
+ return_value = 1;
+ break;
+ }
+
/* If we are clearing the image we just clear, if not decode
*/
if (!clear_image) {
+ /* Ensure we have enough data for the 1-byte LZW code size + 1-byte gif trailer
+ */
+ if (gif_bytes < 2) {
+ return_value = GIF_INSUFFICIENT_FRAME_DATA;
+ break;
+ /* If we only have the 1-byte LZW code size + 1-byte gif trailer, we're finished
+ */
+ } else if ((gif_bytes = 2) && (gif_data[1] == gif_trailer)) {
+ return_value = 1;
+ break;
+ }
+
/* Set our dirty status
*/
if ((background_action == 2) || (background_action == 3))
14 years, 11 months
r4416 dynis - in /branches/dynis/libnsgif: libnsgif.c libnsgif.h
by netsurf@semichrome.net
Author: dynis
Date: Sun Jun 22 02:54:03 2008
New Revision: 4416
URL: http://source.netsurf-browser.org?rev=4416&view=rev
Log:
Made a constant for the GIF trailer (0x3b) so it's more obvious what that byte does
Modified:
branches/dynis/libnsgif/libnsgif.c
branches/dynis/libnsgif/libnsgif.h
Modified: branches/dynis/libnsgif/libnsgif.c
URL: http://source.netsurf-browser.org/branches/dynis/libnsgif/libnsgif.c?rev=...
==============================================================================
--- branches/dynis/libnsgif/libnsgif.c (original)
+++ branches/dynis/libnsgif/libnsgif.c Sun Jun 22 02:54:03 2008
@@ -101,7 +101,6 @@
/* Whether to clear the decoded image rather than plot
*/
static bool clear_image = false;
-
/* Initialises any workspace held by the animation and attempts to decode
any information that hasn't already been decoded.
@@ -359,7 +358,7 @@
/* Check we have enough data for at least the header, or if we've finished
*/
- if ((gif_bytes > 0) && (gif_data[0] == 0x3b)) return 1;
+ if ((gif_bytes > 0) && (gif_data[0] == GIF_TRAILER)) return 1;
if (gif_bytes < 11) return -1;
/* We could theoretically get some junk data that gives us millions of frames, so
@@ -536,7 +535,7 @@
/* Check for end of data
*/
- more_images &= !((gif_bytes < 1) || (gif_data[0] == 0x3b));
+ more_images &= !((gif_bytes < 1) || (gif_data[0] == GIF_TRAILER));
}
/* Check if we've finished
@@ -546,7 +545,7 @@
else {
gif->buffer_position = gif_data - gif->gif_data;
gif->frame_count = frame + 1;
- if (gif_data[0] == 0x3b) return 1;
+ if (gif_data[0] == GIF_TRAILER) return 1;
}
return 0;
}
@@ -836,7 +835,7 @@
/* Check for end of data
*/
gif_bytes = gif->buffer_size - gif->buffer_position;
- more_images &= !((gif_bytes < 1) || (gif_data[0] == 0x3b));
+ more_images &= !((gif_bytes < 1) || (gif_data[0] == GIF_TRAILER));
gif->buffer_position++;
}
Modified: branches/dynis/libnsgif/libnsgif.h
URL: http://source.netsurf-browser.org/branches/dynis/libnsgif/libnsgif.h?rev=...
==============================================================================
--- branches/dynis/libnsgif/libnsgif.h (original)
+++ branches/dynis/libnsgif/libnsgif.h Sun Jun 22 02:54:03 2008
@@ -33,6 +33,7 @@
#define GIF_INSUFFICIENT_DATA -3
#define GIF_DATA_ERROR -4
#define GIF_INSUFFICIENT_MEMORY -5
+#define GIF_FRAME_NO_DISPLAY -6
/* Maximum colour table size
*/
@@ -42,11 +43,16 @@
*/
#define GIF_MAX_LZW 12
+/* 1-byte GIF Trailer "[indicates] the end of the GIF Data Stream" (fixed value: 0x3b)
+*/
+#define GIF_TRAILER 0x3b
+
/* The GIF frame data
*/
typedef struct gif_frame {
unsigned int frame_pointer; /**< offset (in bytes) to the GIF frame data */
unsigned int frame_delay; /**< delay (in cs) before animating the frame */
+ bool display; /**< whether the frame should be displayed/animated */
bool virgin; /**< whether the frame has previously been used */
bool opaque; /**< whether the frame is totally opaque */
bool redraw_required; /**< whether a forcable screen redraw is required */
14 years, 11 months
r4415 dynis - /branches/dynis/libnsgif/libnsgif.c
by netsurf@semichrome.net
Author: dynis
Date: Sun Jun 22 02:40:55 2008
New Revision: 4415
URL: http://source.netsurf-browser.org?rev=4415&view=rev
Log:
Provide better GIF documentation in the comments to assist in future editing
Modified:
branches/dynis/libnsgif/libnsgif.c
Modified: branches/dynis/libnsgif/libnsgif.c
URL: http://source.netsurf-browser.org/branches/dynis/libnsgif/libnsgif.c?rev=...
==============================================================================
--- branches/dynis/libnsgif/libnsgif.c (original)
+++ branches/dynis/libnsgif/libnsgif.c Sun Jun 22 02:40:55 2008
@@ -121,13 +121,17 @@
unsigned int index;
int return_value;
- /* Check for sufficient data to be a GIF
+ /* Check for sufficient data to be a GIF (6-byte header + 7-byte logical screen descriptor)
*/
if (gif->buffer_size < 13) return GIF_INSUFFICIENT_DATA;
/* Get our current processing position
*/
gif_data = gif->gif_data + gif->buffer_position;
+
+ /* the gif format is thoroughly documented; a full description
+ * can be found at http://www.w3.org/Graphics/GIF/spec-gif89a.txt
+ */
/* See if we should initialise the GIF
*/
@@ -147,21 +151,34 @@
gif->frame_count_partial = 0;
gif->decoded_frame = -1;
- /* Check we are a GIF
- */
+ /* 6-byte GIF file header is:
+ *
+ * +0 CHAR[2] Signature ('GIF')
+ * +3 CHAR[2] Version ('87a' or '89a')
+ */
if (strncmp((const char *) gif_data, "GIF", 3) != 0)
return GIF_DATA_ERROR;
gif_data += 3;
- /* Check we are a GIF type 87a or 89a
+ /* Ensure GIF reports version 87a or 89a
*/
/* if ((strncmp(gif_data, "87a", 3) != 0) &&
(strncmp(gif_data, "89a", 3) != 0))
LOG(("Unknown GIF format - proceeding anyway"));
*/ gif_data += 3;
- /* Get our GIF data.
- */
+ /* 7-byte Logical Screen Descriptor is:
+ *
+ * +6 SHORT Logical Screen Width
+ * +8 SHORT Logical Screen Height
+ * +10 CHAR __Packed Fields__
+ * 1BIT Global Color Table Flag
+ * 3BITS Color Resolution
+ * 1BIT Sort Flag
+ * 3BITS Size of Global Color Table
+ * +11 CHAR Background Color Index
+ * +12 CHAR Pixel Aspect Ratio
+ */
gif->width = gif_data[0] | (gif_data[1] << 8);
gif->height = gif_data[2] | (gif_data[3] << 8);
gif->global_colours = (gif_data[4] & 0x80);
@@ -665,8 +682,20 @@
gif_data++;
}
- /* Decode the header
- */
+ /* 10-byte Image Descriptor is:
+ *
+ * +0 CHAR Image Separator (0x2c)
+ * +1 SHORT Image Left Position
+ * +3 SHORT Image Top Position
+ * +5 SHORT Width
+ * +7 SHORT Height
+ * +9 CHAR __Packed Fields__
+ * 1BIT Local Color Table Flag
+ * 1BIT Interlace Flag
+ * 1BIT Sort Flag
+ * 2BITS Reserved
+ * 3BITS Size of Local Color Table
+ */
if (gif_data[0] != 0x2c) {
return_value = GIF_DATA_ERROR;
break;
14 years, 11 months
r4413 bursa - in /branches/dynis/libnsgif: Makefile bin/ examples/ examples/decode_gif.c examples/waves.gif
by netsurf@semichrome.net
Author: bursa
Date: Sat Jun 21 15:35:42 2008
New Revision: 4413
URL: http://source.netsurf-browser.org?rev=4413&view=rev
Log:
Simplified example of using libnsgif.
Added:
branches/dynis/libnsgif/bin/
branches/dynis/libnsgif/examples/
branches/dynis/libnsgif/examples/decode_gif.c
branches/dynis/libnsgif/examples/waves.gif (with props)
Modified:
branches/dynis/libnsgif/Makefile
Modified: branches/dynis/libnsgif/Makefile
URL: http://source.netsurf-browser.org/branches/dynis/libnsgif/Makefile?rev=44...
==============================================================================
--- branches/dynis/libnsgif/Makefile (original)
+++ branches/dynis/libnsgif/Makefile Sat Jun 21 15:35:42 2008
@@ -23,7 +23,7 @@
.PHONY: all clean docs install uninstall
-all: libnsgif.a
+all: libnsgif.a bin/decode_gif
libnsgif.a: libnsgif.o libnsgif.pc
${AR} ${ARFLAGS} libnsgif.a libnsgif.o
@@ -33,6 +33,9 @@
%.o: %.c
${CC} -c ${CFLAGS} -o $@ $<
+
+bin/decode_gif: examples/decode_gif.c libnsgif.a
+ ${CC} ${CFLAGS} -o $@ $< libnsgif.a
docs:
${DOXYGEN}
Added: branches/dynis/libnsgif/examples/decode_gif.c
URL: http://source.netsurf-browser.org/branches/dynis/libnsgif/examples/decode...
==============================================================================
--- branches/dynis/libnsgif/examples/decode_gif.c (added)
+++ branches/dynis/libnsgif/examples/decode_gif.c Sat Jun 21 15:35:42 2008
@@ -1,0 +1,221 @@
+/*
+ * Copyright 2008 Sean Fox <dyntryx(a)gmail.com>
+ * Copyright 2008 James Bursa <james(a)netsurf-browser.org>
+ *
+ * This file is part of NetSurf, http://www.netsurf-browser.org/
+ *
+ * NetSurf is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * NetSurf is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <assert.h>
+#include <errno.h>
+#include <stdbool.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <sys/stat.h>
+#include <libnsgif.h>
+
+char *load_file(const char *path, size_t *data_size);
+void die(const char *context, int code);
+void *bitmap_create(int width, int height);
+void bitmap_set_opaque(void *bitmap, bool opaque);
+bool bitmap_test_opaque(void *bitmap);
+char *bitmap_get_buffer(void *bitmap);
+void bitmap_destroy(void *bitmap);
+void bitmap_modified(void *bitmap);
+
+
+gif_bitmap_callback_vt bitmap_callbacks = {
+ bitmap_create,
+ bitmap_destroy,
+ bitmap_get_buffer,
+ bitmap_set_opaque,
+ bitmap_test_opaque,
+ bitmap_modified
+};
+
+
+int main(int argc, char *argv[])
+{
+ struct gif_animation gif;
+ size_t size;
+ int code;
+ unsigned int i;
+
+ if (argc != 2) {
+ fprintf(stderr, "Usage: %s image.gif\n", argv[0]);
+ return 1;
+ }
+
+ /* load file into memory */
+ char *data = load_file(argv[1], &size);
+
+ /* initialise gif_animation structure */
+ gif.buffer_size = size;
+ gif.gif_data = (unsigned char *) data;
+ gif.buffer_position = 0;
+
+ /* begin decoding */
+ do {
+ code = gif_initialise(&gif, &bitmap_callbacks);
+ if (code != 0 && code != 1)
+ die("gif_initialise", code);
+ } while (code != 1);
+
+ printf("P3\n");
+ printf("# %s\n", argv[1]);
+ printf("# width %u \n", gif.width);
+ printf("# height %u \n", gif.height);
+ printf("# frame_count %u \n", gif.frame_count);
+ printf("# frame_count_partial %u \n", gif.frame_count_partial);
+ printf("# background_colour %x \n", gif.background_colour);
+ printf("# loop_count %u \n", gif.loop_count);
+ printf("%u %u 256\n", gif.width, gif.height * gif.frame_count);
+
+ /* decode the frames */
+ for (i = 0; i != gif.frame_count; i++) {
+ unsigned int row, col;
+ char *image;
+
+ code = gif_decode_frame(&gif, i, &bitmap_callbacks);
+ if (code != 0)
+ die("gif_decode_frame", code);
+
+ printf("# frame %u:\n", i);
+ image = (char *) gif.frame_image;
+ for (row = 0; row != gif.height; row++) {
+ for (col = 0; col != gif.width; col++) {
+ size_t z = (row * gif.width + col) * 4;
+ printf("%u %u %u ",
+ (unsigned char) image[z],
+ (unsigned char) image[z + 1],
+ (unsigned char) image[z + 2]);
+ }
+ printf("\n");
+ }
+ }
+
+ return 0;
+}
+
+
+char *load_file(const char *path, size_t *data_size)
+{
+ FILE *fd;
+ struct stat sb;
+ char *buffer;
+ size_t size;
+ size_t n;
+
+ fd = fopen(path, "rb");
+ if (!fd) {
+ perror(path);
+ exit(EXIT_FAILURE);
+ }
+
+ if (stat(path, &sb)) {
+ perror(path);
+ exit(EXIT_FAILURE);
+ }
+ size = sb.st_size;
+
+ buffer = malloc(size);
+ if (!buffer) {
+ fprintf(stderr, "Unable to allocate %lld bytes\n",
+ (long long) size);
+ exit(EXIT_FAILURE);
+ }
+
+ n = fread(buffer, 1, size, fd);
+ if (n != size) {
+ perror(path);
+ exit(EXIT_FAILURE);
+ }
+
+ fclose(fd);
+
+ *data_size = size;
+ return buffer;
+}
+
+
+void die(const char *context, int code)
+{
+ fprintf(stderr, "%s failed: ", context);
+ switch (code)
+ {
+ case GIF_INSUFFICIENT_FRAME_DATA:
+ fprintf(stderr, "GIF_INSUFFICIENT_FRAME_DATA");
+ break;
+ case GIF_FRAME_DATA_ERROR:
+ fprintf(stderr, "GIF_FRAME_DATA_ERROR");
+ break;
+ case GIF_INSUFFICIENT_DATA:
+ fprintf(stderr, "GIF_INSUFFICIENT_DATA");
+ break;
+ case GIF_DATA_ERROR:
+ fprintf(stderr, "GIF_DATA_ERROR");
+ break;
+ case GIF_INSUFFICIENT_MEMORY:
+ fprintf(stderr, "GIF_INSUFFICIENT_MEMORY");
+ break;
+ default:
+ fprintf(stderr, "unknown code %i", code);
+ break;
+ }
+ fprintf(stderr, "\n");
+ exit(EXIT_FAILURE);
+}
+
+
+void *bitmap_create(int width, int height)
+{
+ return calloc(width * height, 4);
+}
+
+
+void bitmap_set_opaque(void *bitmap, bool opaque)
+{
+ (void) opaque; /* unused */
+ assert(bitmap);
+}
+
+
+bool bitmap_test_opaque(void *bitmap)
+{
+ assert(bitmap);
+ return false;
+}
+
+
+char *bitmap_get_buffer(void *bitmap)
+{
+ assert(bitmap);
+ return bitmap;
+}
+
+
+void bitmap_destroy(void *bitmap)
+{
+ assert(bitmap);
+ free(bitmap);
+}
+
+
+void bitmap_modified(void *bitmap)
+{
+ assert(bitmap);
+ return;
+}
+
Added: branches/dynis/libnsgif/examples/waves.gif
URL: http://source.netsurf-browser.org/branches/dynis/libnsgif/examples/waves....
==============================================================================
Binary file - no diff available.
Propchange: branches/dynis/libnsgif/examples/waves.gif
------------------------------------------------------------------------------
svn:mime-type = application/octet-stream
14 years, 11 months