home *** CD-ROM | disk | FTP | other *** search
/ PC Pro 2002 April / pcpro0402.iso / essentials / graphics / Gimp / gimp-src-20001226.exe / src / gimp / plug-ins / common / gif.c < prev    next >
Encoding:
Text File  |  2000-10-22  |  62.7 KB  |  2,460 lines

  1. /* GIF saving file filter for The GIMP version 1.0/1.1
  2.  *
  3.  *    - Adam D. Moss
  4.  *    - Peter Mattis
  5.  *    - Spencer Kimball
  6.  *
  7.  *      Based around original GIF code by David Koblas.
  8.  *
  9.  *
  10.  * Version 3.0.2 - 99/04/25
  11.  *                        Adam D. Moss - <adam@gimp.org> <adam@foxbox.org>
  12.  */
  13. /*
  14.  * This filter uses code taken from the "giftopnm" and "ppmtogif" programs
  15.  *    which are part of the "netpbm" package.
  16.  */
  17. /*
  18.  *  "The Graphics Interchange Format(c) is the Copyright property of
  19.  *  CompuServe Incorporated.  GIF(sm) is a Service Mark property of
  20.  *  CompuServe Incorporated." 
  21.  */
  22.  
  23. /*
  24.  * REVISION HISTORY
  25.  *
  26.  * 99/04/25
  27.  * 3.00.02 - Save the comment back onto the image as a persistent
  28.  *           parasite if the comment was edited.
  29.  *
  30.  * 99/03/30
  31.  * 3.00.01 - Round image timing to nearest 10ms instead of
  32.  *           truncating.  Insert a mandatory 10ms minimum delay
  33.  *           for the frames of looping animated GIFs, to avoid
  34.  *           generating an evil CPU-sucking animation that 'other'
  35.  *           GIF-animators sometimes like to save.
  36.  *
  37.  * 99/03/20
  38.  * 3.00.00 - GIF-loading code moved to separate plugin.
  39.  *
  40.  * 99/02/22
  41.  * 2.01.02 - Don't show a progress bar when loading non-interactively
  42.  *
  43.  * 99/01/23
  44.  * 2.01.01 - Use a text-box to permit multi-line comments.  Don't
  45.  *           try to write comment blocks which are longer than
  46.  *           permitted.
  47.  *
  48.  * 98/10/09
  49.  * 2.01.00 - Added support for persistent GIF Comments through
  50.  *           the GIMP 1.1 GimpParasite mechanism where available.
  51.  *           Did some user-interface tweaks.
  52.  *           Fixed a bug when trying to save a GIF smaller
  53.  *           than five pixels high as interlaced.
  54.  *
  55.  * 98/09/28
  56.  * 2.00.05 - Fixed TigerT's Infinite GIF Bug.  Icky one.
  57.  *
  58.  * 98/09/15
  59.  * 2.00.04 - The facility to specify the background colour of
  60.  *           a transparent/animated GIF for non-transparent
  61.  *           viewers now works very much more consistantly.
  62.  *
  63.  *           The only situations in which it will fail to work
  64.  *           as expected now are those where file size can be reduced
  65.  *           (abeit not by much, as the plugin is sometimes more pessimistic
  66.  *           than it need be) by re-using an existing unused colour
  67.  *           index rather than using another bit per pixel in the
  68.  *           encoded file.  That will never be an issue with an image
  69.  *           which was freshly converted from RGB to INDEXED with the
  70.  *           Quantize option, as that option removes any unused colours
  71.  *           from the image.
  72.  *
  73.  *           Let me know if you find the consistancy/size tradeoff more
  74.  *           annoying than helpful and I can adjust it.  IMHO it is too
  75.  *           arcane a feature to present to any user as a runtime option.
  76.  *
  77.  * 98/05/18
  78.  * 2.00.03 - If we did manage to decode at least one frame of a
  79.  *           gif, be sure to display the resulting image even if
  80.  *           it terminated abruptly.
  81.  *
  82.  * 98/04/28
  83.  * 2.00.02 - Fixed a bug with (ms) tag parsing.
  84.  *
  85.  * 98/03/16
  86.  * 2.00.01 - Fixed a long-standing bug when loading GIFs which layer
  87.  *           opaque frames onto transparent ones.
  88.  *
  89.  * 98/03/15
  90.  * 2.00.00 - No longer beta.  Uses the current GIMP brush background
  91.  *           colour as the transparent-index colour for viewers that
  92.  *           don't know about transparency, instead of magenta.  Note
  93.  *           that this is by no means likely to actually work, but
  94.  *           is more likely to do so if your image has been freshly
  95.  *           to-index'd before saving.
  96.  *
  97.  *           Also added some analysis to gif-reading to prevent the
  98.  *           number of encoded bits being pumped up inadvertantly for
  99.  *           successive load/saves of the same image.  [Adam]
  100.  *
  101.  * 97/12/11
  102.  * 1.99.18 - Bleh.  Disposals should specify how the next frame will
  103.  *           be composed with this frame, NOT how this frame will
  104.  *           be composed with the previous frame.  Fixed.  [Adam]
  105.  *
  106.  * 97/11/30
  107.  * 1.99.17 - No more bogus transparency indices in animated GIFs,
  108.  *           hopefully.  Saved files are better-behaved, sometimes
  109.  *           smaller.  [Adam]
  110.  *
  111.  * 97/09/29
  112.  * 1.99.16 - Added a dialog for the user to choose what to do if
  113.  *           one of the layers of the image extends beyond the image
  114.  *           borders - crop or cancel.  Added code behind it.
  115.  *
  116.  *           Corrected the number of bits for the base image to be
  117.  *           on the generous side.  Hopefully we can no longer generate
  118.  *           GIFs which make XV barf.
  119.  *
  120.  *           Now a lot more careful about whether we choose to encode
  121.  *           as a GIF87a or a GIF89a.  Hopefully does everything by the
  122.  *           book.  It should now be nigh-on impossible to torture the
  123.  *           plugin into generating a GIF which isn't extremely well
  124.  *           behaved with respect to the GIF89a specification.
  125.  *
  126.  *           Fixed(?) a lot of dialog callback details, should now be
  127.  *           happy with window deletion (GTK+970925).  Fixed the
  128.  *           cancellation of a save.  [Adam]
  129.  *
  130.  * 97/09/16
  131.  * 1.99.15 - Hey!  We can now cope with loading images which change
  132.  *           colourmap between frames.  This plugin will never save
  133.  *           such abominations of nature while I still live, though.
  134.  *           There should be no noncorrupt GIF in the universe which
  135.  *           GIMP can't load and play now.  [Adam]
  136.  *
  137.  * 97/09/14
  138.  * 1.99.14 - Added a check for layers whose extents don't lay
  139.  *           within the image boundaries, which would make it a
  140.  *           lot harder to generate badly-behaved GIFs.  Doesn't
  141.  *           do anything about it yet, but it should crop all layers
  142.  *           to the image boundaries.  Also, there's now a (separate)
  143.  *           animation-preview plugin!  [Adam]
  144.  *
  145.  * 97/08/29
  146.  * 1.99.13 - Basic ability to embed GIF comments within saved images.
  147.  *           Fixed a bug with encoding the number of loops in a GIF file -
  148.  *           would have been important, but we're not using that feature
  149.  *           yet anyway.  ;)
  150.  *           Subtly improved dialog layout a little. [Adam]
  151.  *
  152.  * 97/07/25
  153.  * 1.99.12 - Fixed attempts to load GIFs which don't exist.  Made a
  154.  *           related cosmetic adjustment. [Adam]
  155.  *
  156.  * 97/07/10
  157.  * 1.99.11 - Fixed a bug with loading and saving GIFs where the bottom
  158.  *           layer wasn't the same size as the image. [Adam]
  159.  *
  160.  * 97/07/06
  161.  * 1.99.10 - New 'save' dialog, now most of the default behaviour of
  162.  *           animated GIF saving is user-settable (looping, default
  163.  *           time between frames, etc.)
  164.  *           PDB entry for saving is no longer compatible.  Fortunately
  165.  *           I don't think that anyone is using file_gif_save in
  166.  *           scripts.  [Adam]
  167.  *
  168.  * 97/07/05
  169.  * 1.99.9  - More animated GIF work: now loads and saves frame disposal
  170.  *           information.  This is neat and will also allow some delta
  171.  *           stuff in the future.
  172.  *           The disposal-method is kept in the layer name, like the timing
  173.  *           info.
  174.  *           (replace) - this frame replaces whatever else has been shown
  175.  *                       so far.
  176.  *           (combine) - this frame builds apon the previous frame.
  177.  *           If a disposal method is not specified, it is assumed to mean
  178.  *           "don't care."  [Adam]
  179.  *
  180.  * 97/07/04
  181.  * 1.99.8  - Can save per-frame timing information too, now.  The time
  182.  *           for which a frame is visible is specified within the layer name
  183.  *           as i,e. (250ms).  If a frame doesn't have this timing value
  184.  *           it defaults to lasting 100ms. [Adam]
  185.  *
  186.  * 97/07/02
  187.  * 1.99.7  - For animated GIFs, fixed the saving of timing information for
  188.  *           frames which couldn't be made transparent.
  189.  *           Added the loading of timing information into the layer
  190.  *           names.  Adjusted GIMP's GIF magic number very slightly. [Adam]
  191.  *
  192.  * 97/06/30
  193.  * 1.99.6  - Now saves GRAY and GRAYA images, albeit not always
  194.  *           optimally (yet). [Adam]
  195.  *
  196.  * 97/06/25
  197.  * 1.99.5  - Good, the transparancy-on-big-architectures bug is
  198.  *           fixed.  Cleaned up some stuff.
  199.  *           (Adam D. Moss, adam@foxbox.org)
  200.  *
  201.  * 97/06/23
  202.  * 1.99.4  - Trying to fix some endianness/word-size problems with
  203.  *           transparent gif-saving on some architectures... does
  204.  *           this help?  (Adam D. Moss, adam@foxbox.org)
  205.  *
  206.  * 97/05/18
  207.  * 1.99.3  - Fixed the problem with GIFs getting loop extensions even
  208.  *           if they only had one frame (thanks to Zach for noticing -
  209.  *           git!  :) )  (Adam D. Moss, adam@foxbox.org)
  210.  *
  211.  * 97/05/17
  212.  * 1.99.2  - Can now save animated GIFs.  Correctly handles saving of
  213.  *           image offsets.  Uses N*tscape extentions to loop infinitely.
  214.  *           Some notable shortcomings - see TODO list below.
  215.  *           (Adam D. Moss, adam@foxbox.org)
  216.  *
  217.  * 97/05/16
  218.  * 1.99.1  - Implemented image offsets in animated GIF loading.  Requires
  219.  *           a fix to gimp_layer_translate in libgimp/gimplayer.c if used
  220.  *           with GIMP versions <= 0.99.10.  Started work on saving animated
  221.  *           GIFs.  Started TODO list.  (Adam D. Moss, adam@foxbox.org)
  222.  *
  223.  * 97/05/15
  224.  * 1.99.0  - Started revision log.  GIF plugin now loads/saves INDEXED
  225.  *           and INDEXEDA images with correct transparency where possible.
  226.  *           Loads multi-image (animated) GIFs as a framestack implemented
  227.  *           in GIMP layers.  Some bug fixes to original code, some new bugs
  228.  *           cheerfully added.  (Adam D. Moss, adam@foxbox.org)
  229.  *
  230.  * Previous versions - load/save INDEXED images.
  231.  *           (Peter Mattis & Spencer Kimball, gimp@scam.xcf.berkeley.edu)
  232.  */
  233.  
  234. /*
  235.  * TODO (more *'s means more important!)
  236.  *
  237.  * - PDB stuff for comments
  238.  *
  239.  * - 'requantize' option for INDEXEDA images which really have 256 colours
  240.  *   in them
  241.  *
  242.  * - Be a bit smarter about finding unused/superfluous colour indices for
  243.  *   lossless colour crunching of INDEXEDA images.  (Specifically, look
  244.  *   for multiple indices which correspond to the same physical colour.)
  245.  *
  246.  * - Tidy up parameters for the GIFEncode routines
  247.  *
  248.  * - Remove unused colourmap entries for GRAYSCALE images.
  249.  *
  250.  * - Button to activate the animation preview plugin from the GIF-save
  251.  *   dialog.
  252.  *
  253.  */
  254.  
  255. /* Copyright notice for code which this plugin was long ago derived from */
  256. /* +-------------------------------------------------------------------+ */
  257. /* | Copyright 1990, 1991, 1993, David Koblas.  (koblas@netcom.com)    | */
  258. /* |   Permission to use, copy, modify, and distribute this software   | */
  259. /* |   and its documentation for any purpose and without fee is hereby | */
  260. /* |   granted, provided that the above copyright notice appear in all | */
  261. /* |   copies and that both that copyright notice and this permission  | */
  262. /* |   notice appear in supporting documentation.  This software is    | */
  263. /* |   provided "as is" without express or implied warranty.           | */
  264. /* +-------------------------------------------------------------------+ */
  265.  
  266. #include "config.h"
  267.  
  268. #include <stdio.h>
  269. #include <stdlib.h>
  270. #include <string.h>
  271. #include <ctype.h>
  272.  
  273. #include <libgimp/gimp.h>
  274. #include <libgimp/gimpui.h>
  275.  
  276. #include "libgimp/stdplugins-intl.h"
  277.  
  278.  
  279. /* uncomment the line below for a little debugging info */
  280. /* #define GIFDEBUG yesplease */
  281.  
  282. /* Does the version of GIMP we're compiling for support
  283.    data attachments to images?  ('Parasites') */
  284. #ifdef GIMP_HAVE_PARASITES
  285. #define FACEHUGGERS aieee
  286. #endif
  287. /* PS: I know that technically facehuggers aren't parasites,
  288.    the pupal-forms are.  But facehuggers are ky00te. */
  289.  
  290. enum
  291. {
  292.   DISPOSE_UNSPECIFIED,
  293.   DISPOSE_COMBINE,
  294.   DISPOSE_REPLACE
  295. };
  296.  
  297. typedef struct
  298. {
  299.   gint interlace;
  300.   gint save_comment;
  301.   gint loop;
  302.   gint default_delay;
  303.   gint default_dispose;
  304. } GIFSaveVals;
  305.  
  306. typedef struct
  307. {
  308.   gint run;
  309. } GIFSaveInterface;
  310.  
  311.  
  312.  
  313. /* Declare some local functions.
  314.  */
  315. static void   query                    (void);
  316. static void   run                      (gchar   *name,
  317.                     gint     nparams,
  318.                     GimpParam  *param,
  319.                     gint    *nreturn_vals,
  320.                     GimpParam **return_vals);
  321. static gint   save_image               (gchar   *filename,
  322.                     gint32   image_ID,
  323.                     gint32   drawable_ID,
  324.                     gint32   orig_image_ID);
  325.  
  326. static gboolean boundscheck            (gint32 image_ID);
  327. static gboolean badbounds_dialog       (void);
  328.  
  329. static void   cropok_callback          (GtkWidget *widget, gpointer   data);
  330.  
  331. static gint   save_dialog              (gint32 image_ID);
  332.  
  333. static void   save_ok_callback         (GtkWidget *widget, gpointer   data);
  334. static void   comment_entry_callback   (GtkWidget *widget, gpointer   data);
  335.  
  336.  
  337. static gboolean comment_was_edited = FALSE;
  338.  
  339. static gboolean can_crop = FALSE;
  340. static GimpRunModeType run_mode;
  341. #ifdef FACEHUGGERS
  342. GimpParasite * comment_parasite = NULL;
  343. #endif
  344.  
  345. /* For compression code */
  346. static gint Interlace;
  347.  
  348.  
  349. GimpPlugInInfo PLUG_IN_INFO =
  350. {
  351.   NULL,  /* init_proc  */
  352.   NULL,  /* quit_proc  */
  353.   query, /* query_proc */
  354.   run,   /* run_proc   */
  355. };
  356.  
  357. static GIFSaveVals gsvals =
  358. {
  359.   FALSE,   /* interlace                            */
  360.   TRUE,    /* save comment                         */
  361.   TRUE,    /* loop infinitely                      */
  362.   100,     /* default_delay between frames (100ms) */
  363.   0        /* default_dispose = "don't care"       */
  364. };
  365.  
  366. static GIFSaveInterface gsint =
  367. {
  368.   FALSE   /*  run  */
  369. };
  370.  
  371.  
  372. MAIN ()
  373.  
  374. static void
  375. query (void)
  376. {
  377.   static GimpParamDef save_args[] =
  378.   {
  379.     { GIMP_PDB_INT32,    "run_mode",        "Interactive, non-interactive" },
  380.     { GIMP_PDB_IMAGE,    "image",           "Image to save" },
  381.     { GIMP_PDB_DRAWABLE, "drawable",        "Drawable to save" },
  382.     { GIMP_PDB_STRING,   "filename",        "The name of the file to save the image in" },
  383.     { GIMP_PDB_STRING,   "raw_filename",    "The name entered" },
  384.     { GIMP_PDB_INT32,    "interlace",       "Try to save as interlaced" },
  385.     { GIMP_PDB_INT32,    "loop",            "(animated gif) loop infinitely" },
  386.     { GIMP_PDB_INT32,    "default_delay",   "(animated gif) Default delay between framese in milliseconds" },
  387.     { GIMP_PDB_INT32,    "default_dispose", "(animated gif) Default disposal type (0=`don't care`, 1=combine, 2=replace)" }
  388.   };
  389.   static gint nsave_args = sizeof (save_args) / sizeof (save_args[0]);
  390.  
  391.   gimp_install_procedure ("file_gif_save",
  392.                           "saves files in Compuserve GIF file format",
  393.                           "Save a file in Compuserve GIF format, with "
  394.               "possible animation, transparency, and comment.  "
  395.               "To save an animation, operate on a multi-layer "
  396.               "file.  The plug-in will intrepret <50% alpha as "
  397.               "transparent.  When run non-interactively, the "
  398.               "value for the comment is taken from the "
  399.               "'gimp-comment' parasite.  ",
  400.                           "Spencer Kimball, Peter Mattis, Adam Moss, David Koblas",
  401.                           "Spencer Kimball, Peter Mattis, Adam Moss, David Koblas",
  402.                           "1995-1997",
  403.                           "<Save>/GIF",
  404.               "INDEXED*, GRAY*",
  405.                           GIMP_PLUGIN,
  406.                           nsave_args, 0,
  407.                           save_args, NULL);
  408.  
  409.   gimp_register_save_handler ("file_gif_save",
  410.                   "gif",
  411.                   "");
  412. }
  413.  
  414. static void
  415. run (gchar   *name,
  416.      gint     nparams,
  417.      GimpParam  *param,
  418.      gint    *nreturn_vals,
  419.      GimpParam **return_vals)
  420. {
  421.   static GimpParam values[2];
  422.   GimpPDBStatusType   status = GIMP_PDB_SUCCESS;
  423.   gint32        image_ID;
  424.   gint32        drawable_ID;
  425.   gint32        orig_image_ID;
  426.   GimpExportReturnType export = GIMP_EXPORT_CANCEL;
  427.  
  428.   run_mode = param[0].data.d_int32;
  429.  
  430.   *nreturn_vals = 1;
  431.   *return_vals  = values;
  432.   values[0].type          = GIMP_PDB_STATUS;
  433.   values[0].data.d_status = GIMP_PDB_EXECUTION_ERROR;
  434.  
  435.   if (strcmp (name, "file_gif_save") == 0)
  436.     {
  437.       INIT_I18N_UI();
  438.       gimp_ui_init ("gif", FALSE);
  439.  
  440.       image_ID    = orig_image_ID = param[1].data.d_int32;
  441.       drawable_ID = param[2].data.d_int32;
  442.  
  443.       /*  eventually export the image */ 
  444.       switch (run_mode)
  445.     {
  446.     case GIMP_RUN_INTERACTIVE:
  447.     case GIMP_RUN_WITH_LAST_VALS:
  448.       export = gimp_export_image (&image_ID, &drawable_ID, "GIF", 
  449.                       (GIMP_EXPORT_CAN_HANDLE_INDEXED |
  450.                        GIMP_EXPORT_CAN_HANDLE_GRAY | 
  451.                        GIMP_EXPORT_CAN_HANDLE_ALPHA  |
  452.                        GIMP_EXPORT_CAN_HANDLE_LAYERS_AS_ANIMATION));
  453.       if (export == GIMP_EXPORT_CANCEL)
  454.         {
  455.           values[0].data.d_status = GIMP_PDB_CANCEL;
  456.           return;
  457.         }
  458.       break;
  459.     default:
  460.       break;
  461.     }
  462.  
  463.       if (boundscheck (image_ID))
  464.     /* The image may or may not have had layers out of
  465.        bounds, but the user didn't mind cropping it down. */
  466.     {
  467.       switch (run_mode)
  468.         {
  469.         case GIMP_RUN_INTERACTIVE:
  470.           /*  Possibly retrieve data  */
  471.           gimp_get_data ("file_gif_save", &gsvals);
  472.         
  473.           /*  First acquire information with a dialog  */
  474.           if (! save_dialog (image_ID))
  475.         status = GIMP_PDB_CANCEL;
  476.           break;
  477.           
  478.         case GIMP_RUN_NONINTERACTIVE:
  479.           /*  Make sure all the arguments are there!  */
  480.           if (nparams != 9)
  481.         {
  482.           status = GIMP_PDB_CALLING_ERROR;
  483.         }
  484.           else
  485.         {
  486.           gsvals.interlace       = (param[5].data.d_int32) ? TRUE : FALSE;
  487.           gsvals.save_comment    = TRUE;  /*  no way to to specify that through the PDB  */
  488.           gsvals.loop            = (param[6].data.d_int32) ? TRUE : FALSE;
  489.           gsvals.default_delay   = param[7].data.d_int32;
  490.           gsvals.default_dispose = param[8].data.d_int32;
  491.         }
  492.           break;
  493.           
  494.         case GIMP_RUN_WITH_LAST_VALS:
  495.           /*  Possibly retrieve data  */
  496.           gimp_get_data ("file_gif_save", &gsvals);
  497.           break;
  498.           
  499.         default:
  500.           break;
  501.         }
  502.  
  503.       if (status == GIMP_PDB_SUCCESS)
  504.         {
  505.           if (save_image (param[3].data.d_string,
  506.                   image_ID,
  507.                   drawable_ID,
  508.                   orig_image_ID))
  509.         {
  510.           /*  Store psvals data  */
  511.           gimp_set_data ("file_gif_save", &gsvals, sizeof (GIFSaveVals));
  512.         }
  513.           else
  514.         {
  515.           status = GIMP_PDB_EXECUTION_ERROR;
  516.         }
  517.         }
  518.     }
  519.       else /* Some layers were out of bounds and the user wishes
  520.           to abort.  */
  521.     {
  522.       status = GIMP_PDB_CANCEL;
  523.     }
  524.  
  525.       if (export == GIMP_EXPORT_EXPORT)
  526.     gimp_image_delete (image_ID);
  527.     }
  528.  
  529.   values[0].data.d_status = status;
  530. }
  531.  
  532. #define MAXCOLORMAPSIZE  256
  533.  
  534. #define INTERLACE          0x40
  535. #define LOCALCOLORMAP      0x80
  536.  
  537. #define GRAYSCALE        1
  538. #define COLOR            2
  539.  
  540. typedef guchar CMap[3][MAXCOLORMAPSIZE];
  541.  
  542.  
  543. gint   verbose = FALSE;
  544. gchar *globalcomment = NULL;
  545.  
  546.  
  547.  
  548. /* ppmtogif.c - read a portable pixmap and produce a GIF file
  549. **
  550. ** Based on GIFENCOD by David Rowley <mgardi@watdscu.waterloo.edu>. A
  551. ** Lempel-Ziv compression based on "compress".
  552. **
  553. ** Modified by Marcel Wijkstra <wijkstra@fwi.uva.nl>
  554. **
  555. **
  556. ** Copyright (C) 1989 by Jef Poskanzer.
  557. **
  558. ** Permission to use, copy, modify, and distribute this software and its
  559. ** documentation for any purpose and without fee is hereby granted, provided
  560. ** that the above copyright notice appear in all copies and that both that
  561. ** copyright notice and this permission notice appear in supporting
  562. ** documentation.  This software is provided "as is" without express or
  563. ** implied warranty.
  564. **
  565. ** The Graphics Interchange Format(c) is the Copyright property of
  566. ** CompuServe Incorporated.  GIF(sm) is a Service Mark property of
  567. ** CompuServe Incorporated.
  568. */
  569.  
  570. #define MAXCOLORS 256
  571.  
  572. /*
  573.  * Pointer to function returning an int
  574.  */
  575. typedef int (*ifunptr) (int, int);
  576.  
  577. /*
  578.  * a code_int must be able to hold 2**BITS values of type int, and also -1
  579.  */
  580. typedef int code_int;
  581.  
  582. #ifdef SIGNED_COMPARE_SLOW
  583. typedef unsigned long int count_int;
  584. typedef unsigned short int count_short;
  585. #else /*SIGNED_COMPARE_SLOW */
  586. typedef long int count_int;
  587. #endif /*SIGNED_COMPARE_SLOW */
  588.  
  589.  
  590.  
  591. static int find_unused_ia_colour (guchar *pixels,
  592.                   int numpixels,
  593.                   int num_indices,
  594.                   int* colors);
  595.  
  596. void special_flatten_indexed_alpha (guchar *pixels,
  597.                     int *transparent,
  598.                     int *colors,
  599.                     int numpixels);
  600. static int colorstobpp (int);
  601. static int bpptocolors (int);
  602. static int GetPixel (int, int);
  603. static void BumpPixel (void);
  604. static int GIFNextPixel (ifunptr);
  605.  
  606. static void GIFEncodeHeader (FILE *, gboolean, int, int, int, int,
  607.                  int *, int *, int *, ifunptr);
  608. static void GIFEncodeGraphicControlExt (FILE *, int, int, int, int, int,
  609.                     int, int, int, int *, int *, int *,
  610.                     ifunptr);
  611. static void GIFEncodeImageData (FILE *, int, int, int, int, int, int,
  612.                 int *, int *, int *, ifunptr, gint, gint);
  613. static void GIFEncodeClose (FILE *, int, int, int, int, int, int,
  614.                 int *, int *, int *, ifunptr);
  615. static void GIFEncodeLoopExt (FILE *, guint);
  616. static void GIFEncodeCommentExt (FILE *, char *);
  617.  
  618. int rowstride;
  619. guchar *pixels;
  620. int cur_progress;
  621. int max_progress;
  622.  
  623. static void Putword (int, FILE *);
  624. static void compress (int, FILE *, ifunptr);
  625. static void output (code_int);
  626. static void cl_block (void);
  627. static void cl_hash (count_int);
  628. static void writeerr (void);
  629. static void char_init (void);
  630. static void char_out (int);
  631. static void flush_char (void);
  632.  
  633.  
  634.  
  635. static int find_unused_ia_colour (guchar *pixels,
  636.                   int numpixels,
  637.                   int num_indices,
  638.                   int* colors)
  639. {
  640.   int i;
  641.   gboolean ix_used[256];
  642.  
  643. #ifdef GIFDEBUG
  644.   g_print ("GIF: fuiac: Image claims to use %d/%d indices - finding free "
  645.        "index...\n", (int)(*colors),(int)num_indices);
  646. #endif
  647.  
  648.   for (i=0; i<256; i++)
  649.     {
  650.       ix_used[i] = (gboolean)FALSE;
  651.     }
  652.  
  653.   for (i=0; i<numpixels; i++)
  654.     {
  655.       if (pixels[i*2+1]) ix_used[pixels[i*2]] = (gboolean)TRUE;
  656.     }
  657.   
  658.   for (i=num_indices-1; i>=0; i--)
  659.     {
  660.       if (ix_used[i] == (gboolean)FALSE)
  661.     {
  662. #ifdef GIFDEBUG
  663.       g_print ("GIF: Found unused colour index %d.\n",(int)i);
  664. #endif
  665.       return i;
  666.     }
  667.     }
  668.  
  669.   /* Couldn't find an unused colour index within the number of
  670.      bits per pixel we wanted.  Will have to increment the number
  671.      of colours in the image and assign a transparent pixel there. */
  672.   if ((*colors) < 256)
  673.     {
  674.       (*colors)++;
  675.       g_print ("GIF: 2nd pass - Increasing bounds and using colour index %d.\n"
  676.            , (int) (*colors)-1);
  677.       return ((*colors)-1);
  678.     }
  679.   
  680.   g_message (_("GIF: Couldn't simply reduce colors further.\nSaving as opaque.\n"));
  681.   return (-1);
  682. }
  683.  
  684.  
  685. void
  686. special_flatten_indexed_alpha (guchar *pixels,
  687.                    int *transparent,
  688.                    int *colors,
  689.                    int numpixels)
  690. {
  691.   guint32 i;
  692.  
  693.   /* Each transparent pixel in the image is mapped to a uniform value for
  694.      encoding, if image already has <=255 colours */
  695.   
  696.   if ((*transparent) == -1) /* tough, no indices left for the trans. index */
  697.     {
  698.       for (i=0; i<numpixels; i++)
  699.     pixels[i] = pixels[i*2];
  700.     }
  701.   else  /* make transparent */
  702.     {
  703.       for (i=0; i<numpixels; i++)
  704.     {
  705.       if (!(pixels[i*2+1] & 128))
  706.         {
  707.           pixels[i] = (guchar)(*transparent);
  708.         }
  709.       else
  710.         {
  711.           pixels[i] = pixels[i*2];
  712.         }
  713.     }
  714.     }
  715.  
  716.  
  717.   /* Pixel data now takes half as much space (the alpha data has been
  718.      discarded) */
  719.   /*  pixels = g_realloc (pixels, numpixels);*/
  720. }
  721.  
  722.  
  723. int
  724. parse_ms_tag (char *str)
  725. {
  726.   gint sum = 0;
  727.   gint offset = 0;
  728.   gint length;
  729.  
  730.   length = strlen(str);
  731.  
  732. find_another_bra:
  733.  
  734.   while ((offset<length) && (str[offset]!='('))
  735.     offset++;
  736.   
  737.   if (offset>=length)
  738.     return(-1);
  739.  
  740.   if (!isdigit(str[++offset]))
  741.     goto find_another_bra;
  742.  
  743.   do
  744.     {
  745.       sum *= 10;
  746.       sum += str[offset] - '0';
  747.       offset++;
  748.     }
  749.   while ((offset<length) && (isdigit(str[offset])));  
  750.  
  751.   if (length-offset <= 2)
  752.     return(-3);
  753.  
  754.   if ((toupper(str[offset]) != 'M') || (toupper(str[offset+1]) != 'S'))
  755.     return(-4);
  756.  
  757.   return (sum);
  758. }
  759.  
  760.  
  761. int
  762. parse_disposal_tag (char *str)
  763. {
  764.   gint offset = 0;
  765.   gint length;
  766.  
  767.   length = strlen(str);
  768.  
  769.   while ((offset+9)<=length)
  770.     {
  771.       if (strncmp(&str[offset],"(combine)",9)==0) 
  772.     return(0x01);
  773.       if (strncmp(&str[offset],"(replace)",9)==0) 
  774.     return(0x02);
  775.       offset++;
  776.     }
  777.  
  778.   return (gsvals.default_dispose);
  779. }
  780.  
  781.  
  782. static gboolean
  783. boundscheck (gint32 image_ID)
  784. {
  785.   GimpDrawable *drawable;
  786.   gint32 *layers;   
  787.   gint nlayers;
  788.   gint i;
  789.   gint offset_x, offset_y;
  790.  
  791.   /* get a list of layers for this image_ID */
  792.   layers = gimp_image_get_layers (image_ID, &nlayers);  
  793.  
  794.  
  795.   /*** Iterate through the layers to make sure they're all ***/
  796.   /*** within the bounds of the image                      ***/
  797.  
  798.   for (i=0;i<nlayers;i++)
  799.     {
  800.       drawable = gimp_drawable_get (layers[i]);
  801.       gimp_drawable_offsets (layers[i], &offset_x, &offset_y);
  802.  
  803.       if ((offset_x < 0) ||
  804.       (offset_y < 0) ||
  805.       (offset_x+drawable->width > gimp_image_width(image_ID)) ||
  806.       (offset_y+drawable->height > gimp_image_height(image_ID)))
  807.     {
  808.       g_free (layers);
  809.       gimp_drawable_detach(drawable);
  810.  
  811.       /* Image has illegal bounds - ask the user what it wants to do */
  812.  
  813.       /* Do the crop if we can't talk to the user, or if we asked
  814.        * the user and they said yes. */
  815.       if ((run_mode == GIMP_RUN_NONINTERACTIVE) || badbounds_dialog ())
  816.         {
  817.           gimp_crop (image_ID,
  818.              gimp_image_width (image_ID), gimp_image_height (image_ID), 
  819.              0, 0);
  820.           return TRUE;
  821.         }
  822.       else
  823.         {
  824.           return FALSE;
  825.         }
  826.     }
  827.       else
  828.     gimp_drawable_detach(drawable);
  829.     }
  830.  
  831.   g_free (layers);
  832.  
  833.   return TRUE;
  834. }
  835.  
  836.  
  837. static gint
  838. save_image (gchar  *filename,
  839.         gint32  image_ID,
  840.         gint32  drawable_ID,
  841.         gint32  orig_image_ID)
  842. {
  843.   GimpPixelRgn pixel_rgn;
  844.   GimpDrawable *drawable;
  845.   GimpImageType drawable_type;
  846.   FILE *outfile;
  847.   int Red[MAXCOLORS];
  848.   int Green[MAXCOLORS];
  849.   int Blue[MAXCOLORS];
  850.   guchar *cmap;
  851.   guint rows, cols;
  852.   int BitsPerPixel, liberalBPP=0, useBPP=0;
  853.   int colors;
  854.   char *temp_buf;
  855.   int i;
  856.   int transparent;
  857.   gint offset_x, offset_y;
  858.  
  859.   gint32 *layers;   
  860.   int nlayers;
  861.  
  862.   gboolean is_gif89 = FALSE;
  863.  
  864.   int Delay89;
  865.   int Disposal;
  866.   char *layer_name;
  867.  
  868.   unsigned char bgred, bggreen, bgblue;
  869.  
  870.  
  871. #ifdef FACEHUGGERS
  872.   /* Save the comment back to the ImageID, if appropriate */
  873.   if (globalcomment != NULL && comment_was_edited)
  874.     {
  875.       comment_parasite = gimp_parasite_new ("gimp-comment",
  876.                         GIMP_PARASITE_PERSISTENT,
  877.                         strlen (globalcomment)+1,
  878.                         (void*) globalcomment);
  879.       gimp_image_parasite_attach (orig_image_ID, comment_parasite);
  880.       gimp_parasite_free (comment_parasite);
  881.       comment_parasite = NULL;
  882.     }
  883. #endif
  884.  
  885.  
  886.   /* get a list of layers for this image_ID */
  887.   layers = gimp_image_get_layers (image_ID, &nlayers);  
  888.  
  889.  
  890.   drawable_type = gimp_drawable_type (layers[0]);
  891.  
  892.  
  893.   /* If the image has multiple layers (i.e. will be animated), a comment,
  894.      or transparency, then it must be encoded as a GIF89a file, not a vanilla
  895.      GIF87a. */
  896.   if (nlayers > 1)
  897.     is_gif89 = TRUE;
  898.  
  899.   if (gsvals.save_comment)
  900.     is_gif89 = TRUE;
  901.  
  902.   switch (drawable_type)
  903.     {
  904.     case GIMP_INDEXEDA_IMAGE:
  905.       is_gif89 = TRUE;
  906.     case GIMP_INDEXED_IMAGE:
  907.       cmap = gimp_image_get_cmap (image_ID, &colors);
  908.       
  909.       gimp_palette_get_background(&bgred, &bggreen, &bgblue);
  910.  
  911.       for (i = 0; i < colors; i++)
  912.     {
  913.       Red[i] = *cmap++;
  914.       Green[i] = *cmap++;
  915.       Blue[i] = *cmap++;
  916.     }
  917.       for ( ; i < 256; i++)
  918.     {
  919.       Red[i] = bgred;
  920.       Green[i] = bggreen;
  921.       Blue[i] = bgblue;
  922.     }
  923.       break;
  924.     case GIMP_GRAYA_IMAGE:
  925.       is_gif89 = TRUE;
  926.     case GIMP_GRAY_IMAGE:
  927.       colors = 256;                   /* FIXME: Not ideal. */
  928.       for ( i = 0;  i < 256; i++)
  929.     {
  930.       Red[i] = Green[i] = Blue[i] = i;
  931.     }
  932.       break;
  933.  
  934.     default:
  935.       g_message (_("GIF: Sorry, can't save RGB images as GIFs - convert to INDEXED\nor GRAY first.\n"));
  936.       return FALSE;
  937.       break;
  938.     }
  939.  
  940.   if (run_mode != GIMP_RUN_NONINTERACTIVE)
  941.     {
  942.       /* init the progress meter */    
  943.       temp_buf = g_strdup_printf (_("Saving %s:"), filename);
  944.       gimp_progress_init (temp_buf);
  945.       g_free (temp_buf);
  946.     }
  947.   
  948.  
  949.   /* open the destination file for writing */
  950.   outfile = fopen (filename, "wb");
  951.   if (!outfile)
  952.     {
  953.       g_message (_("GIF: can't open %s\n"), filename);
  954.       return FALSE;
  955.     }
  956.  
  957.  
  958.   /* write the GIFheader */
  959.  
  960.   if (colors < 256)
  961.     {
  962.       /* we keep track of how many bits we promised to have in liberalBPP,
  963.      so that we don't accidentally come under this when doing
  964.      clever transparency stuff where we can re-use wasted indices. */
  965.       liberalBPP = BitsPerPixel =
  966.     colorstobpp (colors + ((drawable_type==GIMP_INDEXEDA_IMAGE) ? 1 : 0));
  967.     }
  968.   else
  969.     {
  970.       liberalBPP = BitsPerPixel =
  971.     colorstobpp (256);
  972.  
  973.       if (drawable_type==GIMP_INDEXEDA_IMAGE)
  974.     {
  975.       g_print ("GIF: Too many colours?\n");
  976.     }
  977.     }
  978.  
  979.   cols = gimp_image_width (image_ID);
  980.   rows = gimp_image_height (image_ID);
  981.   Interlace = gsvals.interlace;
  982.   GIFEncodeHeader (outfile, is_gif89, cols, rows, 0,
  983.            BitsPerPixel, Red, Green, Blue, GetPixel);
  984.  
  985.  
  986.   /* If the image has multiple layers it'll be made into an
  987.      animated GIF, so write out the infinite-looping extension */
  988.   if ((nlayers > 1) && (gsvals.loop))
  989.     GIFEncodeLoopExt (outfile, 0);
  990.  
  991.   /* Write comment extension - mustn't be written before the looping ext. */
  992.   if (gsvals.save_comment)
  993.     {
  994.       GIFEncodeCommentExt (outfile, globalcomment);
  995.     }
  996.  
  997.  
  998.  
  999.   /*** Now for each layer in the image, save an image in a compound GIF ***/
  1000.   /************************************************************************/
  1001.  
  1002.   i = nlayers-1;
  1003.  
  1004.   while (i >= 0)
  1005.     {
  1006.       drawable_type = gimp_drawable_type (layers[i]);
  1007.       drawable = gimp_drawable_get (layers[i]);
  1008.       gimp_drawable_offsets (layers[i], &offset_x, &offset_y);
  1009.       cols = drawable->width;
  1010.       rows = drawable->height;
  1011.       rowstride = drawable->width;
  1012.       
  1013.       gimp_pixel_rgn_init (&pixel_rgn, drawable, 0, 0,
  1014.                drawable->width, drawable->height, FALSE, FALSE);
  1015.  
  1016.       cur_progress = 0;
  1017.       max_progress = drawable->height;
  1018.       
  1019.       pixels = (guchar *) g_malloc (drawable->width *
  1020.                     drawable->height *
  1021.                     (((drawable_type == GIMP_INDEXEDA_IMAGE)||
  1022.                       (drawable_type == GIMP_GRAYA_IMAGE)) ? 2:1) );
  1023.       
  1024.       gimp_pixel_rgn_get_rect (&pixel_rgn, pixels, 0, 0,
  1025.                    drawable->width, drawable->height);
  1026.  
  1027.  
  1028.       /* sort out whether we need to do transparency jiggery-pokery */
  1029.       if ((drawable_type == GIMP_INDEXEDA_IMAGE)||(drawable_type == GIMP_GRAYA_IMAGE))
  1030.     {
  1031.       /* Try to find an entry which isn't actually used in the
  1032.          image, for a transparency index. */
  1033.       
  1034.       transparent =
  1035.         find_unused_ia_colour(pixels,
  1036.                   drawable->width * drawable->height,
  1037.                   bpptocolors(colorstobpp(colors)),
  1038.                   &colors);
  1039.  
  1040.       special_flatten_indexed_alpha (pixels,
  1041.                      &transparent,
  1042.                      &colors,
  1043.                      drawable->width * drawable->height);
  1044.     }
  1045.       else
  1046.     transparent = -1;
  1047.       
  1048.       
  1049.       BitsPerPixel = colorstobpp (colors);
  1050.  
  1051.       if (BitsPerPixel != liberalBPP)
  1052.     {
  1053.       /* We were able to re-use an index within the existing bitspace,
  1054.          whereas the estimate in the header was pessimistic but still
  1055.          needs to be upheld... */
  1056. #ifdef GIFDEBUG
  1057.       g_warning("Promised %d bpp, pondered writing chunk with %d bpp!",
  1058.             liberalBPP, BitsPerPixel);
  1059. #endif
  1060.       g_warning ("Transparent colour *might* be incorrect "
  1061.               "on viewers which don't support transparency.");
  1062.     }
  1063.       useBPP = (BitsPerPixel > liberalBPP) ? BitsPerPixel : liberalBPP;
  1064.  
  1065.       
  1066.       if (is_gif89)
  1067.     {
  1068.       if (i>0)
  1069.         {
  1070.           layer_name = gimp_layer_get_name(layers[i-1]);
  1071.           Disposal = parse_disposal_tag(layer_name);
  1072.           g_free(layer_name);
  1073.         }
  1074.       else
  1075.         Disposal = gsvals.default_dispose;
  1076.  
  1077.       layer_name = gimp_layer_get_name(layers[i]);
  1078.       Delay89 = parse_ms_tag(layer_name);
  1079.       g_free(layer_name);
  1080.  
  1081.       if (Delay89 < 0)
  1082.         Delay89 = (gsvals.default_delay + 5) / 10;
  1083.       else
  1084.         Delay89 = (Delay89 + 5) / 10;
  1085.  
  1086.       /* don't allow a CPU-sucking completely 0-delay looping anim */
  1087.       if ((nlayers > 1) &&
  1088.           gsvals.loop &&
  1089.           (Delay89 == 0))
  1090.         {
  1091.           static gboolean onceonly = FALSE;
  1092.  
  1093.           if (!onceonly)
  1094.         {
  1095.           g_warning("GIF plugin: Delay inserted to prevent evil "
  1096.                 "CPU-sucking anim.\n");
  1097.           onceonly = TRUE;
  1098.         }
  1099.           Delay89 = 1;
  1100.         }
  1101.  
  1102.       GIFEncodeGraphicControlExt (outfile, Disposal, Delay89, nlayers,
  1103.                       cols, rows, 0,
  1104.                       transparent,
  1105.                       useBPP,
  1106.                       Red, Green,
  1107.                       Blue, GetPixel);
  1108.     }
  1109.  
  1110.       GIFEncodeImageData (outfile, cols, rows,
  1111.               (rows>4) ? gsvals.interlace : 0,
  1112.               0, transparent,
  1113.               useBPP,
  1114.               Red, Green, Blue, GetPixel,
  1115.               offset_x, offset_y);
  1116.  
  1117.       
  1118.       
  1119.       gimp_drawable_detach (drawable);
  1120.       
  1121.       g_free (pixels);
  1122.  
  1123.       i--;
  1124.     }
  1125.   
  1126.   g_free(layers);
  1127.  
  1128.   GIFEncodeClose (outfile, cols, rows, gsvals.interlace, 0, transparent,
  1129.           useBPP, Red, Green, Blue, GetPixel);
  1130.  
  1131.   return TRUE;
  1132. }
  1133.  
  1134. static gboolean
  1135. badbounds_dialog (void)
  1136. {
  1137.   GtkWidget *dlg;
  1138.   GtkWidget *label;
  1139.   GtkWidget *frame;
  1140.   GtkWidget *vbox;
  1141.  
  1142.   dlg = gimp_dialog_new (_("GIF Warning"), "gif_warning",
  1143.              gimp_standard_help_func, "filters/gif.html#warning",
  1144.              GTK_WIN_POS_MOUSE,
  1145.              FALSE, FALSE, FALSE,
  1146.  
  1147.              _("OK"), cropok_callback,
  1148.              NULL, NULL, NULL, TRUE, FALSE,
  1149.              _("Cancel"), gtk_widget_destroy,
  1150.              NULL, 1, NULL, FALSE, TRUE,
  1151.  
  1152.              NULL);
  1153.  
  1154.   gtk_signal_connect (GTK_OBJECT (dlg), "destroy",
  1155.               GTK_SIGNAL_FUNC (gtk_main_quit),
  1156.               NULL);
  1157.  
  1158.   /*  the warning message  */
  1159.   frame = gtk_frame_new (NULL);
  1160.   gtk_frame_set_shadow_type (GTK_FRAME (frame), GTK_SHADOW_ETCHED_IN);
  1161.   gtk_container_set_border_width (GTK_CONTAINER (frame), 6);
  1162.   gtk_box_pack_start (GTK_BOX (GTK_DIALOG (dlg)->vbox), frame, TRUE, TRUE, 0);
  1163.  
  1164.   vbox = gtk_vbox_new (FALSE, 4);
  1165.   gtk_container_set_border_width (GTK_CONTAINER (vbox), 4);
  1166.   gtk_container_add (GTK_CONTAINER (frame), vbox);
  1167.   
  1168.   label= gtk_label_new (_("The image which you are trying to save as a GIF\n"
  1169.               "contains layers which extend beyond the actual\n"
  1170.               "borders of the image.  This isn't allowed in GIFs,\n"
  1171.               "I'm afraid.\n\n"
  1172.               "You may choose whether to crop all of the layers to\n"
  1173.               "the image borders, or cancel this save."));
  1174.   gtk_box_pack_start (GTK_BOX (vbox), label, TRUE, TRUE, 0);
  1175.   gtk_widget_show (label);
  1176.  
  1177.   gtk_widget_show (vbox);
  1178.   gtk_widget_show (frame);
  1179.  
  1180.   gtk_widget_show (dlg);
  1181.  
  1182.   gtk_main ();
  1183.   gdk_flush ();
  1184.  
  1185.   return can_crop;
  1186. }
  1187.  
  1188.  
  1189. static gint
  1190. save_dialog (gint32 image_ID)
  1191. {
  1192.   GtkWidget *dlg;
  1193.   GtkWidget *main_vbox;
  1194.   GtkWidget *toggle;
  1195.   GtkWidget *label;
  1196.   GtkWidget *spinbutton;
  1197.   GtkObject *adj;
  1198.   GtkWidget *text;
  1199.   GtkWidget *frame;
  1200.   GtkWidget *vbox;
  1201.   GtkWidget *hbox;
  1202.   GtkWidget *disposal_option_menu;
  1203.   GtkWidget *com_table;
  1204.   GtkWidget *vscrollbar;
  1205. #ifdef FACEHUGGERS
  1206.   GimpParasite* GIF2_CMNT;
  1207. #endif
  1208.  
  1209.   gint32 nlayers;
  1210.  
  1211.   gimp_image_get_layers (image_ID, &nlayers);
  1212.  
  1213.   dlg = gimp_dialog_new (_("Save as GIF"), "gif",
  1214.              gimp_standard_help_func, "filters/gif.html",
  1215.              GTK_WIN_POS_MOUSE,
  1216.              FALSE, TRUE, FALSE,
  1217.  
  1218.              _("OK"), save_ok_callback,
  1219.              NULL, NULL, NULL, TRUE, FALSE,
  1220.              _("Cancel"), gtk_widget_destroy,
  1221.              NULL, 1, NULL, FALSE, TRUE,
  1222.  
  1223.              NULL);
  1224.  
  1225.   gtk_signal_connect (GTK_OBJECT (dlg), "destroy",
  1226.               GTK_SIGNAL_FUNC (gtk_main_quit),
  1227.               NULL);
  1228.  
  1229.   main_vbox = gtk_vbox_new (FALSE, 4);
  1230.   gtk_container_set_border_width (GTK_CONTAINER (main_vbox), 6);
  1231.   gtk_container_add (GTK_CONTAINER (GTK_DIALOG (dlg)->vbox), main_vbox);
  1232.   gtk_widget_show (main_vbox);
  1233.  
  1234.   /*  regular gif parameter settings  */
  1235.   frame = gtk_frame_new (_("GIF Options"));
  1236.   gtk_frame_set_shadow_type (GTK_FRAME (frame), GTK_SHADOW_ETCHED_IN);
  1237.   gtk_box_pack_start (GTK_BOX (main_vbox), frame, TRUE, TRUE, 0);
  1238.  
  1239.   vbox = gtk_vbox_new (FALSE, 4);
  1240.   gtk_container_set_border_width (GTK_CONTAINER (vbox), 4);
  1241.   gtk_container_add (GTK_CONTAINER (frame), vbox);
  1242.  
  1243.   toggle = gtk_check_button_new_with_label (_("Interlace"));
  1244.   gtk_box_pack_start (GTK_BOX (vbox), toggle, FALSE, FALSE, 0);
  1245.   gtk_signal_connect (GTK_OBJECT (toggle), "toggled",
  1246.               GTK_SIGNAL_FUNC (gimp_toggle_button_update),
  1247.               &gsvals.interlace);
  1248.   gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (toggle), gsvals.interlace);
  1249.   gtk_widget_show (toggle);
  1250.  
  1251.   hbox = gtk_hbox_new (FALSE, 4);
  1252.   gtk_box_pack_start (GTK_BOX (vbox), hbox, TRUE, TRUE, 0);
  1253.  
  1254.   toggle = gtk_check_button_new_with_label (_("GIF Comment:"));
  1255.   gtk_box_pack_start (GTK_BOX (hbox), toggle, FALSE, FALSE, 0);
  1256.   gtk_signal_connect (GTK_OBJECT (toggle), "toggled",
  1257.               GTK_SIGNAL_FUNC (gimp_toggle_button_update),
  1258.               &gsvals.save_comment);
  1259.   gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (toggle), gsvals.save_comment);
  1260.   gtk_widget_show (toggle);
  1261.  
  1262.   com_table = gtk_table_new (1, 1, FALSE);
  1263.   gtk_box_pack_start (GTK_BOX (hbox), com_table, TRUE, TRUE, 0);
  1264.  
  1265.   text = gtk_text_new (NULL, NULL);
  1266.   gtk_text_set_editable (GTK_TEXT (text), TRUE);
  1267.   gtk_widget_set_usize (text, 80,3);
  1268.   gtk_table_attach (GTK_TABLE (com_table), text, 0, 1, 0, 1,
  1269.                     GTK_EXPAND | GTK_SHRINK | GTK_FILL,
  1270.                     GTK_EXPAND | GTK_SHRINK | GTK_FILL, 0, 0);
  1271.   
  1272.   if (globalcomment != NULL)
  1273.     {
  1274.       g_free (globalcomment);
  1275.     }
  1276. #ifdef FACEHUGGERS
  1277.   GIF2_CMNT = gimp_image_parasite_find (image_ID, "gimp-comment");
  1278.   if (GIF2_CMNT)
  1279.     {
  1280.       globalcomment = g_malloc (GIF2_CMNT->size+1);
  1281.       memcpy (globalcomment, GIF2_CMNT->data, GIF2_CMNT->size);
  1282.       globalcomment[GIF2_CMNT->size] = 0;
  1283.     }
  1284.   else
  1285.     {
  1286. #endif
  1287.       /*    globalcomment = g_malloc(1+strlen(_("Made with GIMP")));
  1288.         strcpy(globalcomment, _("Made with GIMP")); */
  1289.       globalcomment = NULL;
  1290. #ifdef FACEHUGGERS
  1291.     }
  1292.   gimp_parasite_free (GIF2_CMNT);
  1293. #endif
  1294.  
  1295.   if (globalcomment)
  1296.     gtk_text_insert (GTK_TEXT (text), NULL, NULL, NULL, globalcomment, -1);
  1297.   gtk_signal_connect (GTK_OBJECT (text), "changed",
  1298.               GTK_SIGNAL_FUNC (comment_entry_callback),
  1299.               NULL);
  1300.  
  1301.   vscrollbar = gtk_vscrollbar_new (GTK_TEXT (text)->vadj);
  1302.   gtk_table_attach (GTK_TABLE (com_table), vscrollbar, 1, 2, 0, 1,
  1303.             GTK_FILL, GTK_EXPAND | GTK_SHRINK | GTK_FILL, 0, 0);
  1304.   gtk_widget_show (vscrollbar);
  1305.   gtk_widget_show (text);
  1306.   gtk_widget_show (com_table);
  1307.  
  1308.   gtk_widget_show (hbox);
  1309.  
  1310.   gtk_widget_show (vbox);
  1311.   gtk_widget_show (frame);
  1312.  
  1313.   /*  additional animated gif parameter settings  */
  1314.   frame = gtk_frame_new (_("Animated GIF Options"));
  1315.   gtk_frame_set_shadow_type (GTK_FRAME (frame), GTK_SHADOW_ETCHED_IN);
  1316.   gtk_box_pack_start (GTK_BOX (main_vbox), frame, FALSE, FALSE, 0);
  1317.  
  1318.   vbox = gtk_vbox_new (FALSE, 4);
  1319.   gtk_container_set_border_width (GTK_CONTAINER (vbox), 4);
  1320.   gtk_container_add (GTK_CONTAINER (frame), vbox);
  1321.  
  1322.   toggle = gtk_check_button_new_with_label (_("Loop forever"));
  1323.   gtk_box_pack_start (GTK_BOX (vbox), toggle, FALSE, FALSE, 0);
  1324.   gtk_signal_connect (GTK_OBJECT (toggle), "toggled",
  1325.               GTK_SIGNAL_FUNC (gimp_toggle_button_update),
  1326.               &gsvals.loop);
  1327.   gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (toggle), gsvals.loop);
  1328.   gtk_widget_show (toggle);
  1329.  
  1330.   /* default_delay entry field */
  1331.   hbox = gtk_hbox_new (FALSE, 4);
  1332.   gtk_box_pack_start (GTK_BOX (vbox), hbox, FALSE, FALSE, 0);
  1333.  
  1334.   label = gtk_label_new (_("Delay between Frames where Unspecified:"));
  1335.   gtk_box_pack_start (GTK_BOX (hbox), label, FALSE, FALSE, 0);
  1336.   gtk_widget_show (label);
  1337.  
  1338.   spinbutton = gimp_spin_button_new (&adj, gsvals.default_delay,
  1339.                      0, 65000, 10, 100, 0, 1, 0);
  1340.   gtk_box_pack_start (GTK_BOX (hbox), spinbutton, FALSE, FALSE, 0);
  1341.   gtk_signal_connect (GTK_OBJECT (adj), "value_changed",
  1342.                       GTK_SIGNAL_FUNC (gimp_int_adjustment_update),
  1343.                       &gsvals.default_delay);
  1344.   gtk_widget_show (spinbutton);
  1345.  
  1346.   label = gtk_label_new (_("Milliseconds"));
  1347.   gtk_box_pack_start (GTK_BOX (hbox), label, FALSE, FALSE, 0);
  1348.   gtk_widget_show (label);
  1349.  
  1350.   gtk_widget_show (hbox);
  1351.  
  1352.   /* Disposal selector */
  1353.   hbox = gtk_hbox_new (FALSE, 4);
  1354.   gtk_box_pack_start (GTK_BOX (vbox), hbox, FALSE, FALSE, 0);
  1355.  
  1356.   label = gtk_label_new (_("Frame Disposal where Unspecified: "));
  1357.   gtk_box_pack_start (GTK_BOX (hbox), label, FALSE, FALSE, 0);
  1358.   gtk_widget_show (label);
  1359.  
  1360.   disposal_option_menu =
  1361.     gimp_option_menu_new2 (FALSE, gimp_menu_item_update,
  1362.                &gsvals.default_dispose,
  1363.                (gpointer) gsvals.default_dispose,
  1364.  
  1365.                _("I don't Care"),
  1366.                (gpointer) DISPOSE_UNSPECIFIED, NULL,
  1367.                _("Cumulative Layers (Combine)"),
  1368.                (gpointer) DISPOSE_COMBINE, NULL,
  1369.                _("One Frame per Layer (Replace)"),
  1370.                (gpointer) DISPOSE_REPLACE, NULL,
  1371.  
  1372.                NULL);
  1373.   gtk_box_pack_start (GTK_BOX (hbox), disposal_option_menu, FALSE, FALSE, 0);
  1374.   gtk_widget_show (disposal_option_menu);
  1375.  
  1376.   gtk_widget_show (hbox);
  1377.   gtk_widget_show (vbox);
  1378.  
  1379.   /* If the image has only one layer it can't be animated, so
  1380.      desensitize the animation options. */
  1381.  
  1382.   if (nlayers == 1) gtk_widget_set_sensitive (frame, FALSE);
  1383.  
  1384.   gtk_widget_show (frame);
  1385.  
  1386.   gtk_widget_show (dlg);
  1387.  
  1388.   gtk_main ();
  1389.   gdk_flush ();
  1390.  
  1391.   return gsint.run;
  1392. }
  1393.  
  1394.  
  1395. static int
  1396. colorstobpp (int colors)
  1397. {
  1398.   int bpp;
  1399.  
  1400.   if (colors <= 2)
  1401.     bpp = 1;
  1402.   else if (colors <= 4)
  1403.     bpp = 2;
  1404.   else if (colors <= 8)
  1405.     bpp = 3;
  1406.   else if (colors <= 16)
  1407.     bpp = 4;
  1408.   else if (colors <= 32)
  1409.     bpp = 5;
  1410.   else if (colors <= 64)
  1411.     bpp = 6;
  1412.   else if (colors <= 128)
  1413.     bpp = 7;
  1414.   else if (colors <= 256)
  1415.     bpp = 8;
  1416.   else
  1417.     {
  1418.       g_warning ("GIF: colorstobpp - Eep! too many colours: %d\n", colors);
  1419.       return 8;
  1420.     }
  1421.  
  1422.   return bpp;
  1423. }
  1424.  
  1425.  
  1426.  
  1427. static int
  1428. bpptocolors (int bpp)
  1429. {
  1430.   int colors;
  1431.  
  1432.   if (bpp>8)
  1433.     {
  1434.       g_warning ("GIF: bpptocolors - Eep! bpp==%d !\n", bpp);
  1435.       return 256;
  1436.     }
  1437.   
  1438.   colors = 1 << bpp;
  1439.  
  1440.   return (colors);
  1441. }
  1442.  
  1443.  
  1444.  
  1445. static int
  1446. GetPixel (int x,
  1447.       int y)
  1448. {
  1449.   return *(pixels + (rowstride * (long) y) + (long) x);
  1450. }
  1451.  
  1452.  
  1453. /*****************************************************************************
  1454.  *
  1455.  * GIFENCODE.C    - GIF Image compression interface
  1456.  *
  1457.  * GIFEncode( FName, GHeight, GWidth, GInterlace, Background, Transparent,
  1458.  *            BitsPerPixel, Red, Green, Blue, GetPixel )
  1459.  *
  1460.  *****************************************************************************/
  1461.  
  1462. static gint  Width, Height;
  1463. static gint  curx, cury;
  1464. static glong CountDown;
  1465. static gint  Pass = 0;
  1466.  
  1467. /*
  1468.  * Bump the 'curx' and 'cury' to point to the next pixel
  1469.  */
  1470. static void
  1471. BumpPixel (void)
  1472. {
  1473.   /*
  1474.    * Bump the current X position
  1475.    */
  1476.   curx++;
  1477.  
  1478.   /*
  1479.    * If we are at the end of a scan line, set curx back to the beginning
  1480.    * If we are interlaced, bump the cury to the appropriate spot,
  1481.    * otherwise, just increment it.
  1482.    */
  1483.   if (curx == Width)
  1484.     {
  1485.       if (run_mode != GIMP_RUN_NONINTERACTIVE)
  1486.     {
  1487.       cur_progress++;
  1488.       if ((cur_progress % 16) == 0)
  1489.         gimp_progress_update ((double) cur_progress / (double) max_progress);
  1490.     }
  1491.  
  1492.       curx = 0;
  1493.  
  1494.       if (!Interlace)
  1495.     ++cury;
  1496.       else
  1497.     {
  1498.       switch (Pass)
  1499.         {
  1500.  
  1501.         case 0:
  1502.           cury += 8;
  1503.           if (cury >= Height)
  1504.         {
  1505.           Pass++;
  1506.           cury = 4;
  1507.         }
  1508.           break;
  1509.  
  1510.         case 1:
  1511.           cury += 8;
  1512.           if (cury >= Height)
  1513.         {
  1514.           Pass++;
  1515.           cury = 2;
  1516.         }
  1517.           break;
  1518.  
  1519.         case 2:
  1520.           cury += 4;
  1521.           if (cury >= Height)
  1522.         {
  1523.           Pass++;
  1524.           cury = 1;
  1525.         }
  1526.           break;
  1527.  
  1528.         case 3:
  1529.           cury += 2;
  1530.           break;
  1531.         }
  1532.     }
  1533.     }
  1534. }
  1535.  
  1536. /*
  1537.  * Return the next pixel from the image
  1538.  */
  1539. static int
  1540. GIFNextPixel (ifunptr getpixel)
  1541. {
  1542.   int r;
  1543.  
  1544.   if (CountDown == 0)
  1545.     return EOF;
  1546.  
  1547.   --CountDown;
  1548.  
  1549.   r = (*getpixel) (curx, cury);
  1550.  
  1551.   BumpPixel ();
  1552.  
  1553.   return r;
  1554. }
  1555.  
  1556. /* public */
  1557.  
  1558. static void
  1559. GIFEncodeHeader (FILE    *fp,
  1560.          gboolean gif89,
  1561.          int      GWidth,
  1562.          int      GHeight,
  1563.          int      Background,
  1564.          int      BitsPerPixel,
  1565.          int      Red[],
  1566.          int      Green[],
  1567.          int      Blue[],
  1568.          ifunptr  GetPixel)
  1569. {
  1570.   int B;
  1571.   int RWidth, RHeight;
  1572.   int LeftOfs, TopOfs;
  1573.   int Resolution;
  1574.   int ColorMapSize;
  1575.   int InitCodeSize;
  1576.   int i;
  1577.  
  1578.   ColorMapSize = 1 << BitsPerPixel;
  1579.  
  1580.   RWidth = Width = GWidth;
  1581.   RHeight = Height = GHeight;
  1582.   LeftOfs = TopOfs = 0;
  1583.  
  1584.   Resolution = BitsPerPixel;
  1585.  
  1586.   /*
  1587.    * Calculate number of bits we are expecting
  1588.    */
  1589.   CountDown = (long) Width *(long) Height;
  1590.  
  1591.   /*
  1592.    * Indicate which pass we are on (if interlace)
  1593.    */
  1594.   Pass = 0;
  1595.  
  1596.   /*
  1597.    * The initial code size
  1598.    */
  1599.   if (BitsPerPixel <= 1)
  1600.     InitCodeSize = 2;
  1601.   else
  1602.     InitCodeSize = BitsPerPixel;
  1603.  
  1604.   /*
  1605.    * Set up the current x and y position
  1606.    */
  1607.   curx = cury = 0;
  1608.  
  1609.   /*
  1610.    * Write the Magic header
  1611.    */
  1612.   fwrite (gif89 ? "GIF89a" : "GIF87a", 1, 6, fp);
  1613.  
  1614.   /*
  1615.    * Write out the screen width and height
  1616.    */
  1617.   Putword (RWidth, fp);
  1618.   Putword (RHeight, fp);
  1619.  
  1620.   /*
  1621.    * Indicate that there is a global colour map
  1622.    */
  1623.   B = 0x80;            /* Yes, there is a color map */
  1624.  
  1625.   /*
  1626.    * OR in the resolution
  1627.    */
  1628.   B |= (Resolution - 1) << 5;
  1629.  
  1630.   /*
  1631.    * OR in the Bits per Pixel
  1632.    */
  1633.   B |= (BitsPerPixel - 1);
  1634.  
  1635.   /*
  1636.    * Write it out
  1637.    */
  1638.   fputc (B, fp);
  1639.  
  1640.   /*
  1641.    * Write out the Background colour
  1642.    */
  1643.   fputc (Background, fp);
  1644.  
  1645.   /*
  1646.    * Byte of 0's (future expansion)
  1647.    */
  1648.   fputc (0, fp);
  1649.  
  1650.   /*
  1651.    * Write out the Global Colour Map
  1652.    */
  1653.   for (i = 0; i < ColorMapSize; i++)
  1654.     {
  1655.       fputc (Red[i], fp);
  1656.       fputc (Green[i], fp);
  1657.       fputc (Blue[i], fp);
  1658.     }
  1659. }
  1660.  
  1661.  
  1662. static void
  1663. GIFEncodeGraphicControlExt (FILE    *fp,
  1664.                 int      Disposal,
  1665.                 int      Delay89,
  1666.                 int      NumFramesInImage,
  1667.                 int      GWidth,
  1668.                 int      GHeight,
  1669.                 int      Background,
  1670.                 int      Transparent,
  1671.                 int      BitsPerPixel,
  1672.                 int      Red[],
  1673.                 int      Green[],
  1674.                 int      Blue[],
  1675.                 ifunptr  GetPixel)
  1676. {
  1677.   int RWidth, RHeight;
  1678.   int LeftOfs, TopOfs;
  1679.   int Resolution;
  1680.   int ColorMapSize;
  1681.   int InitCodeSize;
  1682.  
  1683.   ColorMapSize = 1 << BitsPerPixel;
  1684.  
  1685.   RWidth = Width = GWidth;
  1686.   RHeight = Height = GHeight;
  1687.   LeftOfs = TopOfs = 0;
  1688.  
  1689.   Resolution = BitsPerPixel;
  1690.  
  1691.   /*
  1692.    * Calculate number of bits we are expecting
  1693.    */
  1694.   CountDown = (long) Width *(long) Height;
  1695.  
  1696.   /*
  1697.    * Indicate which pass we are on (if interlace)
  1698.    */
  1699.   Pass = 0;
  1700.  
  1701.   /*
  1702.    * The initial code size
  1703.    */
  1704.   if (BitsPerPixel <= 1)
  1705.     InitCodeSize = 2;
  1706.   else
  1707.     InitCodeSize = BitsPerPixel;
  1708.  
  1709.   /*
  1710.    * Set up the current x and y position
  1711.    */
  1712.   curx = cury = 0;
  1713.  
  1714.   /*
  1715.    * Write out extension for transparent colour index, if necessary.
  1716.    */
  1717.   if ( (Transparent >= 0) || (NumFramesInImage > 1) )
  1718.     {
  1719.       /* Extension Introducer - fixed. */
  1720.       fputc ('!', fp);
  1721.       /* Graphic Control Label - fixed. */
  1722.       fputc (0xf9, fp);
  1723.       /* Block Size - fixed. */
  1724.       fputc (4, fp);
  1725.       
  1726.       /* Packed Fields - XXXdddut (d=disposal, u=userInput, t=transFlag) */
  1727.       /*                    s8421                                        */
  1728.       fputc ( ((Transparent >= 0) ? 0x01 : 0x00) /* TRANSPARENCY */
  1729.  
  1730.           /* DISPOSAL */
  1731.           | ((NumFramesInImage > 1) ? (Disposal << 2) : 0x00 ),
  1732.           /* 0x03 or 0x01 build frames cumulatively */
  1733.           /* 0x02 clears frame before drawing */
  1734.           /* 0x00 'don't care' */
  1735.  
  1736.           fp);
  1737.       
  1738.       fputc (Delay89 & 255, fp);
  1739.       fputc ((Delay89>>8) & 255, fp);
  1740.  
  1741.       fputc (Transparent, fp);
  1742.       fputc (0, fp);
  1743.     }
  1744. }
  1745.  
  1746.  
  1747. static void
  1748. GIFEncodeImageData (FILE    *fp,
  1749.             int      GWidth,
  1750.             int      GHeight,
  1751.             int      GInterlace,
  1752.             int      Background,
  1753.             int      Transparent,
  1754.             int      BitsPerPixel,
  1755.             int      Red[],
  1756.             int      Green[],
  1757.             int      Blue[],
  1758.             ifunptr  GetPixel,
  1759.             gint     offset_x,
  1760.             gint     offset_y)
  1761. {
  1762.   int RWidth, RHeight;
  1763.   int LeftOfs, TopOfs;
  1764.   int Resolution;
  1765.   int ColorMapSize;
  1766.   int InitCodeSize;
  1767.  
  1768.   Interlace = GInterlace;
  1769.  
  1770.   ColorMapSize = 1 << BitsPerPixel;
  1771.  
  1772.   RWidth = Width = GWidth;
  1773.   RHeight = Height = GHeight;
  1774.   LeftOfs = (int) offset_x;
  1775.   TopOfs = (int) offset_y;
  1776.  
  1777.   Resolution = BitsPerPixel;
  1778.  
  1779.   /*
  1780.    * Calculate number of bits we are expecting
  1781.    */
  1782.   CountDown = (long) Width *(long) Height;
  1783.  
  1784.   /*
  1785.    * Indicate which pass we are on (if interlace)
  1786.    */
  1787.   Pass = 0;
  1788.  
  1789.   /*
  1790.    * The initial code size
  1791.    */
  1792.   if (BitsPerPixel <= 1)
  1793.     InitCodeSize = 2;
  1794.   else
  1795.     InitCodeSize = BitsPerPixel;
  1796.  
  1797.   /*
  1798.    * Set up the current x and y position
  1799.    */
  1800.   curx = cury = 0;
  1801.  
  1802. #if 0
  1803.   /*
  1804.    * Write an Image separator
  1805.    */
  1806.   fputc (',', fp);
  1807.  
  1808.   /*
  1809.    * Write the Image header
  1810.    */
  1811.  
  1812.   Putword (LeftOfs, fp);
  1813.   Putword (TopOfs, fp);
  1814.   Putword (Width, fp);
  1815.   Putword (Height, fp);
  1816.  
  1817.   /*
  1818.    * Write out whether or not the image is interlaced
  1819.    */
  1820.   if (Interlace)
  1821.     fputc (0x40, fp);
  1822.   else
  1823.     fputc (0x00, fp);
  1824.  
  1825.   /*
  1826.    * Write out the initial code size
  1827.    */
  1828.   fputc (InitCodeSize, fp);
  1829.  
  1830.   /*
  1831.    * Go and actually compress the data
  1832.    */
  1833.   compress (InitCodeSize + 1, fp, GetPixel);
  1834.  
  1835.   /*
  1836.    * Write out a Zero-length packet (to end the series)
  1837.    */
  1838.   fputc (0, fp);
  1839.  
  1840.  
  1841.   /***************************/
  1842.   Interlace = GInterlace;
  1843.   ColorMapSize = 1 << BitsPerPixel;
  1844.   RWidth = Width = GWidth;
  1845.   RHeight = Height = GHeight;
  1846.   LeftOfs = TopOfs = 0;
  1847.   Resolution = BitsPerPixel;
  1848.  
  1849.   CountDown = (long) Width *(long) Height;
  1850.   Pass = 0;
  1851.   /*
  1852.    * The initial code size
  1853.    */
  1854.   if (BitsPerPixel <= 1)
  1855.     InitCodeSize = 2;
  1856.   else
  1857.     InitCodeSize = BitsPerPixel;
  1858.   /*
  1859.    * Set up the current x and y position
  1860.    */
  1861.   curx = cury = 0;
  1862.  
  1863. #endif
  1864.  
  1865.  
  1866.   cur_progress = 0;
  1867.  
  1868.  
  1869.   /*
  1870.    * Write an Image separator
  1871.    */
  1872.   fputc (',', fp);
  1873.  
  1874.   /*
  1875.    * Write the Image header
  1876.    */
  1877.  
  1878.   Putword (LeftOfs, fp);
  1879.   Putword (TopOfs, fp);
  1880.   Putword (Width, fp);
  1881.   Putword (Height, fp);
  1882.  
  1883.   /*
  1884.    * Write out whether or not the image is interlaced
  1885.    */
  1886.   if (Interlace)
  1887.     fputc (0x40, fp);
  1888.   else
  1889.     fputc (0x00, fp);
  1890.  
  1891.   /*
  1892.    * Write out the initial code size
  1893.    */
  1894.   fputc (InitCodeSize, fp);
  1895.  
  1896.   /*
  1897.    * Go and actually compress the data
  1898.    */
  1899.   compress (InitCodeSize + 1, fp, GetPixel);
  1900.  
  1901.   /*
  1902.    * Write out a Zero-length packet (to end the series)
  1903.    */
  1904.   fputc (0, fp);
  1905. }
  1906.  
  1907.  
  1908. static void
  1909. GIFEncodeClose (FILE    *fp,
  1910.         int      GWidth,
  1911.         int      GHeight,
  1912.         int      GInterlace,
  1913.         int      Background,
  1914.         int      Transparent,
  1915.         int      BitsPerPixel,
  1916.         int      Red[],
  1917.         int      Green[],
  1918.         int      Blue[],
  1919.         ifunptr  GetPixel)
  1920. {
  1921.   /*
  1922.    * Write the GIF file terminator
  1923.    */
  1924.   fputc (';', fp);
  1925.  
  1926.   /*
  1927.    * And close the file
  1928.    */
  1929.   fclose (fp);
  1930. }
  1931.  
  1932.  
  1933. static void
  1934. GIFEncodeLoopExt (FILE    *fp,
  1935.           guint    num_loops)
  1936. {
  1937.   fputc(0x21,fp);
  1938.   fputc(0xff,fp);
  1939.   fputc(0x0b,fp);
  1940.   fputs("NETSCAPE2.0",fp);
  1941.   fputc(0x03,fp);
  1942.   fputc(0x01,fp);
  1943.   Putword(num_loops,fp);
  1944.   fputc(0x00,fp);
  1945.  
  1946.   /* NOTE: num_loops==0 means 'loop infinitely' */
  1947. }
  1948.  
  1949.  
  1950. static void GIFEncodeCommentExt (FILE *fp, char *comment)
  1951. {
  1952.   if (!comment || !*comment)
  1953.     return;
  1954.  
  1955.   if (strlen(comment)>240)
  1956.     {
  1957.       g_print ("GIF: warning: comment too large - comment block not written.\n");
  1958.       return;
  1959.     }
  1960.  
  1961.   fputc(0x21,fp);
  1962.   fputc(0xfe,fp);
  1963.   fputc(strlen(comment),fp);
  1964.   fputs((const char *)comment,fp);
  1965.   fputc(0x00,fp);
  1966. }
  1967.  
  1968.  
  1969.  
  1970. /*
  1971.  * Write out a word to the GIF file
  1972.  */
  1973. static void
  1974. Putword (int   w,
  1975.      FILE *fp)
  1976. {
  1977.   fputc (w & 0xff, fp);
  1978.   fputc ((w / 256) & 0xff, fp);
  1979. }
  1980.  
  1981.  
  1982. /***************************************************************************
  1983.  *
  1984.  *  GIFCOMPR.C       - GIF Image compression routines
  1985.  *
  1986.  *  Lempel-Ziv compression based on 'compress'.  GIF modifications by
  1987.  *  David Rowley (mgardi@watdcsu.waterloo.edu)
  1988.  *
  1989.  ***************************************************************************/
  1990.  
  1991. /*
  1992.  * General DEFINEs
  1993.  */
  1994.  
  1995. #define GIF_BITS    12
  1996.  
  1997. #define HSIZE  5003        /* 80% occupancy */
  1998.  
  1999. #ifdef NO_UCHAR
  2000. typedef char char_type;
  2001. #else /*NO_UCHAR */
  2002. typedef unsigned char char_type;
  2003. #endif /*NO_UCHAR */
  2004.  
  2005. /*
  2006.  
  2007.  * GIF Image compression - modified 'compress'
  2008.  *
  2009.  * Based on: compress.c - File compression ala IEEE Computer, June 1984.
  2010.  *
  2011.  * By Authors:  Spencer W. Thomas       (decvax!harpo!utah-cs!utah-gr!thomas)
  2012.  *              Jim McKie               (decvax!mcvax!jim)
  2013.  *              Steve Davies            (decvax!vax135!petsd!peora!srd)
  2014.  *              Ken Turkowski           (decvax!decwrl!turtlevax!ken)
  2015.  *              James A. Woods          (decvax!ihnp4!ames!jaw)
  2016.  *              Joe Orost               (decvax!vax135!petsd!joe)
  2017.  *
  2018.  */
  2019. #include <ctype.h>
  2020.  
  2021. #define ARGVAL() (*++(*argv) || (--argc && *++argv))
  2022.  
  2023. static int n_bits;        /* number of bits/code */
  2024. static int maxbits = GIF_BITS;    /* user settable max # bits/code */
  2025. static code_int maxcode;    /* maximum code, given n_bits */
  2026. static code_int maxmaxcode = (code_int) 1 << GIF_BITS;    /* should NEVER generate this code */
  2027. #ifdef COMPATIBLE        /* But wrong! */
  2028. #define MAXCODE(Mn_bits)        ((code_int) 1 << (Mn_bits) - 1)
  2029. #else /*COMPATIBLE */
  2030. #define MAXCODE(Mn_bits)        (((code_int) 1 << (Mn_bits)) - 1)
  2031. #endif /*COMPATIBLE */
  2032.  
  2033. static count_int htab[HSIZE];
  2034. static unsigned short codetab[HSIZE];
  2035. #define HashTabOf(i)       htab[i]
  2036. #define CodeTabOf(i)    codetab[i]
  2037.  
  2038. const code_int hsize = HSIZE;    /* the original reason for this being
  2039.                    variable was "for dynamic table sizing",
  2040.                    but since it was never actually changed
  2041.                    I made it const   --Adam. */
  2042.  
  2043. /*
  2044.  * To save much memory, we overlay the table used by compress() with those
  2045.  * used by decompress().  The tab_prefix table is the same size and type
  2046.  * as the codetab.  The tab_suffix table needs 2**GIF_BITS characters.  We
  2047.  * get this from the beginning of htab.  The output stack uses the rest
  2048.  * of htab, and contains characters.  There is plenty of room for any
  2049.  * possible stack (stack used to be 8000 characters).
  2050.  */
  2051.  
  2052. #define tab_prefixof(i) CodeTabOf(i)
  2053. #define tab_suffixof(i)        ((char_type*)(htab))[i]
  2054. #define de_stack               ((char_type*)&tab_suffixof((code_int)1<<GIF_BITS))
  2055.  
  2056. static code_int free_ent = 0;    /* first unused entry */
  2057.  
  2058. /*
  2059.  * block compression parameters -- after all codes are used up,
  2060.  * and compression rate changes, start over.
  2061.  */
  2062. static int clear_flg = 0;
  2063.  
  2064. static int offset;
  2065. static long int in_count = 1;    /* length of input */
  2066. static long int out_count = 0;    /* # of codes output (for debugging) */
  2067.  
  2068. /*
  2069.  * compress stdin to stdout
  2070.  *
  2071.  * Algorithm:  use open addressing double hashing (no chaining) on the
  2072.  * prefix code / next character combination.  We do a variant of Knuth's
  2073.  * algorithm D (vol. 3, sec. 6.4) along with G. Knott's relatively-prime
  2074.  * secondary probe.  Here, the modular division first probe is gives way
  2075.  * to a faster exclusive-or manipulation.  Also do block compression with
  2076.  * an adaptive reset, whereby the code table is cleared when the compression
  2077.  * ratio decreases, but after the table fills.  The variable-length output
  2078.  * codes are re-sized at this point, and a special CLEAR code is generated
  2079.  * for the decompressor.  Late addition:  construct the table according to
  2080.  * file size for noticeable speed improvement on small files.  Please direct
  2081.  * questions about this implementation to ames!jaw.
  2082.  */
  2083.  
  2084. static int g_init_bits;
  2085. static FILE *g_outfile;
  2086.  
  2087. static int ClearCode;
  2088. static int EOFCode;
  2089.  
  2090.  
  2091. static unsigned long cur_accum;
  2092. static int cur_bits;
  2093.  
  2094. static unsigned long masks[] =
  2095. {0x0000, 0x0001, 0x0003, 0x0007, 0x000F,
  2096.  0x001F, 0x003F, 0x007F, 0x00FF,
  2097.  0x01FF, 0x03FF, 0x07FF, 0x0FFF,
  2098.  0x1FFF, 0x3FFF, 0x7FFF, 0xFFFF};
  2099.  
  2100.  
  2101. static void
  2102. compress (int      init_bits,
  2103.       FILE    *outfile,
  2104.       ifunptr  ReadValue)
  2105. {
  2106.   register long fcode;
  2107.   register code_int i /* = 0 */ ;
  2108.   register int c;
  2109.   register code_int ent;
  2110.   register code_int disp;
  2111.   register code_int hsize_reg;
  2112.   register int hshift;
  2113.  
  2114.  
  2115.   /*
  2116.    * Set up the globals:  g_init_bits - initial number of bits
  2117.    *                      g_outfile   - pointer to output file
  2118.    */
  2119.   g_init_bits = init_bits;
  2120.   g_outfile = outfile;
  2121.  
  2122.   cur_bits = 0;
  2123.   cur_accum = 0;
  2124.  
  2125.   /*
  2126.    * Set up the necessary values
  2127.    */
  2128.   offset = 0;
  2129.   out_count = 0;
  2130.   clear_flg = 0;
  2131.   in_count = 1;
  2132.  
  2133.   ClearCode = (1 << (init_bits - 1));
  2134.   EOFCode = ClearCode + 1;
  2135.   free_ent = ClearCode + 2;
  2136.  
  2137.  
  2138.   /* Had some problems here... should be okay now.  --Adam */
  2139.   n_bits = g_init_bits;
  2140.   maxcode = MAXCODE (n_bits);
  2141.  
  2142.  
  2143.  
  2144.   char_init ();
  2145.  
  2146.   ent = GIFNextPixel (ReadValue);
  2147.  
  2148.   hshift = 0;
  2149.   for (fcode = (long) hsize; fcode < 65536L; fcode *= 2L)
  2150.     ++hshift;
  2151.   hshift = 8 - hshift;        /* set hash code range bound */
  2152.  
  2153.   hsize_reg = hsize;
  2154.   cl_hash ((count_int) hsize_reg);    /* clear hash table */
  2155.  
  2156.   output ((code_int) ClearCode);
  2157.  
  2158.  
  2159. #ifdef SIGNED_COMPARE_SLOW
  2160.   while ((c = GIFNextPixel (ReadValue)) != (unsigned) EOF)
  2161.     {
  2162. #else /*SIGNED_COMPARE_SLOW */
  2163.   while ((c = GIFNextPixel (ReadValue)) != EOF)
  2164.     {                /* } */
  2165. #endif /*SIGNED_COMPARE_SLOW */
  2166.  
  2167.       ++in_count;
  2168.  
  2169.       fcode = (long) (((long) c << maxbits) + ent);
  2170.       i = (((code_int) c << hshift) ^ ent);    /* xor hashing */
  2171.  
  2172.       if (HashTabOf (i) == fcode)
  2173.     {
  2174.       ent = CodeTabOf (i);
  2175.       continue;
  2176.     }
  2177.       else if ((long) HashTabOf (i) < 0)    /* empty slot */
  2178.     goto nomatch;
  2179.       disp = hsize_reg - i;    /* secondary hash (after G. Knott) */
  2180.       if (i == 0)
  2181.     disp = 1;
  2182.     probe:
  2183.       if ((i -= disp) < 0)
  2184.     i += hsize_reg;
  2185.  
  2186.       if (HashTabOf (i) == fcode)
  2187.     {
  2188.       ent = CodeTabOf (i);
  2189.       continue;
  2190.     }
  2191.       if ((long) HashTabOf (i) > 0)
  2192.     goto probe;
  2193.     nomatch:
  2194.       output ((code_int) ent);
  2195.       ++out_count;
  2196.       ent = c;
  2197. #ifdef SIGNED_COMPARE_SLOW
  2198.       if ((unsigned) free_ent < (unsigned) maxmaxcode)
  2199.     {
  2200. #else /*SIGNED_COMPARE_SLOW */
  2201.       if (free_ent < maxmaxcode)
  2202.     {            /* } */
  2203. #endif /*SIGNED_COMPARE_SLOW */
  2204.       CodeTabOf (i) = free_ent++;    /* code -> hashtable */
  2205.       HashTabOf (i) = fcode;
  2206.     }
  2207.       else
  2208.     cl_block ();
  2209.     }
  2210.   /*
  2211.    * Put out the final code.
  2212.    */
  2213.   output ((code_int) ent);
  2214.   ++out_count;
  2215.   output ((code_int) EOFCode);
  2216. }
  2217.  
  2218. /*****************************************************************
  2219.  * TAG( output )
  2220.  *
  2221.  * Output the given code.
  2222.  * Inputs:
  2223.  *      code:   A n_bits-bit integer.  If == -1, then EOF.  This assumes
  2224.  *              that n_bits =< (long)wordsize - 1.
  2225.  * Outputs:
  2226.  *      Outputs code to the file.
  2227.  * Assumptions:
  2228.  *      Chars are 8 bits long.
  2229.  * Algorithm:
  2230.  *      Maintain a GIF_BITS character long buffer (so that 8 codes will
  2231.  * fit in it exactly).  Use the VAX insv instruction to insert each
  2232.  * code in turn.  When the buffer fills up empty it and start over.
  2233.  */
  2234.  
  2235. static void
  2236. output (code_int code)
  2237. {
  2238.   cur_accum &= masks[cur_bits];
  2239.  
  2240.   if (cur_bits > 0)
  2241.     cur_accum |= ((long) code << cur_bits);
  2242.   else
  2243.     cur_accum = code;
  2244.  
  2245.   cur_bits += n_bits;
  2246.  
  2247.   while (cur_bits >= 8)
  2248.     {
  2249.       char_out ((unsigned int) (cur_accum & 0xff));
  2250.       cur_accum >>= 8;
  2251.       cur_bits -= 8;
  2252.     }
  2253.  
  2254.   /*
  2255.    * If the next entry is going to be too big for the code size,
  2256.    * then increase it, if possible.
  2257.    */
  2258.   if (free_ent > maxcode || clear_flg)
  2259.     {
  2260.  
  2261.       if (clear_flg)
  2262.     {
  2263.  
  2264.       maxcode = MAXCODE (n_bits = g_init_bits);
  2265.       clear_flg = 0;
  2266.  
  2267.     }
  2268.       else
  2269.     {
  2270.  
  2271.       ++n_bits;
  2272.       if (n_bits == maxbits)
  2273.         maxcode = maxmaxcode;
  2274.       else
  2275.         maxcode = MAXCODE (n_bits);
  2276.     }
  2277.     }
  2278.  
  2279.   if (code == EOFCode)
  2280.     {
  2281.       /*
  2282.        * At EOF, write the rest of the buffer.
  2283.        */
  2284.       while (cur_bits > 0)
  2285.     {
  2286.       char_out ((unsigned int) (cur_accum & 0xff));
  2287.       cur_accum >>= 8;
  2288.       cur_bits -= 8;
  2289.     }
  2290.  
  2291.       flush_char ();
  2292.  
  2293.       fflush (g_outfile);
  2294.  
  2295.       if (ferror (g_outfile))
  2296.     writeerr ();
  2297.     }
  2298. }
  2299.  
  2300. /*
  2301.  * Clear out the hash table
  2302.  */
  2303. static void
  2304. cl_block ()            /* table clear for block compress */
  2305. {
  2306.  
  2307.   cl_hash ((count_int) hsize);
  2308.   free_ent = ClearCode + 2;
  2309.   clear_flg = 1;
  2310.  
  2311.   output ((code_int) ClearCode);
  2312. }
  2313.  
  2314. static void
  2315. cl_hash (register count_int hsize)            /* reset code table */
  2316. {
  2317.  
  2318.   register count_int *htab_p = htab + hsize;
  2319.  
  2320.   register long i;
  2321.   register long m1 = -1;
  2322.  
  2323.   i = hsize - 16;
  2324.   do
  2325.     {                /* might use Sys V memset(3) here */
  2326.       *(htab_p - 16) = m1;
  2327.       *(htab_p - 15) = m1;
  2328.       *(htab_p - 14) = m1;
  2329.       *(htab_p - 13) = m1;
  2330.       *(htab_p - 12) = m1;
  2331.       *(htab_p - 11) = m1;
  2332.       *(htab_p - 10) = m1;
  2333.       *(htab_p - 9) = m1;
  2334.       *(htab_p - 8) = m1;
  2335.       *(htab_p - 7) = m1;
  2336.       *(htab_p - 6) = m1;
  2337.       *(htab_p - 5) = m1;
  2338.       *(htab_p - 4) = m1;
  2339.       *(htab_p - 3) = m1;
  2340.       *(htab_p - 2) = m1;
  2341.       *(htab_p - 1) = m1;
  2342.       htab_p -= 16;
  2343.     }
  2344.   while ((i -= 16) >= 0);
  2345.  
  2346.   for (i += 16; i > 0; --i)
  2347.     *--htab_p = m1;
  2348. }
  2349.  
  2350. static void
  2351. writeerr ()
  2352. {
  2353.   g_message (_("GIF: error writing output file\n"));
  2354.   return;
  2355. }
  2356.  
  2357. /******************************************************************************
  2358.  *
  2359.  * GIF Specific routines
  2360.  *
  2361.  ******************************************************************************/
  2362.  
  2363. /*
  2364.  * Number of characters so far in this 'packet'
  2365.  */
  2366. static int a_count;
  2367.  
  2368. /*
  2369.  * Set up the 'byte output' routine
  2370.  */
  2371. static void
  2372. char_init ()
  2373. {
  2374.   a_count = 0;
  2375. }
  2376.  
  2377. /*
  2378.  * Define the storage for the packet accumulator
  2379.  */
  2380. static char accum[256];
  2381.  
  2382. /*
  2383.  * Add a character to the end of the current packet, and if it is 254
  2384.  * characters, flush the packet to disk.
  2385.  */
  2386. static void
  2387. char_out (int c)
  2388. {
  2389.   accum[a_count++] = c;
  2390.   if (a_count >= 254)
  2391.     flush_char ();
  2392. }
  2393.  
  2394. /*
  2395.  * Flush the packet to disk, and reset the accumulator
  2396.  */
  2397. static void
  2398. flush_char (void)
  2399. {
  2400.   if (a_count > 0)
  2401.     {
  2402.       fputc (a_count, g_outfile);
  2403.       fwrite (accum, 1, a_count, g_outfile);
  2404.       a_count = 0;
  2405.     }
  2406. }
  2407.  
  2408.  
  2409. /* crop dialog functions */
  2410.  
  2411. static void
  2412. cropok_callback (GtkWidget *widget,
  2413.          gpointer   data)
  2414. {
  2415.   can_crop = TRUE;
  2416.  
  2417.   gtk_widget_destroy (GTK_WIDGET (data));
  2418. }
  2419.  
  2420. /*  Save interface functions  */
  2421.  
  2422. static void
  2423. save_ok_callback (GtkWidget *widget,
  2424.           gpointer   data)
  2425. {
  2426.   gsint.run = TRUE;
  2427.  
  2428.   gtk_widget_destroy (GTK_WIDGET (data));
  2429. }
  2430.  
  2431. static void
  2432. comment_entry_callback (GtkWidget *widget,
  2433.             gpointer   data)
  2434. {
  2435.   gint ssize;
  2436.   gchar* str;
  2437.  
  2438.   str = gtk_editable_get_chars (GTK_EDITABLE (widget), 0, -1);
  2439.   ssize = strlen (str);
  2440.  
  2441.   /* Temporary kludge for overlength strings - just return */
  2442.   if (ssize > 240)
  2443.     {
  2444.       g_message (_("GIF save: Your comment string is too long.\n"));
  2445.       g_free (str);
  2446.       return;
  2447.     }
  2448.  
  2449.   if (globalcomment != NULL) g_free (globalcomment);
  2450.   globalcomment = g_malloc (ssize + 1);
  2451.  
  2452.   /*strcpy(globalcomment, gtk_entry_get_text (GTK_ENTRY (widget)));*/
  2453.   strcpy (globalcomment, str);
  2454.   g_free (str);
  2455.  
  2456.   comment_was_edited = TRUE;
  2457.  
  2458.   /*g_print ("COMMENT: %s\n",globalcomment);*/
  2459. }
  2460.