377
static GimpParamDef save_args[] =
385
static const GimpParamDef save_args[] =
379
{ GIMP_PDB_INT32, "run_mode", "Interactive, non-interactive" },
387
{ GIMP_PDB_INT32, "run-mode", "Interactive, non-interactive" },
380
388
{ GIMP_PDB_IMAGE, "image", "Image to save" },
381
389
{ GIMP_PDB_DRAWABLE, "drawable", "Drawable to save" },
382
390
{ GIMP_PDB_STRING, "filename", "The name of the file to save the image in" },
383
{ GIMP_PDB_STRING, "raw_filename", "The name entered" },
391
{ GIMP_PDB_STRING, "raw-filename", "The name entered" },
384
392
{ GIMP_PDB_INT32, "interlace", "Try to save as interlaced" },
385
393
{ 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)" }
394
{ GIMP_PDB_INT32, "default-delay", "(animated gif) Default delay between framese in milliseconds" },
395
{ GIMP_PDB_INT32, "default-dispose", "(animated gif) Default disposal type (0=`don't care`, 1=combine, 2=replace)" }
390
gimp_install_procedure ("file_gif_save",
398
gimp_install_procedure (SAVE_PROC,
391
399
"saves files in Compuserve GIF file format",
392
400
"Save a file in Compuserve GIF format, with "
393
"possible animation, transparency, and comment. "
394
"To save an animation, operate on a multi-layer "
395
"file. The plug-in will intrepret <50% alpha as "
396
"transparent. When run non-interactively, the "
397
"value for the comment is taken from the "
398
"'gimp-comment' parasite. ",
401
"possible animation, transparency, and comment. "
402
"To save an animation, operate on a multi-layer "
403
"file. The plug-in will intrepret <50% alpha as "
404
"transparent. When run non-interactively, the "
405
"value for the comment is taken from the "
406
"'gimp-comment' parasite. ",
399
407
"Spencer Kimball, Peter Mattis, Adam Moss, David Koblas",
400
408
"Spencer Kimball, Peter Mattis, Adam Moss, David Koblas",
405
413
G_N_ELEMENTS (save_args), 0,
406
414
save_args, NULL);
408
gimp_register_file_handler_mime ("file_gif_save", "image/gif");
409
gimp_register_save_handler ("file_gif_save", "gif", "");
416
gimp_register_file_handler_mime (SAVE_PROC, "image/gif");
417
gimp_register_save_handler (SAVE_PROC, "gif", "");
432
440
values[0].type = GIMP_PDB_STATUS;
433
441
values[0].data.d_status = GIMP_PDB_EXECUTION_ERROR;
435
if (strcmp (name, "file_gif_save") == 0)
443
if (strcmp (name, SAVE_PROC) == 0)
437
445
image_ID = orig_image_ID = param[1].data.d_int32;
438
446
drawable_ID = param[2].data.d_int32;
440
448
/* eventually export the image */
441
449
switch (run_mode)
443
case GIMP_RUN_INTERACTIVE:
444
case GIMP_RUN_WITH_LAST_VALS:
445
gimp_ui_init ("gif", FALSE);
446
export = gimp_export_image (&image_ID, &drawable_ID, "GIF",
447
(GIMP_EXPORT_CAN_HANDLE_INDEXED |
448
GIMP_EXPORT_CAN_HANDLE_GRAY |
449
GIMP_EXPORT_CAN_HANDLE_ALPHA |
450
GIMP_EXPORT_CAN_HANDLE_LAYERS_AS_ANIMATION));
451
if (export == GIMP_EXPORT_CANCEL)
453
values[0].data.d_status = GIMP_PDB_CANCEL;
461
if (boundscheck (image_ID))
462
/* The image may or may not have had layers out of
463
bounds, but the user didn't mind cropping it down. */
467
case GIMP_RUN_INTERACTIVE:
468
/* Possibly retrieve data */
469
gimp_get_data ("file_gif_save", &gsvals);
471
/* First acquire information with a dialog */
472
if (! save_dialog (image_ID))
473
status = GIMP_PDB_CANCEL;
476
case GIMP_RUN_NONINTERACTIVE:
477
/* Make sure all the arguments are there! */
480
status = GIMP_PDB_CALLING_ERROR;
484
gsvals.interlace = (param[5].data.d_int32) ? TRUE : FALSE;
485
gsvals.save_comment = TRUE; /* no way to to specify that through the PDB */
486
gsvals.loop = (param[6].data.d_int32) ? TRUE : FALSE;
487
gsvals.default_delay = param[7].data.d_int32;
488
gsvals.default_dispose = param[8].data.d_int32;
492
case GIMP_RUN_WITH_LAST_VALS:
493
/* Possibly retrieve data */
494
gimp_get_data ("file_gif_save", &gsvals);
501
if (status == GIMP_PDB_SUCCESS)
503
if (save_image (param[3].data.d_string,
508
/* Store psvals data */
509
gimp_set_data ("file_gif_save",
510
&gsvals, sizeof (GIFSaveVals));
514
status = GIMP_PDB_EXECUTION_ERROR;
518
else /* Some layers were out of bounds and the user wishes
521
status = GIMP_PDB_CANCEL;
451
case GIMP_RUN_INTERACTIVE:
452
case GIMP_RUN_WITH_LAST_VALS:
453
gimp_ui_init (PLUG_IN_BINARY, FALSE);
454
export = gimp_export_image (&image_ID, &drawable_ID, "GIF",
455
(GIMP_EXPORT_CAN_HANDLE_INDEXED |
456
GIMP_EXPORT_CAN_HANDLE_GRAY |
457
GIMP_EXPORT_CAN_HANDLE_ALPHA |
458
GIMP_EXPORT_CAN_HANDLE_LAYERS_AS_ANIMATION));
459
if (export == GIMP_EXPORT_CANCEL)
461
values[0].data.d_status = GIMP_PDB_CANCEL;
469
if (bounds_check (image_ID))
470
/* The image may or may not have had layers out of
471
bounds, but the user didn't mind cropping it down. */
475
case GIMP_RUN_INTERACTIVE:
476
/* Possibly retrieve data */
477
gimp_get_data (SAVE_PROC, &gsvals);
479
/* First acquire information with a dialog */
480
if (! save_dialog (image_ID))
481
status = GIMP_PDB_CANCEL;
484
case GIMP_RUN_NONINTERACTIVE:
485
/* Make sure all the arguments are there! */
488
status = GIMP_PDB_CALLING_ERROR;
492
gsvals.interlace = (param[5].data.d_int32) ? TRUE : FALSE;
493
gsvals.save_comment = TRUE; /* no way to to specify that through the PDB */
494
gsvals.loop = (param[6].data.d_int32) ? TRUE : FALSE;
495
gsvals.default_delay = param[7].data.d_int32;
496
gsvals.default_dispose = param[8].data.d_int32;
500
case GIMP_RUN_WITH_LAST_VALS:
501
/* Possibly retrieve data */
502
gimp_get_data (SAVE_PROC, &gsvals);
509
if (status == GIMP_PDB_SUCCESS)
511
if (save_image (param[3].data.d_string,
516
/* Store psvals data */
517
gimp_set_data (SAVE_PROC, &gsvals, sizeof (GIFSaveVals));
521
status = GIMP_PDB_EXECUTION_ERROR;
526
/* Some layers were out of bounds and the user wishes
529
status = GIMP_PDB_CANCEL;
524
532
if (export == GIMP_EXPORT_EXPORT)
525
gimp_image_delete (image_ID);
533
gimp_image_delete (image_ID);
528
536
values[0].data.d_status = status;
531
#define MAXCOLORMAPSIZE 256
533
#define INTERLACE 0x40
534
#define LOCALCOLORMAP 0x80
539
typedef guchar CMap[3][MAXCOLORMAPSIZE];
542
539
static gchar * globalcomment = NULL;
589
static gint find_unused_ia_colour (guchar *pixels,
586
static gint find_unused_ia_colour (const guchar *pixels,
594
591
static void special_flatten_indexed_alpha (guchar *pixels,
598
static int colorstobpp (int);
599
static int bpptocolors (int);
600
static int GetPixel (int, int);
601
static void BumpPixel (void);
602
static int GIFNextPixel (ifunptr);
604
static void GIFEncodeHeader (FILE *, gboolean, int, int, int, int,
605
int *, int *, int *, ifunptr);
606
static void GIFEncodeGraphicControlExt (FILE *, int, int, int, int,
607
int, int, int, ifunptr);
608
static void GIFEncodeImageData (FILE *, int, int, int, int,
609
ifunptr, gint, gint);
610
static void GIFEncodeClose (FILE *);
611
static void GIFEncodeLoopExt (FILE *, guint);
612
static void GIFEncodeCommentExt (FILE *, const gchar *comment);
619
static void Putword (int, FILE *);
620
static void compress (int, FILE *, ifunptr);
594
static int colors_to_bpp (int);
595
static int bpp_to_colors (int);
596
static int get_pixel (int, int);
597
static int gif_next_pixel (ifunptr);
598
static void bump_pixel (void);
600
static void gif_encode_header (FILE *, gboolean, int, int, int, int,
601
int *, int *, int *, ifunptr);
602
static void gif_encode_graphic_control_ext (FILE *, int, int, int, int,
603
int, int, int, ifunptr);
604
static void gif_encode_image_data (FILE *, int, int, int, int,
605
ifunptr, gint, gint);
606
static void gif_encode_close (FILE *);
607
static void gif_encode_loop_ext (FILE *, guint);
608
static void gif_encode_comment_ext (FILE *, const gchar *comment);
610
static gint rowstride;
611
static guchar *pixels;
612
static gint cur_progress;
613
static gint max_progress;
622
static void nocompress (int, FILE *, ifunptr);
616
static void no_compress (int, FILE *, ifunptr);
625
static void rlecompress (int, FILE *, ifunptr);
619
static void rle_compress (int, FILE *, ifunptr);
627
static void normalcompress (int, FILE *, ifunptr);
630
static void output (code_int);
631
static void cl_block (void);
632
static void cl_hash (count_int);
633
static void writeerr (void);
634
static void char_init (void);
635
static void char_out (int);
621
static void normal_compress (int, FILE *, ifunptr);
624
static void put_word (int, FILE *);
625
static void compress (int, FILE *, ifunptr);
626
static void output (code_int);
627
static void cl_block (void);
628
static void cl_hash (count_int);
629
static void write_err (void);
630
static void char_init (void);
631
static void char_out (int);
636
632
static void flush_char (void);
641
find_unused_ia_colour (guchar *pixels,
637
find_unused_ia_colour (const guchar *pixels,
647
642
gboolean ix_used[256];
650
646
g_printerr ("GIF: fuiac: Image claims to use %d/%d indices - finding free "
651
"index...\n", (int)(*colors),(int)num_indices);
647
"index...\n", *colors, num_indices);
654
for (i=0; i<256; i++)
656
ix_used[i] = (gboolean)FALSE;
659
for (i=0; i<numpixels; i++)
661
if (pixels[i*2+1]) ix_used[pixels[i*2]] = (gboolean) TRUE;
664
for (i=num_indices-1; i>=0; i--)
666
if (ix_used[i] == (gboolean)FALSE)
650
for (i = 0; i < 256; i++)
653
for (i = 0; i < numpixels; i++)
655
if (pixels[i * 2 + 1])
656
ix_used[pixels[i * 2]] = TRUE;
659
for (i = num_indices - 1; i >= 0; i--)
669
g_printerr ("GIF: Found unused colour index %d.\n", (int) i);
664
g_printerr ("GIF: Found unused colour index %d.\n", (int) i);
675
670
/* Couldn't find an unused colour index within the number of
676
671
bits per pixel we wanted. Will have to increment the number
677
672
of colours in the image and assign a transparent pixel there. */
681
677
g_printerr ("GIF: 2nd pass "
682
678
"- Increasing bounds and using colour index %d.\n",
684
return ((*colors)-1);
680
return ((*colors) - 1);
687
683
g_message (_("Couldn't simply reduce colors further. Saving as opaque."));
693
690
special_flatten_indexed_alpha (guchar *pixels,
700
696
/* Each transparent pixel in the image is mapped to a uniform value for
701
697
encoding, if image already has <=255 colours */
703
if ((*transparent) == -1) /* tough, no indices left for the trans. index */
699
if (transparent == -1) /* tough, no indices left for the trans. index */
705
for (i=0; i<numpixels; i++)
706
pixels[i] = pixels[i*2];
701
for (i = 0; i < numpixels; i++)
702
pixels[i] = pixels[i * 2];
708
704
else /* make transparent */
710
for (i=0; i<numpixels; i++)
712
if (!(pixels[i*2+1] & 128))
714
pixels[i] = (guchar)(*transparent);
718
pixels[i] = pixels[i*2];
706
for (i = 0; i < numpixels; i++)
708
if (! (pixels[i * 2 + 1] & 128))
710
pixels[i] = (guchar) transparent;
714
pixels[i] = pixels[i * 2];
724
/* Pixel data now takes half as much space (the alpha data has been
726
/* pixels = g_realloc (pixels, numpixels);*/
731
parse_ms_tag (char *str)
722
parse_ms_tag (const gchar *str)
808
799
drawable = gimp_drawable_get (layers[i]);
809
800
gimp_drawable_offsets (layers[i], &offset_x, &offset_y);
811
if ((offset_x < 0) ||
813
(offset_x+drawable->width > gimp_image_width(image_ID)) ||
814
(offset_y+drawable->height > gimp_image_height(image_ID)))
817
gimp_drawable_detach(drawable);
819
/* Image has illegal bounds - ask the user what it wants to do */
821
/* Do the crop if we can't talk to the user, or if we asked
822
* the user and they said yes. */
823
if ((run_mode == GIMP_RUN_NONINTERACTIVE) || badbounds_dialog ())
825
gimp_image_crop (image_ID,
826
gimp_image_width (image_ID),
827
gimp_image_height (image_ID),
804
|| (offset_x+drawable->width > gimp_image_width(image_ID))
805
|| (offset_y+drawable->height > gimp_image_height(image_ID)))
808
gimp_drawable_detach (drawable);
810
/* Image has illegal bounds - ask the user what it wants to do */
812
/* Do the crop if we can't talk to the user, or if we asked
813
* the user and they said yes. */
814
if ((run_mode == GIMP_RUN_NONINTERACTIVE) || bad_bounds_dialog ())
816
gimp_image_crop (image_ID,
817
gimp_image_width (image_ID),
818
gimp_image_height (image_ID),
838
gimp_drawable_detach (drawable);
829
gimp_drawable_detach (drawable);
1009
999
if (colors < 256)
1011
1001
/* we keep track of how many bits we promised to have in liberalBPP,
1012
so that we don't accidentally come under this when doing
1013
clever transparency stuff where we can re-use wasted indices. */
1002
so that we don't accidentally come under this when doing
1003
clever transparency stuff where we can re-use wasted indices. */
1014
1004
liberalBPP = BitsPerPixel =
1015
colorstobpp (colors + ((drawable_type==GIMP_INDEXEDA_IMAGE) ? 1 : 0));
1005
colors_to_bpp (colors + ((drawable_type==GIMP_INDEXEDA_IMAGE) ? 1 : 0));
1019
1009
liberalBPP = BitsPerPixel =
1010
colors_to_bpp (256);
1022
if (drawable_type==GIMP_INDEXEDA_IMAGE)
1024
g_printerr ("GIF: Too many colours?\n");
1012
if (drawable_type == GIMP_INDEXEDA_IMAGE)
1014
g_printerr ("GIF: Too many colours?\n");
1028
1018
cols = gimp_image_width (image_ID);
1029
1019
rows = gimp_image_height (image_ID);
1030
1020
Interlace = gsvals.interlace;
1031
GIFEncodeHeader (outfile, is_gif89, cols, rows, bgindex,
1032
BitsPerPixel, Red, Green, Blue, GetPixel);
1021
gif_encode_header (outfile, is_gif89, cols, rows, bgindex,
1022
BitsPerPixel, Red, Green, Blue, get_pixel);
1035
1025
/* If the image has multiple layers it'll be made into an
1036
1026
animated GIF, so write out the infinite-looping extension */
1037
1027
if ((nlayers > 1) && (gsvals.loop))
1038
GIFEncodeLoopExt (outfile, 0);
1028
gif_encode_loop_ext (outfile, 0);
1040
1030
/* Write comment extension - mustn't be written before the looping ext. */
1041
1031
if (gsvals.save_comment && globalcomment)
1043
GIFEncodeCommentExt (outfile, globalcomment);
1033
gif_encode_comment_ext (outfile, globalcomment);
1048
1037
/*** Now for each layer in the image, save an image in a compound GIF ***/
1049
1038
/************************************************************************/
1041
max_progress = nlayers * rows;
1043
for (i = nlayers - 1; i >= 0; i--, cur_progress = (nlayers - i) * rows)
1055
1045
drawable_type = gimp_drawable_type (layers[i]);
1056
1046
drawable = gimp_drawable_get (layers[i]);
1060
1050
rowstride = drawable->width;
1062
1052
gimp_pixel_rgn_init (&pixel_rgn, drawable, 0, 0,
1063
drawable->width, drawable->height, FALSE, FALSE);
1066
max_progress = drawable->height;
1068
pixels = (guchar *) g_malloc (drawable->width *
1070
(((drawable_type == GIMP_INDEXEDA_IMAGE)||
1071
(drawable_type == GIMP_GRAYA_IMAGE)) ? 2:1) );
1053
drawable->width, drawable->height, FALSE, FALSE);
1055
pixels = g_new (guchar, (drawable->width * drawable->height
1056
* (((drawable_type == GIMP_INDEXEDA_IMAGE)
1057
|| (drawable_type == GIMP_GRAYA_IMAGE)) ? 2 : 1)));
1073
1059
gimp_pixel_rgn_get_rect (&pixel_rgn, pixels, 0, 0,
1074
drawable->width, drawable->height);
1060
drawable->width, drawable->height);
1077
1063
/* sort out whether we need to do transparency jiggery-pokery */
1078
if ((drawable_type == GIMP_INDEXEDA_IMAGE)||(drawable_type == GIMP_GRAYA_IMAGE))
1080
/* Try to find an entry which isn't actually used in the
1081
image, for a transparency index. */
1084
find_unused_ia_colour(pixels,
1085
drawable->width * drawable->height,
1086
bpptocolors(colorstobpp(colors)),
1089
special_flatten_indexed_alpha (pixels,
1092
drawable->width * drawable->height);
1064
if ((drawable_type == GIMP_INDEXEDA_IMAGE)
1065
|| (drawable_type == GIMP_GRAYA_IMAGE))
1067
/* Try to find an entry which isn't actually used in the
1068
image, for a transparency index. */
1071
find_unused_ia_colour (pixels,
1072
drawable->width * drawable->height,
1073
bpp_to_colors (colors_to_bpp (colors)),
1076
special_flatten_indexed_alpha (pixels,
1078
drawable->width * drawable->height);
1098
BitsPerPixel = colorstobpp (colors);
1085
BitsPerPixel = colors_to_bpp (colors);
1100
1087
if (BitsPerPixel != liberalBPP)
1102
/* We were able to re-use an index within the existing bitspace,
1103
whereas the estimate in the header was pessimistic but still
1104
needs to be upheld... */
1105
static gboolean onceonly = FALSE;
1089
/* We were able to re-use an index within the existing bitspace,
1090
whereas the estimate in the header was pessimistic but still
1091
needs to be upheld... */
1093
static gboolean onceonly = FALSE;
1110
g_warning ("Promised %d bpp, pondered writing chunk with %d bpp!",
1097
g_warning ("Promised %d bpp, pondered writing chunk with %d bpp!",
1111
1098
liberalBPP, BitsPerPixel);
1113
g_message (_("Warning:\n"
1114
"Transparent color in written file might be "
1115
"incorrect on viewers which don't support "
1117
1099
onceonly = TRUE;
1120
1104
useBPP = (BitsPerPixel > liberalBPP) ? BitsPerPixel : liberalBPP;
1127
layer_name = gimp_drawable_get_name (layers[i - 1]);
1128
Disposal = parse_disposal_tag (layer_name);
1129
g_free (layer_name);
1132
Disposal = gsvals.default_dispose;
1134
layer_name = gimp_drawable_get_name (layers[i]);
1135
Delay89 = parse_ms_tag (layer_name);
1136
g_free (layer_name);
1139
Delay89 = (gsvals.default_delay + 5) / 10;
1141
Delay89 = (Delay89 + 5) / 10;
1143
/* don't allow a CPU-sucking completely 0-delay looping anim */
1144
if ((nlayers > 1) &&
1148
static gboolean onceonly = FALSE;
1152
g_message (_("Delay inserted to prevent evil "
1153
"CPU-sucking anim."));
1159
GIFEncodeGraphicControlExt (outfile, Disposal, Delay89, nlayers,
1166
GIFEncodeImageData (outfile, cols, rows,
1167
(rows>4) ? gsvals.interlace : 0,
1170
offset_x, offset_y);
1172
gimp_drawable_detach (drawable);
1108
if (i > 0 && ! gsvals.always_use_default_dispose)
1110
layer_name = gimp_drawable_get_name (layers[i - 1]);
1111
Disposal = parse_disposal_tag (layer_name);
1112
g_free (layer_name);
1116
Disposal = gsvals.default_dispose;
1119
layer_name = gimp_drawable_get_name (layers[i]);
1120
Delay89 = parse_ms_tag (layer_name);
1121
g_free (layer_name);
1123
if (Delay89 < 0 || gsvals.always_use_default_delay)
1124
Delay89 = (gsvals.default_delay + 5) / 10;
1126
Delay89 = (Delay89 + 5) / 10;
1128
/* don't allow a CPU-sucking completely 0-delay looping anim */
1129
if ((nlayers > 1) && gsvals.loop && (Delay89 == 0))
1131
static gboolean onceonly = FALSE;
1135
g_message (_("Delay inserted to prevent evil "
1136
"CPU-sucking animation."));
1142
gif_encode_graphic_control_ext (outfile, Disposal, Delay89, nlayers,
1149
gif_encode_image_data (outfile, cols, rows,
1150
(rows > 4) ? gsvals.interlace : 0,
1153
offset_x, offset_y);
1155
gimp_drawable_detach (drawable);
1179
1160
g_free(layers);
1181
GIFEncodeClose (outfile);
1162
gif_encode_close (outfile);
1186
1167
static gboolean
1187
badbounds_dialog (void)
1168
bad_bounds_dialog (void)
1194
dlg = gimp_dialog_new (_("GIF Warning"), "gif_warning",
1196
gimp_standard_help_func, "file-gif-save",
1198
GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL,
1199
GTK_STOCK_OK, GTK_RESPONSE_OK,
1203
/* the warning message */
1205
vbox = gtk_vbox_new (FALSE, 12);
1206
gtk_container_set_border_width (GTK_CONTAINER (vbox), 12);
1207
gtk_box_pack_start (GTK_BOX (GTK_DIALOG (dlg)->vbox), vbox, TRUE, TRUE, 0);
1208
gtk_widget_show (vbox);
1210
label= gtk_label_new (_("The image which you are trying to save as a GIF\n"
1211
"contains layers which extend beyond the actual\n"
1212
"borders of the image. This isn't allowed in GIFs,\n"
1214
"You may choose whether to crop all of the layers to\n"
1215
"the image borders, or cancel this save."));
1216
gtk_box_pack_start (GTK_BOX (vbox), label, TRUE, TRUE, 0);
1217
gtk_widget_show (label);
1219
gtk_widget_show (dlg);
1221
crop = (gimp_dialog_run (GIMP_DIALOG (dlg)) == GTK_RESPONSE_OK);
1223
gtk_widget_destroy (dlg);
1173
dialog = gtk_message_dialog_new (NULL, 0,
1174
GTK_MESSAGE_WARNING, GTK_BUTTONS_NONE,
1175
_("The image you are trying to save as a "
1176
"GIF contains layers which extend beyond "
1177
"the actual borders of the image."));
1179
gtk_dialog_add_buttons (GTK_DIALOG (dialog),
1180
GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL,
1181
GIMP_STOCK_TOOL_CROP, GTK_RESPONSE_OK,
1184
gtk_dialog_set_alternative_button_order (GTK_DIALOG (dialog),
1186
GTK_RESPONSE_CANCEL,
1189
gimp_window_set_transient (GTK_WINDOW (dialog));
1191
gtk_message_dialog_format_secondary_text (GTK_MESSAGE_DIALOG (dialog),
1192
_("The GIF file format does not "
1193
"allow this. You may choose "
1194
"whether to crop all of the "
1195
"layers to the image borders, "
1196
"or cancel this save."));
1198
gtk_widget_show (dialog);
1200
crop = (gtk_dialog_run (GTK_DIALOG (dialog)) == GTK_RESPONSE_OK);
1202
gtk_widget_destroy (dialog);
1364
1350
hbox = gtk_hbox_new (FALSE, 6);
1365
1351
gtk_box_pack_start (GTK_BOX (vbox), hbox, FALSE, FALSE, 0);
1367
label = gtk_label_new (_("_Delay between frames where unspecified:"));
1353
label = gtk_label_new_with_mnemonic (_("_Delay between frames where unspecified:"));
1368
1354
gtk_box_pack_start (GTK_BOX (hbox), label, FALSE, FALSE, 0);
1369
1355
gtk_widget_show (label);
1371
1357
spinbutton = gimp_spin_button_new (&adj, gsvals.default_delay,
1372
0, 65000, 10, 100, 0, 1, 0);
1358
0, 65000, 10, 100, 0, 1, 0);
1373
1359
gtk_box_pack_start (GTK_BOX (hbox), spinbutton, FALSE, FALSE, 0);
1374
1360
gtk_widget_show (spinbutton);
1376
g_signal_connect (adj, "value_changed",
1362
gtk_label_set_mnemonic_widget (GTK_LABEL (label), spinbutton);
1364
g_signal_connect (adj, "value-changed",
1377
1365
G_CALLBACK (gimp_int_adjustment_update),
1378
1366
&gsvals.default_delay);
2107
2061
static int cur_bits;
2109
2063
static unsigned long masks[] =
2110
{0x0000, 0x0001, 0x0003, 0x0007, 0x000F,
2111
0x001F, 0x003F, 0x007F, 0x00FF,
2112
0x01FF, 0x03FF, 0x07FF, 0x0FFF,
2113
0x1FFF, 0x3FFF, 0x7FFF, 0xFFFF};
2064
{0x0000, 0x0001, 0x0003, 0x0007,
2065
0x000F, 0x001F, 0x003F, 0x007F,
2066
0x00FF, 0x01FF, 0x03FF, 0x07FF,
2067
0x0FFF, 0x1FFF, 0x3FFF, 0x7FFF,
2117
2072
compress (int init_bits,
2122
nocompress(init_bits, outfile, ReadValue);
2077
no_compress(init_bits, outfile, ReadValue);
2125
rlecompress(init_bits, outfile, ReadValue);
2080
rle_compress(init_bits, outfile, ReadValue);
2127
normalcompress(init_bits, outfile, ReadValue);
2082
normal_compress(init_bits, outfile, ReadValue);
2134
nocompress (int init_bits,
2089
no_compress (int init_bits,
2138
2093
register long fcode;
2139
2094
register code_int i /* = 0 */ ;
2399
ent = GIFNextPixel (ReadValue);
2354
ent = gif_next_pixel (ReadValue);
2402
2357
for (fcode = (long) hsize; fcode < 65536L; fcode *= 2L)
2404
hshift = 8 - hshift; /* set hash code range bound */
2359
hshift = 8 - hshift; /* set hash code range bound */
2406
2361
hsize_reg = hsize;
2407
cl_hash ((count_int) hsize_reg); /* clear hash table */
2362
cl_hash ((count_int) hsize_reg); /* clear hash table */
2409
2364
output ((code_int) ClearCode);
2413
2368
#ifdef SIGNED_COMPARE_SLOW
2414
while ((c = GIFNextPixel (ReadValue)) != (unsigned) EOF)
2369
while ((c = gif_next_pixel (ReadValue)) != (unsigned) EOF)
2416
2371
#else /*SIGNED_COMPARE_SLOW */
2417
while ((c = GIFNextPixel (ReadValue)) != EOF)
2372
while ((c = gif_next_pixel (ReadValue)) != EOF)
2419
2374
#endif /*SIGNED_COMPARE_SLOW */
2423
2378
fcode = (long) (((long) c << maxbits) + ent);
2424
i = (((code_int) c << hshift) ^ ent); /* xor hashing */
2379
i = (((code_int) c << hshift) ^ ent); /* xor hashing */
2426
2381
if (HashTabOf (i) == fcode)
2428
ent = CodeTabOf (i);
2431
else if ((long) HashTabOf (i) < 0) /* empty slot */
2433
disp = hsize_reg - i; /* secondary hash (after G. Knott) */
2383
ent = CodeTabOf (i);
2386
else if ((long) HashTabOf (i) < 0) /* empty slot */
2388
disp = hsize_reg - i; /* secondary hash (after G. Knott) */
2437
2392
if ((i -= disp) < 0)
2440
2395
if (HashTabOf (i) == fcode)
2442
ent = CodeTabOf (i);
2397
ent = CodeTabOf (i);
2445
2400
if ((long) HashTabOf (i) > 0)
2448
2403
output ((code_int) ent);
2451
2406
#ifdef SIGNED_COMPARE_SLOW
2452
2407
if ((unsigned) free_ent < (unsigned) maxmaxcode)
2454
2409
#else /*SIGNED_COMPARE_SLOW */
2455
2410
if (free_ent < maxmaxcode)
2457
2412
#endif /*SIGNED_COMPARE_SLOW */
2458
CodeTabOf (i) = free_ent++; /* code -> hashtable */
2459
HashTabOf (i) = fcode;
2413
CodeTabOf (i) = free_ent++; /* code -> hashtable */
2414
HashTabOf (i) = fcode;