3 * Routines for image/gif media dissection
4 * Copyright 2003, 2004, Olivier Biot.
8 * Refer to the AUTHORS file or the AUTHORS section in the man page
9 * for contacting the author(s) of this file.
11 * Wireshark - Network traffic analyzer
12 * By Gerald Combs <gerald@wireshark.org>
13 * Copyright 1998 Gerald Combs
15 * Compuserve GIF media decoding functionality provided by Olivier Biot.
17 * The two GIF specifications are found at several locations, such as W3C:
18 * http://www.w3.org/Graphics/GIF/spec-gif87.txt
19 * http://www.w3.org/Graphics/GIF/spec-gif89a.txt
21 * This program is free software; you can redistribute it and/or
22 * modify it under the terms of the GNU General Public License
23 * as published by the Free Software Foundation; either version 2
24 * of the License, or (at your option) any later version.
26 * This program is distributed in the hope that it will be useful,
27 * but WITHOUT ANY WARRANTY; without even the implied warranty of
28 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
29 * GNU General Public License for more details.
31 * You should have received a copy of the GNU General Public License
32 * along with this program; if not, write to the Free Software
33 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
36 /* Edit this file with 4-space indentation */
38 #define NEW_PROTO_TREE_API
46 #include <epan/packet.h>
48 /* General-purpose debug logger.
49 * Requires double parentheses because of variable arguments of printf().
51 * Enable debug logging for GIF by defining AM_CFLAGS
52 * so that it contains "-DDEBUG_image_gif" or "-DDEBUG_image"
54 #if (defined(DEBUG_image_gif) || defined(DEBUG_image))
56 g_print("%s:%u: ", __FILE__, __LINE__); \
62 #define IMG_GIF "image-gif"
64 /************************** Variable declarations **************************/
66 static const value_string vals_true_false
[] = {
72 static const value_string vals_extensions
[] = {
73 { 0xF9, "Graphics Control" },
75 { 0xFF, "Application" },
76 { 0x01, "Plain Text" },
85 static dissector_handle_t gif_handle
;
87 /* Protocol and registered fields */
88 static header_field_info
*hfi_gif
= NULL
;
90 #define GIF_HFI_INIT HFI_INIT(proto_gif)
94 static header_field_info hfi_version GIF_HFI_INIT
=
97 FT_STRING
, BASE_NONE
, NULL
, 0x00,
102 /* Screen descriptor */
103 static header_field_info hfi_screen_width GIF_HFI_INIT
=
105 IMG_GIF
".screen.width",
106 FT_UINT16
, BASE_DEC
, NULL
, 0x00,
111 static header_field_info hfi_screen_height GIF_HFI_INIT
=
113 IMG_GIF
".screen.height",
114 FT_UINT16
, BASE_DEC
, NULL
, 0x00,
119 static header_field_info hfi_global_color_map_present GIF_HFI_INIT
=
120 { "Global color map is present",
121 IMG_GIF
".global.color_map.present",
122 FT_UINT8
, BASE_DEC
, VALS(vals_true_false
), 0x80,
123 "Indicates if the global color map is present",
127 static header_field_info hfi_global_color_resolution GIF_HFI_INIT
=
128 { "Bits per color minus 1",
129 IMG_GIF
".global.color_bpp",
130 FT_UINT8
, BASE_DEC
, NULL
, 0x70,
131 "The number of bits per color is one plus the field value.",
135 static header_field_info hfi_global_color_map_ordered
/* GIF89a */ GIF_HFI_INIT
=
136 { "Global color map is ordered",
137 IMG_GIF
".global.color_map.ordered",
138 FT_UINT8
, BASE_DEC
, VALS(vals_true_false
), 0x08,
139 "Indicates whether the global color map is ordered.",
143 static header_field_info hfi_global_image_bpp GIF_HFI_INIT
=
144 { "Image bits per pixel minus 1",
145 IMG_GIF
".global.bpp",
146 FT_UINT8
, BASE_DEC
, NULL
, 0x07,
147 "The number of bits per pixel is one plus the field value.",
151 /* Only makes sense if the global color map is present: */
152 static header_field_info hfi_background_color GIF_HFI_INIT
=
153 { "Background color index",
154 IMG_GIF
".image_background_index",
155 FT_UINT8
, BASE_DEC
, NULL
, 0x00,
156 "Index of the background color in the color map.",
160 static header_field_info hfi_pixel_aspect_ratio
/* GIF89a */ GIF_HFI_INIT
=
161 { "Global pixel aspect ratio",
162 IMG_GIF
".global.pixel_aspect_ratio",
163 FT_UINT8
, BASE_DEC
, NULL
, 0x00,
164 "Gives an approximate value of the aspect ratio of the pixels.",
168 static header_field_info hfi_global_color_map GIF_HFI_INIT
=
169 { "Global color map",
170 IMG_GIF
".global.color_map",
171 FT_BYTES
, BASE_NONE
, NULL
, 0x00,
177 /* Image descriptor */
178 static header_field_info hfi_image_left GIF_HFI_INIT
=
179 { "Image left position",
180 IMG_GIF
".image.left",
181 FT_UINT16
, BASE_DEC
, NULL
, 0x00,
182 "Offset between left of Screen and left of Image.",
186 static header_field_info hfi_image_top GIF_HFI_INIT
=
187 { "Image top position",
188 IMG_GIF
".image.top",
189 FT_UINT16
, BASE_DEC
, NULL
, 0x00,
190 "Offset between top of Screen and top of Image.",
194 static header_field_info hfi_image_width GIF_HFI_INIT
=
196 IMG_GIF
".image.width",
197 FT_UINT16
, BASE_DEC
, NULL
, 0x00,
202 static header_field_info hfi_image_height GIF_HFI_INIT
=
204 IMG_GIF
".image.height",
205 FT_UINT16
, BASE_DEC
, NULL
, 0x00,
210 static header_field_info hfi_local_color_map_present GIF_HFI_INIT
=
211 { "Local color map is present",
212 IMG_GIF
".local.color_map.present",
213 FT_UINT8
, BASE_DEC
, VALS(vals_true_false
), 0x80,
214 "Indicates if the local color map is present",
218 static header_field_info hfi_local_color_resolution GIF_HFI_INIT
=
219 { "Bits per color minus 1",
220 IMG_GIF
".local.color_bpp",
221 FT_UINT8
, BASE_DEC
, NULL
, 0x70,
222 "The number of bits per color is one plus the field value.",
226 static header_field_info hfi_local_color_map_ordered
/* GIF89a */ GIF_HFI_INIT
=
227 { "Local color map is ordered",
228 IMG_GIF
".local.color_map.ordered",
229 FT_UINT8
, BASE_DEC
, VALS(vals_true_false
), 0x08,
230 "Indicates whether the local color map is ordered.",
235 static header_field_info hfi_local_image_bpp GIF_HFI_INIT
=
236 { "Image bits per pixel minus 1",
237 IMG_GIF
".local.bpp",
238 FT_UINT8
, BASE_DEC
, NULL
, 0x07,
239 "The number of bits per pixel is one plus the field value.",
244 static header_field_info hfi_local_color_map GIF_HFI_INIT
=
246 IMG_GIF
".local.color_map",
247 FT_BYTES
, BASE_NONE
, NULL
, 0x00,
253 static header_field_info hfi_extension GIF_HFI_INIT
=
255 IMG_GIF
".extension",
256 FT_NONE
, BASE_NONE
, NULL
, 0x00,
261 static header_field_info hfi_extension_label GIF_HFI_INIT
=
263 IMG_GIF
".extension.label",
264 FT_UINT8
, BASE_HEX
, VALS(vals_extensions
), 0x00,
269 static header_field_info hfi_image GIF_HFI_INIT
=
272 FT_NONE
, BASE_NONE
, NULL
, 0x00,
277 static header_field_info hfi_image_code_size GIF_HFI_INIT
=
278 { "LZW minimum code size",
279 IMG_GIF
".image.code_size",
280 FT_UINT8
, BASE_DEC
, NULL
, 0x00,
281 "Minimum code size for the LZW compression.",
285 /* Trailer (end of GIF data stream) */
286 static header_field_info hfi_trailer GIF_HFI_INIT
=
287 { "Trailer (End of the GIF stream)",
289 FT_NONE
, BASE_NONE
, NULL
, 0x00,
290 "This byte tells the decoder that the data stream is finished.",
295 /* Initialize the subtree pointers */
296 static gint ett_gif
= -1;
297 static gint ett_global_flags
= -1;
298 static gint ett_local_flags
= -1;
299 static gint ett_extension
= -1;
300 static gint ett_image
= -1;
303 /****************** GIF protocol dissection functions ******************/
305 /* There are two Compuserve GIF standards: GIF87a and GIF89a. GIF image files
306 * always convey their version in the first 6 bytes, written as an US-ASCII
307 * string representation of the version: "GIF87a" or "GIF89a".
311 dissect_gif(tvbuff_t
*tvb
, packet_info
*pinfo
, proto_tree
*tree
, void *data _U_
)
314 proto_tree
*gif_tree
; /* Main GIF tree */
315 proto_tree
*subtree
; /* Main GIF tree */
316 guint offset
= 0, len
= 0;
318 gboolean color_map_present
;
319 guint8 color_resolution
;
321 guint tvb_len
= tvb_reported_length(tvb
);
329 str
= tvb_get_string(wmem_packet_scope(), tvb
, 0, 6);
330 /* Check whether we're processing a GIF object */
331 /* see http://www.w3.org/Graphics/GIF/spec-gif89a.txt section 17 */
332 if (strcmp(str
, "GIF87a") == 0) {
334 } else if (strcmp(str
, "GIF89a") == 0) {
337 /* Not a GIF image! */
341 DISSECTOR_ASSERT(version
);
343 /* Add summary to INFO column if it is enabled */
344 col_append_fstr(pinfo
->cinfo
, COL_INFO
, " (%s)", str
);
346 /* In order to speed up dissection, do not add items to the protocol tree
347 * if it is not visible. However, compute the values that are needed for
348 * correct protocol dissection if they have more meaning than just adding
349 * items to the protocol tree.
352 ti
= proto_tree_add_item(tree
, hfi_gif
, tvb
, 0, -1, ENC_NA
);
353 proto_item_append_text(ti
, ", Version: %s", str
);
354 gif_tree
= proto_item_add_subtree(ti
, ett_gif
);
356 proto_tree_add_item(gif_tree
, &hfi_version
, tvb
, 0, 6, ENC_ASCII
|ENC_NA
);
357 /* Screen descriptor */
358 proto_tree_add_item(gif_tree
, &hfi_screen_width
, tvb
, 6, 2, ENC_LITTLE_ENDIAN
);
359 proto_tree_add_item(gif_tree
, &hfi_screen_height
, tvb
, 8, 2, ENC_LITTLE_ENDIAN
);
361 peek
= tvb_get_guint8(tvb
, 10);
362 /* Bitfield gccc 0ppp
363 * g... .... : global color map present
364 * .ccc .... : color resolution in bits (add one)
365 * .... 0... : GIF87a - reserved (no use)
366 * GIF89a - ordered (most important color 1st)
367 * .... .ppp : bits per pixel in image (add one)
369 color_map_present
= peek
& 0x80;
370 color_resolution
= 1 + ((peek
& 0x60) >> 4);
371 image_bpp
= 1 + (peek
& 0x07);
373 ti
= proto_tree_add_text(gif_tree
, tvb
, 10, 1,
375 if (color_map_present
)
376 proto_item_append_text(ti
, " (Global color table present)");
377 proto_item_append_text(ti
,
378 " (%u bit%s per color) (%u bit%s per pixel)",
379 color_resolution
, plurality(color_resolution
, "", "s"),
380 image_bpp
, plurality(image_bpp
, "", "s"));
381 subtree
= proto_item_add_subtree(ti
, ett_global_flags
);
382 proto_tree_add_item(subtree
, &hfi_global_color_map_present
,
383 tvb
, 10, 1, ENC_LITTLE_ENDIAN
);
384 proto_tree_add_item(subtree
, &hfi_global_color_resolution
,
385 tvb
, 10, 1, ENC_LITTLE_ENDIAN
);
386 if (version
== GIF_89a
) {
387 proto_tree_add_item(subtree
, &hfi_global_color_map_ordered
,
388 tvb
, 10, 1, ENC_LITTLE_ENDIAN
);
390 proto_tree_add_item(subtree
, &hfi_global_image_bpp
,
391 tvb
, 10, 1, ENC_LITTLE_ENDIAN
);
393 /* Background color */
394 proto_tree_add_item(gif_tree
, &hfi_background_color
,
395 tvb
, 11, 1, ENC_LITTLE_ENDIAN
);
397 /* byte at offset 12 is 0x00 - reserved in GIF87a but encodes the
398 * pixel aspect ratio in GIF89a as:
399 * aspect-ratio = (15 + pixel-aspect-ratio) / 64
400 * where the aspect-ratio is not computed if pixel-aspect-ratio == 0
402 if (version
== GIF_89a
) {
403 peek
= tvb_get_guint8(tvb
, 12);
405 /* Only display if different from 0 */
406 proto_tree_add_uint_format(gif_tree
, hfi_pixel_aspect_ratio
.id
,
408 "%u, yields an aspect ratio of (15 + %u) / 64 = %.2f",
409 peek
, peek
, (float)(15 + peek
) / 64.0);
414 * If present, it takes 2 ^ (image_bpp) byte tuples (R, G, B)
415 * that contain the Red, Green and Blue intensity of the colors
416 * in the Global Color Map */
417 if (color_map_present
) {
418 len
= 3 * (1 << image_bpp
);
419 proto_tree_add_item(gif_tree
, &hfi_global_color_map
,
420 tvb
, 13, len
, ENC_NA
);
425 /* From now on, a set of images prefixed with the image separator
426 * character 0x2C (',') will appear in the byte stream. Each image
428 * - The image separator character 0x2C
429 * - Image left (16 bits LSB first): pixels from left border
430 * - Image top (16 bits LSB first): pixels from to border
431 * - Image width (16 bits LSB first)
432 * - Image height (16 bits LSB first)
433 * - A bitfield MI00 0ppp
434 * M... .... : Use global color map if unset (ignore ppp);
435 * if set a local color map will be defined.
436 * .I.. .... : Image formatted in interlaced order if set;
437 * otherwise it is plain sequential order
438 * ..0. .... : GIF87a - Reserved
439 * ..s. .... GIF89a - Set if local color map is ordered
440 * ...0 0... : Reserved
441 * .... .ppp : bits per pixel in image (add one)
442 * - If the local color map bit is set, then a local color table follows
443 * with length = 3 x 2 ^ (1 + bits per pixel)
446 * NOTE that the GIF specification only requires that:
447 * image left + image width <= screen width
448 * image top + image height <= screen height
450 * The Raster Data is encoded as follows:
451 * - Code size (1 byte)
452 * - Blocks consisting of
453 * o Byte count (1 byte): number of bytes in the block
454 * o Data bytes: as many as specified in the byte count
455 * End of data is given with an empty block (byte count == 0).
459 * This is a synchronization method, based on the final character 0xB3
460 * (';') at the end of an image
464 * This is a block of data encoded as:
465 * - The GIF extension block introducer 0x21 ('!')
466 * - The extension function code (1 byte)
467 * - Blocks consisting of
468 * o Byte count (1 byte): number of bytes in the block
469 * o Data bytes: as many as specified in the byte count
470 * End of data is given with an empty block (byte count == 0).
472 * NOTE that the GIF extension block can only appear at the following
474 * - Immediately before an Image Descriptor
475 * - Before the GIF termination character
477 while (offset
< tvb_len
) {
478 peek
= tvb_get_guint8(tvb
, offset
);
479 if (peek
== 0x21) { /* GIF extension block */
480 guint32 item_len
= 2; /* Fixed header consisting of:
482 * 1 byte : extension_label
485 ti
= proto_tree_add_item(gif_tree
, &hfi_extension
,
486 tvb
, offset
, 1, ENC_NA
);
487 subtree
= proto_item_add_subtree(ti
, ett_extension
);
489 proto_tree_add_item(subtree
, &hfi_extension_label
,
490 tvb
, offset
, 1, ENC_LITTLE_ENDIAN
);
491 peek
= tvb_get_guint8(tvb
, offset
);
492 proto_item_append_text(ti
, ": %s",
493 val_to_str(peek
, vals_extensions
,
494 "<Warning: Unknown extension 0x%02X>"));
497 /* Read length of data block */
498 len
= tvb_get_guint8(tvb
, offset
);
499 proto_tree_add_text(subtree
, tvb
,
501 "Data block (length = %u)", len
);
503 item_len
+= (1 + len
);
505 proto_item_set_len(ti
, item_len
);
506 } else if (peek
== 0x2C) { /* Image separator */
507 proto_tree
*subtree2
;
509 guint32 item_len
= 11; /* Fixed header consisting of:
511 * 2 bytes: image_left
513 * 2 bytes: image_width
514 * 2 bytes: image height
515 * 1 byte : packed bit field
516 * 1 byte : image code size
519 ti
= proto_tree_add_item(gif_tree
, &hfi_image
,
520 tvb
, offset
, 1, ENC_NA
);
521 subtree
= proto_item_add_subtree(ti
, ett_image
);
523 /* Screen descriptor */
524 proto_tree_add_item(subtree
, &hfi_image_left
,
525 tvb
, offset
, 2, ENC_LITTLE_ENDIAN
); offset
+= 2;
526 proto_tree_add_item(subtree
, &hfi_image_top
,
527 tvb
, offset
, 2, ENC_LITTLE_ENDIAN
); offset
+= 2;
528 proto_tree_add_item(subtree
, &hfi_image_width
,
529 tvb
, offset
, 2, ENC_LITTLE_ENDIAN
); offset
+= 2;
530 proto_tree_add_item(subtree
, &hfi_image_height
,
531 tvb
, offset
, 2, ENC_LITTLE_ENDIAN
); offset
+= 2;
533 peek
= tvb_get_guint8(tvb
, offset
);
534 color_map_present
= peek
& 0x80;
535 color_resolution
= 1 + ((peek
& 0x60) >> 4);
536 image_bpp
= 1 + (peek
& 0x07);
538 ti2
= proto_tree_add_text(subtree
, tvb
, offset
, 1,
540 if (color_map_present
)
541 proto_item_append_text(ti2
, " (Local color table present)");
542 proto_item_append_text(ti2
,
543 " (%u bit%s per color) (%u bit%s per pixel)",
544 color_resolution
, plurality(color_resolution
, "", "s"),
545 image_bpp
, plurality(image_bpp
, "", "s"));
546 subtree2
= proto_item_add_subtree(ti2
, ett_local_flags
);
547 proto_tree_add_item(subtree2
, &hfi_local_color_map_present
,
548 tvb
, offset
, 1, ENC_LITTLE_ENDIAN
);
549 proto_tree_add_item(subtree2
, &hfi_local_color_resolution
,
550 tvb
, offset
, 1, ENC_LITTLE_ENDIAN
);
551 if (version
== GIF_89a
) {
552 proto_tree_add_item(subtree2
, &hfi_local_color_map_ordered
,
553 tvb
, offset
, 1, ENC_LITTLE_ENDIAN
);
555 proto_tree_add_item(subtree2
, &hfi_global_image_bpp
,
556 tvb
, offset
, 1, ENC_LITTLE_ENDIAN
);
560 * If present, it takes 2 ^ (image_bpp) byte tuples (R, G, B)
561 * that contain the Red, Green and Blue intensity of the colors
562 * in the Local Color Map */
563 if (color_map_present
) {
564 len
= 3 * (1 << image_bpp
);
565 proto_tree_add_item(subtree
, &hfi_local_color_map
,
566 tvb
, offset
, len
, ENC_NA
);
573 proto_tree_add_item(subtree
, &hfi_image_code_size
,
574 tvb
, offset
, 1, ENC_LITTLE_ENDIAN
);
577 /* Read length of data block */
578 len
= tvb_get_guint8(tvb
, offset
);
579 proto_tree_add_text(subtree
, tvb
,
581 "Data block (length = %u)", len
);
583 item_len
+= (1 + len
);
585 proto_item_set_len(ti
, item_len
);
587 /* GIF processing stops at this very byte */
588 proto_tree_add_item(gif_tree
, &hfi_trailer
,
589 tvb
, offset
, 1, ENC_NA
);
598 dissect_gif_heur(tvbuff_t
*tvb
, packet_info
*pinfo
, proto_tree
*tree
, void *data _U_
)
600 return dissect_gif(tvb
, pinfo
, tree
, NULL
) > 0;
604 /****************** Register the protocol with Wireshark ******************/
607 /* This format is required because a script is used to build the C function
608 * that calls the protocol registration. */
611 proto_register_gif(void)
613 #ifndef HAVE_HFI_SECTION_INIT
615 * Setup list of header fields.
617 static header_field_info
*hfi
[] = {
619 * GIF signature and version
624 * Logical screen descriptor
628 &hfi_global_color_map_present
,
629 &hfi_global_color_resolution
,
630 &hfi_global_color_map_ordered
,
631 &hfi_global_image_bpp
,
632 &hfi_background_color
,
633 &hfi_pixel_aspect_ratio
,
634 &hfi_global_color_map
,
637 * Local color map (part of image)
639 &hfi_local_color_map_present
,
640 &hfi_local_color_resolution
,
641 &hfi_local_color_map_ordered
,
642 /* &hfi_local_image_bpp, */
643 &hfi_local_color_map
,
649 &hfi_extension_label
,
659 &hfi_image_code_size
,
667 /* Setup protocol subtree array */
668 static gint
*ett
[] = {
678 /* Register the protocol name and description */
679 proto_gif
= proto_register_protocol(
685 hfi_gif
= proto_registrar_get_nth(proto_gif
);
687 /* Required function calls to register the header fields
688 * and subtrees used */
689 proto_register_fields(proto_gif
, hfi
, array_length(hfi
));
690 proto_register_subtree_array(ett
, array_length(ett
));
692 gif_handle
= new_register_dissector(IMG_GIF
, dissect_gif
, proto_gif
);
697 proto_reg_handoff_gif(void)
699 /* Register the GIF media type */
700 dissector_add_string("media_type", "image/gif", gif_handle
);
701 heur_dissector_add("http", dissect_gif_heur
, hfi_gif
->id
);
702 heur_dissector_add("wtap_file", dissect_gif_heur
, hfi_gif
->id
);