HACK: pinfo->private_data points to smb_info again
[wireshark-wip.git] / epan / dissectors / packet-image-gif.c
blob42c9eb33e3437ff97755d0586552b42c853729c8
1 /* packet-image-gif.c
3 * Routines for image/gif media dissection
4 * Copyright 2003, 2004, Olivier Biot.
6 * $Id$
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
40 #include "config.h"
42 #include <string.h>
44 #include <glib.h>
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))
55 #define DebugLog(x) \
56 g_print("%s:%u: ", __FILE__, __LINE__); \
57 g_print x
58 #else
59 #define DebugLog(x) ;
60 #endif
62 #define IMG_GIF "image-gif"
64 /************************** Variable declarations **************************/
66 static const value_string vals_true_false[] = {
67 { 0, "False" },
68 { 1, "True" },
69 { 0, NULL },
72 static const value_string vals_extensions[] = {
73 { 0xF9, "Graphics Control" },
74 { 0xFE, "Comment" },
75 { 0xFF, "Application" },
76 { 0x01, "Plain Text" },
77 { 0x00, NULL },
80 enum {
81 GIF_87a = 0x87,
82 GIF_89a = 0x89
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)
92 /* header fields */
93 /* GIF signature */
94 static header_field_info hfi_version GIF_HFI_INIT =
95 { "Version",
96 IMG_GIF ".version",
97 FT_STRING, BASE_NONE, NULL, 0x00,
98 "GIF Version",
99 HFILL
102 /* Screen descriptor */
103 static header_field_info hfi_screen_width GIF_HFI_INIT =
104 { "Screen width",
105 IMG_GIF ".screen.width",
106 FT_UINT16, BASE_DEC, NULL, 0x00,
107 NULL,
108 HFILL
111 static header_field_info hfi_screen_height GIF_HFI_INIT =
112 { "Screen height",
113 IMG_GIF ".screen.height",
114 FT_UINT16, BASE_DEC, NULL, 0x00,
115 NULL,
116 HFILL
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",
124 HFILL
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.",
132 HFILL
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.",
140 HFILL
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.",
148 HFILL
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.",
157 HFILL
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.",
165 HFILL
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,
172 "Global color map.",
173 HFILL
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.",
183 HFILL
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.",
191 HFILL
194 static header_field_info hfi_image_width GIF_HFI_INIT =
195 { "Image width",
196 IMG_GIF ".image.width",
197 FT_UINT16, BASE_DEC, NULL, 0x00,
198 "Image width.",
199 HFILL
202 static header_field_info hfi_image_height GIF_HFI_INIT =
203 { "Image height",
204 IMG_GIF ".image.height",
205 FT_UINT16, BASE_DEC, NULL, 0x00,
206 "Image height.",
207 HFILL
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",
215 HFILL
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.",
223 HFILL
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.",
231 HFILL
234 #if 0
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.",
240 HFILL
242 #endif
244 static header_field_info hfi_local_color_map GIF_HFI_INIT =
245 { "Local color map",
246 IMG_GIF ".local.color_map",
247 FT_BYTES, BASE_NONE, NULL, 0x00,
248 "Local color map.",
249 HFILL
252 /* Extension */
253 static header_field_info hfi_extension GIF_HFI_INIT =
254 { "Extension",
255 IMG_GIF ".extension",
256 FT_NONE, BASE_NONE, NULL, 0x00,
257 "Extension.",
258 HFILL
261 static header_field_info hfi_extension_label GIF_HFI_INIT =
262 { "Extension label",
263 IMG_GIF ".extension.label",
264 FT_UINT8, BASE_HEX, VALS(vals_extensions), 0x00,
265 "Extension label.",
266 HFILL
269 static header_field_info hfi_image GIF_HFI_INIT =
270 { "Image",
271 IMG_GIF ".image",
272 FT_NONE, BASE_NONE, NULL, 0x00,
273 "Image.",
274 HFILL
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.",
282 HFILL
285 /* Trailer (end of GIF data stream) */
286 static header_field_info hfi_trailer GIF_HFI_INIT =
287 { "Trailer (End of the GIF stream)",
288 IMG_GIF ".end",
289 FT_NONE, BASE_NONE, NULL, 0x00,
290 "This byte tells the decoder that the data stream is finished.",
291 HFILL
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".
310 static gint
311 dissect_gif(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data _U_)
313 proto_item *ti;
314 proto_tree *gif_tree; /* Main GIF tree */
315 proto_tree *subtree; /* Main GIF tree */
316 guint offset = 0, len = 0;
317 guint8 peek;
318 gboolean color_map_present;
319 guint8 color_resolution;
320 guint8 image_bpp;
321 guint tvb_len = tvb_reported_length(tvb);
322 char *str;
324 guint8 version = 0;
326 if (tvb_len < 20)
327 return 0;
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) {
333 version = GIF_87a;
334 } else if (strcmp(str, "GIF89a") == 0) {
335 version = GIF_89a;
336 } else {
337 /* Not a GIF image! */
338 return 0;
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.
351 if (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);
355 /* GIF signature */
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,
374 "Global settings:");
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);
404 if (peek) {
405 /* Only display if different from 0 */
406 proto_tree_add_uint_format(gif_tree, hfi_pixel_aspect_ratio.id,
407 tvb, 12, 1, peek,
408 "%u, yields an aspect ratio of (15 + %u) / 64 = %.2f",
409 peek, peek, (float)(15 + peek) / 64.0);
413 /* Global color map
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);
421 } else {
422 len = 0;
424 offset = 13 + len;
425 /* From now on, a set of images prefixed with the image separator
426 * character 0x2C (',') will appear in the byte stream. Each image
427 * hence consists of:
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)
444 * - The raster data
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).
458 * GIF terminator
459 * This is a synchronization method, based on the final character 0xB3
460 * (';') at the end of an image
463 * GIF extension
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
473 * locations:
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:
481 * 1 byte : 0x21
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);
488 offset++;
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>"));
495 offset++;
496 do {
497 /* Read length of data block */
498 len = tvb_get_guint8(tvb, offset);
499 proto_tree_add_text(subtree, tvb,
500 offset, 1 + len,
501 "Data block (length = %u)", len);
502 offset += (1 + len);
503 item_len += (1 + len);
504 } while (len > 0);
505 proto_item_set_len(ti, item_len);
506 } else if (peek == 0x2C) { /* Image separator */
507 proto_tree *subtree2;
508 proto_item *ti2;
509 guint32 item_len = 11; /* Fixed header consisting of:
510 * 1 byte : 0x2C
511 * 2 bytes: image_left
512 * 2 bytes: image_top
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);
522 offset++;
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;
532 /* bit field */
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,
539 "Local settings:");
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);
557 offset++;
559 /* Local color map
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);
567 } else {
568 len = 0;
570 offset += len;
571 item_len += len;
573 proto_tree_add_item(subtree, &hfi_image_code_size,
574 tvb, offset, 1, ENC_LITTLE_ENDIAN);
575 offset++;
576 do {
577 /* Read length of data block */
578 len = tvb_get_guint8(tvb, offset);
579 proto_tree_add_text(subtree, tvb,
580 offset, 1 + len,
581 "Data block (length = %u)", len);
582 offset += 1 + len;
583 item_len += (1 + len);
584 } while (len > 0);
585 proto_item_set_len(ti, item_len);
586 } else {
587 /* GIF processing stops at this very byte */
588 proto_tree_add_item(gif_tree, &hfi_trailer,
589 tvb, offset, 1, ENC_NA);
590 break;
592 } /* while */
594 return offset;
597 static gboolean
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. */
610 void
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
621 &hfi_version,
624 * Logical screen descriptor
626 &hfi_screen_width,
627 &hfi_screen_height,
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,
646 * Extension
648 &hfi_extension,
649 &hfi_extension_label,
652 * Image
654 &hfi_image,
655 &hfi_image_left,
656 &hfi_image_top,
657 &hfi_image_width,
658 &hfi_image_height,
659 &hfi_image_code_size,
661 * Trailer
663 &hfi_trailer,
665 #endif
667 /* Setup protocol subtree array */
668 static gint *ett[] = {
669 &ett_gif,
670 &ett_global_flags,
671 &ett_local_flags,
672 &ett_extension,
673 &ett_image,
676 int proto_gif;
678 /* Register the protocol name and description */
679 proto_gif = proto_register_protocol(
680 "Compuserve GIF",
681 "GIF image",
682 IMG_GIF
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);
696 void
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);