Codebase list gifsicle / b09f890
Imported Upstream version 1.77 Francois Marier 10 years ago
21 changed file(s) with 1502 addition(s) and 362 deletion(s). Raw diff Collapse all Expand all
268268 SHELL = @SHELL@
269269 STRIP = @STRIP@
270270 VERSION = @VERSION@
271 WERROR = @WERROR@
271272 XMKMF = @XMKMF@
272273 X_CFLAGS = @X_CFLAGS@
273274 X_EXTRA_LIBS = @X_EXTRA_LIBS@
00 Gifsicle NEWS
1
2 Version 1.77
3
4 * Major improvements to color selection (important when reducing
5 colormap size). Use gamma-corrected colors in selection and
6 dithering; this makes image quality much better. Also, when reducing
7 colors with dithering, prefer to select colors that dithering can't
8 approximate.
9
10 * Add ordered dithering modes, which avoid animation artifacts. The
11 default ordered dithering mode (`--dither=ordered`) is a novel mode
12 that combines some of the visual advantages of error diffusion with
13 the artifact avoidance of ordered dithering.
14
15 * Add halftone dithering (`--dither=halftone`).
16
17 * gifview: Improved cache memory management for better animations.
18 Collect memory for old frames based on an explicit --memory-limit
19 (default 40MB).
20
21 * gifview: Add `--fallback-delay` option, to specify a fallback delay
22 for frames with delay 0. Thanks to Sung Pae.
23
124
225 Version 1.76 20.Nov.2013
326
3131 Building Gifsicle on UNIX
3232 -------------------------
3333
34 Just type `./configure`, then `make`. `make install` will build and
35 install Gifsicle and its manual page (under /usr/local by default). If
36 you have checked out Gifsicle from source, run `autoreconf -i` first.
34 Type `./configure`, then `make`.
3735
38 `./configure` accepts the usual options. See `INSTALL` for more
39 details.
36 If `./configure` does not exist (you downloaded from Github), run
37 `autoreconf -i` first.
4038
41 To build without gifview (for example, if you don't have X11), give
42 the `--disable-gifview` option. To build without gifdiff, give the
43 `--disable-gifdiff` option.
39 `./configure` accepts the usual options; see `INSTALL` for more
40 details. To build without gifview (for example, if you don't have
41 X11), use `./configure --disable-gifview`. To build without gifdiff,
42 use `./configure --disable-gifdiff`.
43
44 `make install` will build and install Gifsicle and its manual page
45 (under /usr/local by default).
4446
4547
4648 Building Gifsicle on Windows
1919
2020 /* Define to 1 if you have the `mkstemp' function. */
2121 #undef HAVE_MKSTEMP
22
23 /* Define to 1 if you have the `pow' function. */
24 #undef HAVE_POW
2225
2326 /* Define to 1 if you have the <stdint.h> header file. */
2427 #undef HAVE_STDINT_H
00 #! /bin/sh
11 # Guess values for system-dependent variables and create Makefiles.
2 # Generated by GNU Autoconf 2.69 for gifsicle 1.76.
2 # Generated by GNU Autoconf 2.69 for gifsicle 1.77.
33 #
44 #
55 # Copyright (C) 1992-1996, 1998-2012 Free Software Foundation, Inc.
576576 # Identity of this package.
577577 PACKAGE_NAME='gifsicle'
578578 PACKAGE_TARNAME='gifsicle'
579 PACKAGE_VERSION='1.76'
580 PACKAGE_STRING='gifsicle 1.76'
579 PACKAGE_VERSION='1.77'
580 PACKAGE_STRING='gifsicle 1.77'
581581 PACKAGE_BUGREPORT=''
582582 PACKAGE_URL=''
583583
633633 X_PRE_LIBS
634634 X_CFLAGS
635635 XMKMF
636 WERROR
636637 CPP
637638 am__fastdepCC_FALSE
638639 am__fastdepCC_TRUE
725726 enable_gifdiff
726727 enable_dmalloc
727728 enable_warnings
729 enable_werror
728730 enable_all
729731 enable_ungif
730732 with_x
12791281 # Omit some internal or obsolete options to make the list less imposing.
12801282 # This message is too long to be a string in the A/UX 3.1 sh.
12811283 cat <<_ACEOF
1282 \`configure' configures gifsicle 1.76 to adapt to many kinds of systems.
1284 \`configure' configures gifsicle 1.77 to adapt to many kinds of systems.
12831285
12841286 Usage: $0 [OPTION]... [VAR=VALUE]...
12851287
13491351
13501352 if test -n "$ac_init_help"; then
13511353 case $ac_init_help in
1352 short | recursive ) echo "Configuration of gifsicle 1.76:";;
1354 short | recursive ) echo "Configuration of gifsicle 1.77:";;
13531355 esac
13541356 cat <<\_ACEOF
13551357
13661368 --disable-gifview do not build gifview, a GIF viewer for X11
13671369 --disable-gifdiff do not build gifdiff, a utility for comparing GIFs
13681370 --enable-dmalloc build with debugging malloc library
1369 --enable-warnings compile with -Wall
1371 --enable-warnings compile with -W -Wall
1372 --enable-werror compile with -Werror
13701373 --enable-all --enable-gifview --enable-gifdiff --enable-warnings
13711374 --enable-ungif build without compression
13721375
14521455 test -n "$ac_init_help" && exit $ac_status
14531456 if $ac_init_version; then
14541457 cat <<\_ACEOF
1455 gifsicle configure 1.76
1458 gifsicle configure 1.77
14561459 generated by GNU Autoconf 2.69
14571460
14581461 Copyright (C) 2012 Free Software Foundation, Inc.
20542057 This file contains any messages produced by compilers while
20552058 running configure, to aid debugging if configure makes a mistake.
20562059
2057 It was created by gifsicle $as_me 1.76, which was
2060 It was created by gifsicle $as_me 1.77, which was
20582061 generated by GNU Autoconf 2.69. Invocation command line was
20592062
20602063 $ $0 $@
29202923
29212924 # Define the identity of the package.
29222925 PACKAGE='gifsicle'
2923 VERSION='1.76'
2926 VERSION='1.77'
29242927
29252928
29262929 cat >>confdefs.h <<_ACEOF
43804383 fi
43814384
43824385
4386 # Check whether --enable-werror was given.
4387 if test "${enable_werror+set}" = set; then :
4388 enableval=$enable_werror; if test "x$enableval" = xyes ; then
4389 WERROR="-Werror"
4390 fi
4391 fi
4392
4393
4394
43834395 # Check whether --enable-all was given.
43844396 if test "${enable_all+set}" = set; then :
43854397 enableval=$enable_all; if test "x$enableval" = xyes ; then
43864398 build_gifview=yes
43874399 build_gifdiff=yes
4388 CC="$CC -Wall"
4400 CC="$CC -W -Wall"
43894401 fi
43904402 fi
43914403
51825194 fi
51835195
51845196
5197
51855198 if test "x$ungif" = xyes -o "x$GIFSICLE_UNGIF" = xyes ; then
51865199 GIFWRITE_O=ungifwrt.o
51875200
52355248
52365249 fi
52375250 done
5251
5252 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for library containing pow" >&5
5253 $as_echo_n "checking for library containing pow... " >&6; }
5254 if ${ac_cv_search_pow+:} false; then :
5255 $as_echo_n "(cached) " >&6
5256 else
5257 ac_func_search_save_LIBS=$LIBS
5258 cat confdefs.h - <<_ACEOF >conftest.$ac_ext
5259 /* end confdefs.h. */
5260
5261 /* Override any GCC internal prototype to avoid an error.
5262 Use char because int might match the return type of a GCC
5263 builtin and then its argument prototype would still apply. */
5264 #ifdef __cplusplus
5265 extern "C"
5266 #endif
5267 char pow ();
5268 int
5269 main ()
5270 {
5271 return pow ();
5272 ;
5273 return 0;
5274 }
5275 _ACEOF
5276 for ac_lib in '' m; do
5277 if test -z "$ac_lib"; then
5278 ac_res="none required"
5279 else
5280 ac_res=-l$ac_lib
5281 LIBS="-l$ac_lib $ac_func_search_save_LIBS"
5282 fi
5283 if ac_fn_c_try_link "$LINENO"; then :
5284 ac_cv_search_pow=$ac_res
5285 fi
5286 rm -f core conftest.err conftest.$ac_objext \
5287 conftest$ac_exeext
5288 if ${ac_cv_search_pow+:} false; then :
5289 break
5290 fi
5291 done
5292 if ${ac_cv_search_pow+:} false; then :
5293
5294 else
5295 ac_cv_search_pow=no
5296 fi
5297 rm conftest.$ac_ext
5298 LIBS=$ac_func_search_save_LIBS
5299 fi
5300 { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_search_pow" >&5
5301 $as_echo "$ac_cv_search_pow" >&6; }
5302 ac_res=$ac_cv_search_pow
5303 if test "$ac_res" != no; then :
5304 test "$ac_res" = "none required" || LIBS="$ac_res $LIBS"
5305
5306 $as_echo "#define HAVE_POW 1" >>confdefs.h
5307
5308 fi
52385309
52395310
52405311 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for grep that handles long lines and -e" >&5
62646335 # report actual input values of CONFIG_FILES etc. instead of their
62656336 # values after options handling.
62666337 ac_log="
6267 This file was extended by gifsicle $as_me 1.76, which was
6338 This file was extended by gifsicle $as_me 1.77, which was
62686339 generated by GNU Autoconf 2.69. Invocation command line was
62696340
62706341 CONFIG_FILES = $CONFIG_FILES
63306401 cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
63316402 ac_cs_config="`$as_echo "$ac_configure_args" | sed 's/^ //; s/[\\""\`\$]/\\\\&/g'`"
63326403 ac_cs_version="\\
6333 gifsicle config.status 1.76
6404 gifsicle config.status 1.77
63346405 configured by $0, generated by GNU Autoconf 2.69,
63356406 with options \\"\$ac_cs_config\\"
63366407
00 dnl Process this file with autoconf to produce a configure script.
1 AC_INIT([gifsicle], [1.76])
1 AC_INIT([gifsicle], [1.77])
22 AC_CONFIG_SRCDIR([src/gifsicle.h])
33 AC_CONFIG_HEADERS([config.h])
44 AM_INIT_AUTOMAKE
3131 fi)
3232
3333 AC_ARG_ENABLE(warnings,
34 [ --enable-warnings compile with -Wall],
34 [ --enable-warnings compile with -W -Wall],
3535 if test "x$enableval" = xyes ; then
3636 CC="$CC -W -Wall"
3737 fi)
38
39 AC_ARG_ENABLE([werror],
40 [ --enable-werror compile with -Werror],
41 if test "x$enableval" = xyes ; then
42 WERROR="-Werror"
43 fi)
44 AC_SUBST([WERROR])
3845
3946 AC_ARG_ENABLE(all,
4047 [ --enable-all --enable-gifview --enable-gifdiff --enable-warnings],
4148 if test "x$enableval" = xyes ; then
4249 build_gifview=yes
4350 build_gifdiff=yes
44 CC="$CC -Wall"
51 CC="$CC -W -Wall"
4552 fi)
4653
4754 ungif=
113120 else
114121 MALLOC_O=fmalloc.o
115122 fi
116 AC_SUBST(MALLOC_O)dnl
123 AC_SUBST(MALLOC_O)
117124
118125 dnl
119126 dnl Set up `ungif' support
135142 dnl random or rand, strerror, strtoul, mkstemp, sys/select.h
136143 dnl
137144
138 AC_CHECK_FUNC(random, random_func=random, random_func=rand)
145 AC_CHECK_FUNC([random], [random_func=random], [random_func=rand])
139146 AC_DEFINE_UNQUOTED(RANDOM, ${random_func}, [Define to a function that returns a random number.])
140147
141 AC_REPLACE_FUNCS(strerror)
142 AC_CHECK_FUNCS(strtoul mkstemp)
143
144 AC_CHECK_HEADERS(sys/select.h inttypes.h unistd.h)
148 AC_REPLACE_FUNCS([strerror])
149 AC_CHECK_FUNCS([strtoul mkstemp])
150 AC_SEARCH_LIBS([pow], [m], [AC_DEFINE([HAVE_POW], [1], [Define to 1 if you have the `pow' function.])])
151
152 AC_CHECK_HEADERS([sys/select.h inttypes.h unistd.h])
145153
146154
147155 dnl
00 .\" -*- mode: nroff -*-
1 .ds V 1.76
1 .ds V 1.77
22 .ds E " \-\-
33 .if t .ds E \(em
44 .de Op
00 .\" -*- mode: nroff -*-
1 .ds V 1.76
1 .ds V 1.77
22 .ds E " \-\-
33 .if t .ds E \(em
44 .de Op
5353 .B gifsicle
5454 is a powerful command-line program for creating, editing, manipulating, and
5555 getting information about GIF images and animations.
56 '
57 .SH INTRODUCTION
58 '
59 Without options,
56 .PP
57 .B Gifsicle
58 normally processes input GIF files according to its command line
59 options and writes the result to the standard output. The
60 .Op \-i
61 option, for example, tells
6062 .B gifsicle
61 acts like a filter: you feed it a GIF on standard input, and it writes that
62 GIF on standard output. That means these two commands do the same thing:
63 .Es
64 \fBgifsicle < in.gif > out.gif\fR
65 \fBgifsicle < in.gif | gifsicle | gifsicle > out.gif\fR
66 .Ee
67 Not too interesting. Most times you'll tell
68 .B gifsicle
69 to alter its inputs by giving it command line options. The
70 .Op \-i
71 option, for example, tells it to interlace its input files:
63 to interlace its inputs:
7264 .Es
7365 \fBgifsicle \-i < pic.gif > interlaced-pic.gif\fR
7466 .Ee
7567 .PP
76 To modify GIF files in place, you should use the
68 .B Gifsicle
69 is good at creating and manipulating GIF animations. By default, it
70 combines two or more input files into a \(lqflipbook\(rq animation:
71 .Es
72 \fBgifsicle pic1.gif pic2.gif pic3.gif > animation.gif\fR
73 .Ee
74 Use options like
75 .Op \-\-delay ", " \-\-loopcount ", and " \-\-optimize
76 to tune your animations.
77 .PP
78 To modify GIF files in place, use the
7779 .Op \-\-batch
7880 option. With
7981 .Op \-\-batch ,
8486 .Es
8587 \fBgifsicle \-\-batch \-i *.gif
8688 .Ee
87 .PP
88 .B gifsicle
89 is good at creating and manipulating GIF animations. The simplest way to
90 create an animation is to give more than one input file, which
91 .B gifsicle
92 will combine to create a \(lqflipbook\(rq animation:
93 .Es
94 \fBgifsicle pic1.gif pic2.gif pic3.gif > animation.gif\fR
95 .Ee
96 Use options like
97 .Op \-\-delay ", " \-\-loopcount ", and " \-\-optimize
98 to tune your animations; see their descriptions for more details.
9989 .PP
10090 New users may want to skip to
10191 the Examples section at the end.
117107 .Ix "Bad output" "\fB\-\-careful\fP"
118108 .Ix "Background color" "\fB\-\-background\fP"
119109 .Ix "Colors, changing" "\fB\-\-change\-color\fP, \fB\-\-use\-colormap\fP, \fB\-\-dither\fP, \fB\-\-transform\-colormap\fP"
120 .Ix "\ \ \ reducing number" "\fB\-\-colors\fP, \fB\-\-dither\fP"
110 .Ix "\ \ \ reducing number" "\fB\-\-colors\fP, \fB\-\-dither\fP, \fB\-\-gamma\fP"
121111 .Ix "Comments" "\fB\-\-comment\fP"
122112 .Ix "Extensions" "\fB\-\-extension\fP, \fB\-\-app\-extension\fP, \fB\-\-extension\-info\fP"
123113 .Ix "File size" "\fB\-\-optimize\fP, \fB\-\-unoptimize\fP, \fB\-\-colors\fP"
134124 .Ix "Selecting frames" "frame selections (like \fB'#0'\fP)"
135125 .Ix "Transparency" "\fB\-\-transparent\fP"
136126 .Ix "Warnings" "\fB\-\-no\-warnings\fP"
137 .Ix "Web-safe palette" "\fB\-\-use\-colormap\fP"
138127 .PD
139128 '
140129 .SH COMMAND LINE
970959 must be between 2 and 256. This can be used to shrink output GIFs or
971960 eliminate any local color tables.
972961 .Sp
973 Unless you give
974 .Op \-\-use\-colormap ,
975 an adaptive group of colors is chosen from the existing color table.
976 You can affect this process with the
962 Normally, an adaptive group of colors is chosen from the existing
963 color table. You can affect this process with the
977964 .Op \-\-color\-method
978 option. Gifsicle may need to add an additional color (making
965 option or by giving your own colormap with
966 .Op \-\-use\-colormap .
967 Gifsicle may need to add an additional color (making
979968 .IR num +1
980969 in all) if there is transparency in the image.
981970 '
983972 .TP
984973 .Oa \-\-color\-method method
985974 '
986 Determine how a smaller colormap is chosen. There are three choices:
987 .BR diversity ,
975 Determine how a smaller colormap is chosen.
976 .RB \(oq diversity \(cq,
988977 the default, is
989978 .BR xv (1)'s
990 diversity algorithm, which uses a strict subset of the existing colors.
991 .B blend\-diversity
992 is a modification of this: some color values are blended from a group of
993 the existing colors.
994 .B median\-cut
979 diversity algorithm, which uses a strict subset of the existing colors
980 and generally produces good results.
981 .RB \(oq blend\-diversity \(cq
982 is a modification of this: some color values are blended from groups of
983 existing colors.
984 .RB \(oq median\-cut \(cq
995985 is the median cut algorithm described by Heckbert.
996986 .Op \-\-method
997987 is a synonym for
1001991 .TP 5
1002992 .Oa \-f
1003993 .TP
1004 .Oa \-\-dither
1005 '
1006 This option only matters if the colormap was changed. With
994 .Op \-\-dither "[=\fImethod\fR]"
995 '
996 When
1007997 .Op \-\-dither
1008 on, Floyd-Steinberg error diffusion is used to approximate any colors that
1009 were removed. This looks better, but makes bigger files and can cause
1010 animation artifacts, so it is off by default.
998 is on and the colormap is changed, combinations of colors are used to
999 approximate missing colors. This looks better, but makes bigger files
1000 and can cause animation artifacts, so it is off by default.
1001 .Sp
1002 Specify a dithering algorithm with the optional \fImethod\fR argument.
1003 The default,
1004 .RB \(oq floyd-steinberg \(cq,
1005 uses Floyd-Steinberg error
1006 diffusion. This usually looks best, but can cause animation artifacts,
1007 because dithering choices will vary from frame to frame. Gifsicle also
1008 supports ordered dithering algorithms that avoid animation artifacts.
1009 The
1010 .RB \(oq ro64 \(cq
1011 mode uses a
1012 large, random-looking pattern and generally produces good results. The
1013 .RB \(oq o3 \(cq,
1014 .RB \(oq o4 \(cq,
1015 and
1016 .RB \(oq o8 \(cq
1017 modes use smaller, more
1018 regular patterns. The
1019 .RB \(oq ordered \(cq
1020 mode chooses a good ordered
1021 dithering algorithm. For special effects, try the halftone modes
1022 .RB \(oq halftone \(cq,
1023 .RB \(oq squarehalftone \(cq,
1024 and
1025 .RB \(oq diagonal \(cq.
1026 Some modes take optional parameters using commas. The halftone modes
1027 take a cell size and a color limit:
1028 .RB \(oq halftone,10,3 \(cq
1029 creates 10-pixel wide halftone cells where each cell uses up to 3
1030 colors.
1031 '
1032 .Sp
1033 .TP 5
1034 .Oa \-\-gamma gamma
1035 '
1036 Set the gamma correction to
1037 .IR gamma ,
1038 which can be a real number or
1039 .RB \(oq srgb \(cq.
1040 Roughly speaking, higher
1041 numbers exaggerate shadows and lower numbers exaggerate highlights.
1042 The default is the function defined by the standard sRGB color space,
1043 which usually works well. (Its effects are similar to
1044 \fB\-\-gamma\fP=2.2.) Gifsicle uses gamma correction when choosing a
1045 color palette (\fB\-\-colors\fP) and when dithering
1046 (\fB\-\-dither\fP).
10111047 '
10121048 .Sp
10131049 .PD 0
10221058 .I color
10231059 arguments have the same forms as in the
10241060 .Op \-t
1025 option.) You can change multiple colors by giving the option multiple
1061 option.) Change multiple colors by giving the option multiple
10261062 times. Color changes don't interfere with one another, so you can safely
10271063 swap two colors with
10281064 .Qa \-\-change\-color "color1 color2" \-\-change\-color "color2 color1" .
10391075 standard output. Each colormap in the output GIF is translated into text
10401076 colormap format (see
10411077 .Op \-\-use\-colormap
1042 below) and piped to the command. The output that command generates (which
1043 should also be in text colormap format) will be used as the colormap
1044 instead.
1078 below) and piped to the command. The output that command generates
1079 (which should also be in text colormap format) will replace the input
1080 colormap. The replacement doesn't consider color matching, so pixels
1081 that used color slot
1082 .I n
1083 in the input will still use color slot
1084 .I n
1085 in the output.
10451086 '
10461087 .Sp
10471088 .TP
11231164 .br
11241165 \fBls anim.gif*\fR
11251166 .br
1126 anim.gif anim.gif.000 anim.gif.001 anim.gif.002 anim.gif.003
1167 anim.gif anim.gif.000 anim.gif.001 anim.gif.002 anim.gif.003
11271168 .Ee
11281169 To optimize \(oqanim.gif\(cq:
11291170 .Es
00 Summary: GIF image and animation manipulator
11
22 Name: gifsicle
3 Version: 1.76
3 Version: 1.77
44 Release: 1
5 Source: http://www.lcdf.org/gifsicle/gifsicle-1.76.tar.gz
5 Source: http://www.lcdf.org/gifsicle/gifsicle-1.77.tar.gz
66
77 Icon: logo1.gif
88 URL: http://www.lcdf.org/gifsicle/
00 .\" -*- mode: nroff -*-
1 .ds V 1.76
1 .ds V 1.77
22 .ds E " \-\-
33 .if t .ds E \(em
44 .de Op
224224 '
225225 .Sp
226226 .TP 5
227 .Oa \-\-fallback\-delay delay
228 '
229 Set the frame delay of GIFs that do not specify a delay value
230 or have a delay of 0.
231 The final value is still subject to the value of \-\-min\-delay.
232 Like \-\-min\-delay,
233 .IR delay
234 is measured in hundredths of a second. Default is 0.
235 '
236 .Sp
237 .TP 5
227238 .Op \-\-no\-interactive ", " \+e
228239 '
229240 Don't pay attention to mouse buttons or keystrokes.
241 '
242 .Sp
243 .TP 5
244 .Op \-\-memory\-limit lim
245 '
246 Cache at most
247 .I lim
248 megabytes of images in memory when animating. Default is 40.
230249 '
231250 .Sp
232251 .TP 5
4848 struct Gif_XFrame {
4949 Pixmap pixmap;
5050 int postdisposal;
51 int user_data;
5152 };
5253
5354 Gif_XContext * Gif_NewXContext(Display *display, Window window);
1111 gifview_DEPENDENCIES = @MALLOC_O@ @LIBOBJS@
1212 gifdiff_DEPENDENCIES = @MALLOC_O@ @LIBOBJS@
1313
14 WERROR = @WERROR@
15
1416 gifsicle_SOURCES = clp.c \
1517 giffunc.c gifread.c gifunopt.c \
1618 gifsicle.h merge.c optimize.c quantize.c support.c xform.c \
2426 giffunc.c gifread.c \
2527 gifdiff.c
2628
27 AM_CPPFLAGS = $(X_CFLAGS) -I$(top_srcdir)/include
29 AM_CPPFLAGS = $(X_CFLAGS) $(WERROR) -I$(top_srcdir)/include
2830
2931 EXTRA_DIST = dmalloc.h dmalloc.c fmalloc.c gifwrite.c ungifwrt.c \
3032 Makefile.bcc Makefile.w32 win32cfg.h
208208 SHELL = @SHELL@
209209 STRIP = @STRIP@
210210 VERSION = @VERSION@
211 WERROR = @WERROR@
211212 XMKMF = @XMKMF@
212213 X_CFLAGS = @X_CFLAGS@
213214 X_EXTRA_LIBS = @X_EXTRA_LIBS@
275276 giffunc.c gifread.c \
276277 gifdiff.c
277278
278 AM_CPPFLAGS = $(X_CFLAGS) -I$(top_srcdir)/include
279 AM_CPPFLAGS = $(X_CFLAGS) $(WERROR) -I$(top_srcdir)/include
279280 EXTRA_DIST = dmalloc.h dmalloc.c fmalloc.c gifwrite.c ungifwrt.c \
280281 Makefile.bcc Makefile.w32 win32cfg.h
281282
10961096 if (*arg == 0 || isspace((unsigned char) *arg)
10971097 || ((type & 1) && *arg == '-'))
10981098 val = arg;
1099 else if (type & 1) { // unsigned
1099 else if (type & 1) { /* unsigned */
11001100 #if HAVE_STRTOUL
11011101 clp->val.ul = strtoul(arg, (char **) &val, 0);
11021102 #else
384384 should compare as the same. Gifdiff exits with status 0 if the images are\n\
385385 the same, 1 if they're different, and 2 if there was some error.\n\
386386 \n\
387 Usage: %s [OPTION]... FILE1 FILE2\n\
388 \n\
387 Usage: %s [OPTION]... FILE1 FILE2\n\n", program_name);
388 printf("\
389389 Options:\n\
390390 -q, --brief Don't report detailed differences.\n\
391391 -w, --ignore-redundancy Ignore differences in redundant frames.\n\
392392 -h, --help Print this message and exit.\n\
393393 -v, --version Print version number and exit.\n\
394394 \n\
395 Report bugs to <ekohler@gmail.com>.\n", program_name);
395 Report bugs to <ekohler@gmail.com>.\n");
396396 }
397397
398398
108108 #define CH_COLOR_TRANSFORM 9
109109 #define CH_RESIZE 10
110110 #define CH_MEMORY 11
111 #define CH_GAMMA 12
111112 static const char *output_option_types[] = {
112113 "loopcount", "logical screen", "optimization", "output file",
113114 "colormap size", "dither", "colormap", "colormap method",
114 "background", "color transformation", "resize", "memory conservation"
115 "background", "color transformation", "resize", "memory conservation",
116 "gamma"
115117 };
116118
117119
181183 #define RESIZE_FIT_WIDTH_OPT 365
182184 #define RESIZE_FIT_HEIGHT_OPT 366
183185 #define SIZE_INFO_OPT 367
186 #define GAMMA_OPT 368
187 #define GRAY_OPT 369
184188
185189 #define LOOP_TYPE (Clp_ValFirstUser)
186190 #define DISPOSAL_TYPE (Clp_ValFirstUser + 1)
219223 { "delay", 'd', 'd', Clp_ValInt, Clp_Negate },
220224 { "delete", 0, DELETE_OPT, 0, 0 },
221225 { "disposal", 'D', DISPOSAL_OPT, DISPOSAL_TYPE, Clp_Negate },
222 { "dither", 'f', DITHER_OPT, 0, Clp_Negate },
226 { 0, 'f', DITHER_OPT, 0, Clp_Negate },
227 { "dither", 0, DITHER_OPT, Clp_ValString, Clp_Negate | Clp_Optional },
223228 { "done", 0, ALTER_DONE_OPT, 0, 0 },
224229
225230 { "explode", 'e', 'e', 0, 0 },
231236 { "flip-horizontal", 0, FLIP_HORIZ_OPT, 0, Clp_Negate },
232237 { "flip-vertical", 0, FLIP_VERT_OPT, 0, Clp_Negate },
233238 { "no-flip", 0, NO_FLIP_OPT, 0, 0 },
239
240 { "gamma", 0, GAMMA_OPT, Clp_ValString, Clp_Negate },
241 { "gray", 0, GRAY_OPT, 0, 0 },
234242
235243 { "help", 'h', HELP_OPT, 0, 0 },
236244
780788 }
781789
782790 static void
783 do_set_colormap(Gif_Stream *gfs, Gif_Colormap *gfcm)
784 {
785 colormap_image_func image_func;
786 if (active_output_data.colormap_dither)
787 image_func = colormap_image_floyd_steinberg;
788 else
789 image_func = colormap_image_posterize;
790 colormap_stream(gfs, gfcm, image_func);
791 }
792
793 static void
794791 do_colormap_change(Gif_Stream *gfs)
795792 {
793 if (active_output_data.colormap_fixed || active_output_data.colormap_size > 0)
794 kc_set_gamma(active_output_data.colormap_gamma_type,
795 active_output_data.colormap_gamma);
796
796797 if (active_output_data.colormap_fixed)
797 do_set_colormap(gfs, active_output_data.colormap_fixed);
798 colormap_stream(gfs, active_output_data.colormap_fixed,
799 &active_output_data);
798800
799801 if (active_output_data.colormap_size > 0) {
800802 int nhist;
801803 Gif_Color *hist;
802 Gif_Colormap *(*adapt_func)(Gif_Color *, int, int, int);
804 Gif_Colormap* (*adapt_func)(Gif_Color*, int, Gt_OutputData*);
803805 Gif_Colormap *new_cm;
804806
805807 /* set up the histogram */
836838
837839 }
838840
839 new_cm = (*adapt_func)(hist, nhist, active_output_data.colormap_size,
840 !active_output_data.colormap_fixed);
841 do_set_colormap(gfs, new_cm);
841 new_cm = (*adapt_func)(hist, nhist, &active_output_data);
842 colormap_stream(gfs, new_cm, &active_output_data);
842843
843844 Gif_DeleteArray(hist);
844845 Gif_DeleteColormap(new_cm);
11471148 def_output_data.colormap_size = 0;
11481149 def_output_data.colormap_fixed = 0;
11491150 def_output_data.colormap_algorithm = COLORMAP_DIVERSITY;
1150 def_output_data.colormap_dither = 0;
1151 def_output_data.dither_type = dither_none;
1152 def_output_data.dither_name = "none";
1153 def_output_data.colormap_gamma_type = KC_GAMMA_SRGB;
1154 def_output_data.colormap_gamma = 2.2;
11511155
11521156 def_output_data.optimizing = 0;
11531157 def_output_data.scaling = GT_SCALING_NONE;
11881192 Gif_DeleteColormap(active_output_data.colormap_fixed);
11891193 active_output_data.colormap_fixed = def_output_data.colormap_fixed;
11901194 }
1191 COMBINE_ONE_OUTPUT_OPTION(CH_DITHER, colormap_dither);
1195 if (CHANGED(recent, CH_DITHER)) {
1196 MARK_CH(output, CH_DITHER);
1197 active_output_data.dither_type = def_output_data.dither_type;
1198 active_output_data.dither_data = def_output_data.dither_data;
1199 }
1200 if (CHANGED(recent, CH_GAMMA)) {
1201 MARK_CH(output, CH_GAMMA);
1202 active_output_data.colormap_gamma_type = def_output_data.colormap_gamma_type;
1203 active_output_data.colormap_gamma = def_output_data.colormap_gamma;
1204 }
11921205
11931206 if (CHANGED(recent, CH_RESIZE)) {
11941207 MARK_CH(output, CH_RESIZE);
12571270 int
12581271 main(int argc, char *argv[])
12591272 {
1273 Clp_Parser* clp;
1274
12601275 /* Check SIZEOF constants (useful for Windows). If these assertions fail,
12611276 you've used the wrong Makefile. You should've used Makefile.w32 for
12621277 32-bit Windows and Makefile.w64 for 64-bit Windows. */
12641279 static_assert(sizeof(unsigned long) == SIZEOF_UNSIGNED_LONG, "unsigned long has the wrong size.");
12651280 static_assert(sizeof(void*) == SIZEOF_VOID_P, "void* has the wrong size.");
12661281
1267 Clp_Parser *clp =
1268 Clp_NewParser(argc, (const char * const *)argv, sizeof(options) / sizeof(options[0]), options);
1282 clp = Clp_NewParser(argc, (const char * const *)argv, sizeof(options) / sizeof(options[0]), options);
12691283
12701284 Clp_AddStringListType
12711285 (clp, LOOP_TYPE, Clp_AllowNumbers,
17031717 }
17041718 break;
17051719
1706 case USE_COLORMAP_OPT:
1720 case GRAY_OPT:
1721 MARK_CH(output, CH_USE_COLORMAP);
1722 Gif_DeleteColormap(def_output_data.colormap_fixed);
1723 set_new_fixed_colormap("gray");
1724 break;
1725
1726 case USE_COLORMAP_OPT:
17071727 MARK_CH(output, CH_USE_COLORMAP);
17081728 Gif_DeleteColormap(def_output_data.colormap_fixed);
17091729 if (clp->negated)
17171737 def_output_data.colormap_algorithm = clp->val.i;
17181738 break;
17191739
1720 case DITHER_OPT:
1721 MARK_CH(output, CH_DITHER);
1722 def_output_data.colormap_dither = !clp->negated;
1723 break;
1740 case DITHER_OPT: {
1741 const char* name;
1742 if (clp->negated)
1743 name = "none";
1744 else if (!clp->have_val)
1745 name = "default";
1746 else
1747 name = clp->val.s;
1748 if (strcmp(name, "posterize") == 0)
1749 name = "none";
1750 if (strcmp(name, def_output_data.dither_name) != 0
1751 && (strcmp(name, "none") == 0
1752 || strcmp(def_output_data.dither_name, "default") != 0))
1753 MARK_CH(output, CH_DITHER);
1754 UNCHECKED_MARK_CH(output, CH_DITHER);
1755 if (set_dither_type(&def_output_data, name) < 0)
1756 Clp_OptionError(clp, "%<%s%> is not a valid dither", name);
1757 def_output_data.dither_name = name;
1758 break;
1759 }
1760
1761 case GAMMA_OPT: {
1762 #if HAVE_POW
1763 char* ends;
1764 MARK_CH(output, CH_GAMMA);
1765 if (clp->negated) {
1766 def_output_data.colormap_gamma_type = KC_GAMMA_NUMERIC;
1767 def_output_data.colormap_gamma = 1;
1768 } else if (strcmp(clp->val.s, "sRGB") == 0
1769 || strcmp(clp->val.s, "srgb") == 0)
1770 def_output_data.colormap_gamma_type = KC_GAMMA_SRGB;
1771 else {
1772 double gamma = strtod(clp->val.s, &ends);
1773 if (*clp->val.s && !*ends && !isspace((unsigned char) *clp->val.s)) {
1774 def_output_data.colormap_gamma_type = KC_GAMMA_NUMERIC;
1775 def_output_data.colormap_gamma = gamma;
1776 } else
1777 Clp_OptionError(clp, "%O should be a number or %<srgb%>");
1778 }
1779 #else
1780 Clp_OptionError(clp, "this version of Gifsicle does not support %O");
1781 #endif
1782 break;
1783 }
17241784
17251785 case RESIZE_OPT:
17261786 case RESIZE_FIT_OPT:
104104 int colormap_size;
105105 Gif_Colormap *colormap_fixed;
106106 int colormap_algorithm;
107 int colormap_dither;
107 int dither_type;
108 const uint8_t* dither_data;
109 const char* dither_name;
110 int colormap_gamma_type;
111 double colormap_gamma;
108112
109113 int optimizing;
110114
227231 * quantization
228232 **/
229233 Gif_Color *histogram(Gif_Stream *, int *);
234 #define KC_GAMMA_SRGB 0
235 #define KC_GAMMA_NUMERIC 1
236 void kc_set_gamma(int type, double gamma);
230237
231238 #define COLORMAP_DIVERSITY 0
232239 #define COLORMAP_BLEND_DIVERSITY 1
233240 #define COLORMAP_MEDIAN_CUT 2
234 Gif_Colormap *colormap_blend_diversity(Gif_Color *, int, int, int);
235 Gif_Colormap *colormap_flat_diversity(Gif_Color *, int, int, int);
236 Gif_Colormap *colormap_median_cut(Gif_Color *, int, int, int);
241 Gif_Colormap* colormap_blend_diversity(Gif_Color*, int, Gt_OutputData*);
242 Gif_Colormap* colormap_flat_diversity(Gif_Color*, int, Gt_OutputData*);
243 Gif_Colormap* colormap_median_cut(Gif_Color*, int, Gt_OutputData*);
237244
238245 typedef struct kd3_tree kd3_tree;
239 typedef void (*colormap_image_func)
240 (Gif_Image*, uint8_t*, Gif_Colormap*, kd3_tree*, uint32_t*);
241
242 void colormap_image_posterize
243 (Gif_Image*, uint8_t*, Gif_Colormap*, kd3_tree*, uint32_t*);
244 void colormap_image_floyd_steinberg
245 (Gif_Image*, uint8_t*, Gif_Colormap*, kd3_tree*, uint32_t*);
246 void colormap_stream(Gif_Stream *, Gif_Colormap *, colormap_image_func);
246
247 enum {
248 dither_none = 0, dither_default, dither_floyd_steinberg,
249 dither_ordered, dither_ordered_new
250 };
251 int set_dither_type(Gt_OutputData* od, const char* name);
252 void colormap_stream(Gif_Stream*, Gif_Colormap*, Gt_OutputData*);
247253
248254 /*****
249255 * parsing stuff
4343 #define EXTERN extern
4444 #endif
4545
46 #define SAVE_FRAMES 20
47
4846 /*****
4947 * TIME STUFF (from xwrits)
5048 **/
9896 * THE VIEWER STRUCTURE
9997 **/
10098
99 static unsigned pixel_memory_limit_kb = 40000;
100 static unsigned pixel_memory_kb;
101
101102 typedef struct Gt_Viewer {
102103
103104 Display *display;
129130 Pixmap pixmap;
130131 int im_pos;
131132 int was_unoptimized;
132 int free_pixmaps;
133133
134134 Gif_XFrame *unoptimized_frames;
135 int n_unoptimized_frames;
135136
136137 struct Gt_Viewer *next;
137138
166167 static int install_colormap = 0;
167168 static int interactive = 1;
168169 static int min_delay = 0;
170 static int fallback_delay = 0;
169171
170172 static struct timeval preparation_time;
171173
184186 #define NEW_WINDOW_OPT 311
185187 #define TITLE_OPT 312
186188 #define MIN_DELAY_OPT 313
189 #define FALLBACK_DELAY_OPT 314
190 #define MEMORY_LIMIT_OPT 315
187191
188192 #define WINDOW_TYPE (Clp_ValFirstUser)
189193
196200 { "install-colormap", 'i', INSTALL_COLORMAP_OPT, 0, Clp_Negate },
197201 { "interactive", 'e', INTERACTIVE_OPT, 0, Clp_Negate },
198202 { "help", 0, HELP_OPT, 0, 0 },
203 { "memory-limit", 0, MEMORY_LIMIT_OPT, Clp_ValUnsigned, Clp_Negate },
199204 { "min-delay", 0, MIN_DELAY_OPT, Clp_ValInt, Clp_Negate },
205 { "fallback-delay", 0, FALLBACK_DELAY_OPT, Clp_ValInt, Clp_Negate },
200206 { "name", 0, NAME_OPT, Clp_ValString, 0 },
201207 { "title", 'T', TITLE_OPT, Clp_ValString, 0 },
202208 { "unoptimize", 'U', UNOPTIMIZE_OPT, 0, Clp_Negate },
256262 'Gifview' is a lightweight GIF viewer for X. It can display animated GIFs as\n\
257263 slideshows, one frame at a time, or as animations.\n\
258264 \n\
259 Usage: %s [--display DISPLAY] [OPTION]... [FILE | FRAME]...\n\
260 \n\
265 Usage: %s [--display DISPLAY] [OPTION]... [FILE | FRAME]...\n\n", program_name);
266 printf("\
261267 Options are:\n\
262268 -a, --animate Animate multiframe GIFs.\n\
263269 -U, --unoptimize Unoptimize displayed GIFs.\n\
264270 -d, --display DISPLAY Set display to DISPLAY.\n\
265271 --name NAME Set application resource name to NAME.\n\
266272 -g, --geometry GEOMETRY Set window geometry.\n\
267 -T, --title TITLE Set window title.\n\
273 -T, --title TITLE Set window title.\n");
274 printf("\
268275 -w, --window WINDOW Show GIF in existing WINDOW.\n\
269276 --new-window WINDOW Show GIF in new child of existing WINDOW.\n\
270277 -i, --install-colormap Use a private colormap.\n\
271278 --bg, --background COLOR Use COLOR for transparent pixels.\n\
272279 --min-delay DELAY Set minimum frame delay to DELAY/100 sec.\n\
273 +e, --no-interactive Ignore buttons and keystrokes.\n\
280 --fallback-delay DELAY Set fallback frame delay to DELAY/100 sec.\n\
281 +e, --no-interactive Ignore buttons and keystrokes.\n");
282 printf("\
283 --memory-limit LIM Cache at most LIM megabytes of animation.\n\
274284 --help Print this message and exit.\n\
275285 --version Print version number and exit.\n\
276286 \n\
277 Frame selections: #num, #num1-num2, #num1-, #name\n\
278 \n\
287 Frame selections: #num, #num1-num2, #num1-, #name\n\n");
288 printf("\
279289 Keystrokes:\n\
280290 [N]/[Space] Go to next frame. [P]/[B] Go to previous frame.\n\
281291 [R]/[<] Go to first frame. [>] Go to last frame.\n\
285295 \n\
286296 Left mouse button goes to next frame, right mouse button deletes window.\n\
287297 \n\
288 Report bugs to <ekohler@gmail.com>.\n", program_name);
298 Report bugs to <ekohler@gmail.com>.\n");
289299 }
290300
291301
471481 viewer->pixmap = None;
472482 viewer->im_pos = -1;
473483 viewer->was_unoptimized = 0;
474 viewer->free_pixmaps = 1;
475484 viewer->unoptimized_frames = Gif_NewXFrames(gfs);
485 viewer->n_unoptimized_frames = 0;
476486 viewer->next = viewers;
477487 viewers = viewer;
478488 viewer->animating = 0;
630640 struct timeval interval;
631641 int delay = viewer->im[viewer->im_pos]->delay;
632642 int next_pos = viewer->im_pos + 1;
643 if (delay < 1)
644 delay = fallback_delay;
633645 if (delay < min_delay)
634646 delay = min_delay;
635647 if (next_pos == viewer->nim)
851863 Gif_DeleteArray(strs[0]);
852864 }
853865
866 static unsigned screen_memory_kb(const Gt_Viewer* viewer) {
867 return 1 + ((unsigned) (viewer->gfs->screen_width
868 * viewer->gfs->screen_height) / 334);
869 }
870
854871 static Pixmap
855872 unoptimized_frame(Gt_Viewer *viewer, int frame, int slow)
856873 {
858875 if (!viewer->unoptimized_frames[frame].pixmap) {
859876 (void) Gif_XNextImage(viewer->gfx, viewer->gfs, frame,
860877 viewer->unoptimized_frames);
878 pixel_memory_kb += screen_memory_kb(viewer);
879 viewer->unoptimized_frames[viewer->n_unoptimized_frames].user_data =
880 frame;
881 ++viewer->n_unoptimized_frames;
861882 if (slow) {
862883 set_viewer_name(viewer, frame);
863884 XFlush(viewer->display);
864885 }
865886 }
866887
867 /* maybe kill some old frames */
868 if (viewer->free_pixmaps && frame % SAVE_FRAMES == 1) {
869 int kill, block_first = frame - 1, block_last = frame + SAVE_FRAMES - 1;
870 for (kill = 1; kill < viewer->nim; kill++)
871 if (viewer->unoptimized_frames[kill].pixmap && kill % 50 != 0
872 && (kill < block_first || kill >= block_last)) {
873 XFreePixmap(viewer->display, viewer->unoptimized_frames[kill].pixmap);
874 viewer->unoptimized_frames[kill].pixmap = None;
875 }
888 /* kill some old frames if over the memory limit */
889 while (pixel_memory_limit_kb != (unsigned) -1
890 && pixel_memory_limit_kb < pixel_memory_kb
891 && viewer->n_unoptimized_frames > 1) {
892 int killidx, killframe, i = 0;
893 do {
894 killidx = random() % viewer->n_unoptimized_frames;
895 killframe = viewer->unoptimized_frames[killidx].user_data;
896 ++i;
897 } while (killframe == frame
898 || (i < 10 && killframe > frame && killframe < frame + 5)
899 || (i < 10 && (killframe % 50) == 0));
900 XFreePixmap(viewer->display, viewer->unoptimized_frames[killframe].pixmap);
901 viewer->unoptimized_frames[killframe].pixmap = None;
902 --viewer->n_unoptimized_frames;
903 viewer->unoptimized_frames[killidx].user_data =
904 viewer->unoptimized_frames[viewer->n_unoptimized_frames].user_data;
905 pixel_memory_kb -= screen_memory_kb(viewer);
876906 }
877907
878908 return viewer->unoptimized_frames[frame].pixmap;
902932 }
903933
904934 /* Prepare the frame */
905 (void) unoptimized_frame(viewer, frame, changed_cursor);
935 (void) unoptimized_frame(viewer, frame, changed_cursor && !viewer->animating);
906936
907937 /* Restore cursor */
908938 if (changed_cursor)
13121342 min_delay = clp->negated ? 0 : clp->val.i;
13131343 break;
13141344
1345 case FALLBACK_DELAY_OPT:
1346 fallback_delay = clp->negated ? 0 : clp->val.i;
1347 break;
1348
1349 case MEMORY_LIMIT_OPT:
1350 if (clp->negated || clp->val.u >= ((unsigned) -1 / 1000))
1351 pixel_memory_limit_kb = (unsigned) -1;
1352 else
1353 pixel_memory_limit_kb = clp->val.u * 1000;
1354 break;
1355
13151356 case VERSION_OPT:
13161357 printf("gifview (LCDF Gifsicle) %s\n", VERSION);
13171358 printf("Copyright (C) 1997-2013 Eddie Kohler\n\
1010 #include "gifsicle.h"
1111 #include <assert.h>
1212 #include <string.h>
13
14 static inline uint32_t rgb_distance(const Gif_Color* x, const Gif_Color* y) {
15 return (x->gfc_red - y->gfc_red) * (x->gfc_red - y->gfc_red)
16 + (x->gfc_green - y->gfc_green) * (x->gfc_green - y->gfc_green)
17 + (x->gfc_blue - y->gfc_blue) * (x->gfc_blue - y->gfc_blue);
18 }
19
20 static inline unsigned kd3_distance(const int x[3], const int y[3]) {
21 return (x[0] - y[0]) * (x[0] - y[0])
22 + (x[1] - y[1]) * (x[1] - y[1])
23 + (x[2] - y[2]) * (x[2] - y[2]);
24 }
25
26 static inline void kd3_luminance_transform(int x[3]) {
13 #include <stdlib.h>
14 #include <limits.h>
15 #include <ctype.h>
16 #include <math.h>
17
18 /* kcolor: a 3D vector, each component has 15 bits of precision */
19 /* 15 bits means KC_MAX * KC_MAX always fits within a signed 32-bit
20 integer, and a 3-D squared distance always fits within an unsigned 32-bit
21 integer. */
22 #define KC_MAX 0x7FFF
23 #define KC_WHOLE 0x8000
24 #define KC_HALF 0x4000
25 #define KC_BITS 15
26 typedef struct kcolor {
27 int32_t a[3];
28 } kcolor;
29
30 /* Invariant: (0<=x<256) ==> (srgb_revgamma[srgb_gamma[x] >> 7] <= x). */
31
32 static const uint16_t srgb_gamma_table_256[256] = {
33 0, 10, 20, 30, 40, 50, 60, 70,
34 80, 90, 99, 110, 120, 132, 144, 157,
35 170, 184, 198, 213, 229, 246, 263, 281,
36 299, 319, 338, 359, 380, 403, 425, 449,
37 473, 498, 524, 551, 578, 606, 635, 665,
38 695, 727, 759, 792, 825, 860, 895, 931,
39 968, 1006, 1045, 1085, 1125, 1167, 1209, 1252,
40 1296, 1341, 1386, 1433, 1481, 1529, 1578, 1629,
41 1680, 1732, 1785, 1839, 1894, 1950, 2007, 2065,
42 2123, 2183, 2244, 2305, 2368, 2432, 2496, 2562,
43 2629, 2696, 2765, 2834, 2905, 2977, 3049, 3123,
44 3198, 3273, 3350, 3428, 3507, 3587, 3668, 3750,
45 3833, 3917, 4002, 4088, 4176, 4264, 4354, 4444,
46 4536, 4629, 4723, 4818, 4914, 5011, 5109, 5209,
47 5309, 5411, 5514, 5618, 5723, 5829, 5936, 6045,
48 6154, 6265, 6377, 6490, 6604, 6720, 6836, 6954,
49 7073, 7193, 7315, 7437, 7561, 7686, 7812, 7939,
50 8067, 8197, 8328, 8460, 8593, 8728, 8863, 9000,
51 9139, 9278, 9419, 9560, 9704, 9848, 9994, 10140,
52 10288, 10438, 10588, 10740, 10893, 11048, 11204, 11360,
53 11519, 11678, 11839, 12001, 12164, 12329, 12495, 12662,
54 12831, 13000, 13172, 13344, 13518, 13693, 13869, 14047,
55 14226, 14406, 14588, 14771, 14955, 15141, 15328, 15516,
56 15706, 15897, 16089, 16283, 16478, 16675, 16872, 17071,
57 17272, 17474, 17677, 17882, 18088, 18295, 18504, 18714,
58 18926, 19138, 19353, 19569, 19786, 20004, 20224, 20445,
59 20668, 20892, 21118, 21345, 21573, 21803, 22034, 22267,
60 22501, 22736, 22973, 23211, 23451, 23692, 23935, 24179,
61 24425, 24672, 24920, 25170, 25421, 25674, 25928, 26184,
62 26441, 26700, 26960, 27222, 27485, 27749, 28016, 28283,
63 28552, 28823, 29095, 29368, 29643, 29920, 30197, 30477,
64 30758, 31040, 31324, 31610, 31897, 32185, 32475, 32767
65 };
66
67 static const uint16_t srgb_revgamma_table_256[256] = {
68 0, 1628, 2776, 3619, 4309, 4904, 5434, 5914,
69 6355, 6765, 7150, 7513, 7856, 8184, 8497, 8798,
70 9086, 9365, 9634, 9895, 10147, 10393, 10631, 10864,
71 11091, 11312, 11528, 11739, 11946, 12148, 12347, 12541,
72 12732, 12920, 13104, 13285, 13463, 13639, 13811, 13981,
73 14149, 14314, 14476, 14637, 14795, 14951, 15105, 15257,
74 15408, 15556, 15703, 15848, 15991, 16133, 16273, 16412,
75 16549, 16685, 16819, 16953, 17084, 17215, 17344, 17472,
76 17599, 17725, 17849, 17973, 18095, 18217, 18337, 18457,
77 18575, 18692, 18809, 18925, 19039, 19153, 19266, 19378,
78 19489, 19600, 19710, 19819, 19927, 20034, 20141, 20247,
79 20352, 20457, 20560, 20664, 20766, 20868, 20969, 21070,
80 21170, 21269, 21368, 21466, 21564, 21661, 21758, 21854,
81 21949, 22044, 22138, 22232, 22326, 22418, 22511, 22603,
82 22694, 22785, 22875, 22965, 23055, 23144, 23232, 23321,
83 23408, 23496, 23583, 23669, 23755, 23841, 23926, 24011,
84 24095, 24180, 24263, 24347, 24430, 24512, 24595, 24676,
85 24758, 24839, 24920, 25001, 25081, 25161, 25240, 25319,
86 25398, 25477, 25555, 25633, 25710, 25788, 25865, 25941,
87 26018, 26094, 26170, 26245, 26321, 26396, 26470, 26545,
88 26619, 26693, 26766, 26840, 26913, 26986, 27058, 27130,
89 27202, 27274, 27346, 27417, 27488, 27559, 27630, 27700,
90 27770, 27840, 27910, 27979, 28048, 28117, 28186, 28255,
91 28323, 28391, 28459, 28527, 28594, 28661, 28728, 28795,
92 28862, 28928, 28995, 29061, 29127, 29192, 29258, 29323,
93 29388, 29453, 29518, 29582, 29646, 29711, 29775, 29838,
94 29902, 29965, 30029, 30092, 30155, 30217, 30280, 30342,
95 30404, 30466, 30528, 30590, 30652, 30713, 30774, 30835,
96 30896, 30957, 31017, 31078, 31138, 31198, 31258, 31318,
97 31378, 31437, 31497, 31556, 31615, 31674, 31733, 31791,
98 31850, 31908, 31966, 32024, 32082, 32140, 32198, 32255,
99 32313, 32370, 32427, 32484, 32541, 32598, 32654, 32711
100 };
101
102 static uint16_t* gamma_tables[2] = {
103 (uint16_t*) srgb_gamma_table_256,
104 (uint16_t*) srgb_revgamma_table_256
105 };
106
107
108 static inline void kc_clear(kcolor* x) {
109 x->a[0] = x->a[1] = x->a[2] = 0;
110 }
111
112 static inline void kc_clamp(kcolor* x) {
113 int i;
114 for (i = 0; i < 3; ++i) {
115 if (x->a[i] < 0)
116 x->a[i] = 0;
117 if (x->a[i] > KC_MAX)
118 x->a[i] = KC_MAX;
119 }
120 }
121
122 static inline void kc_set8g(kcolor* x, int a0, int a1, int a2) {
123 x->a[0] = gamma_tables[0][a0];
124 x->a[1] = gamma_tables[0][a1];
125 x->a[2] = gamma_tables[0][a2];
126 }
127
128 static inline void kc_revgamma_transform(kcolor* x) {
129 int d;
130 for (d = 0; d != 3; ++d) {
131 int c = gamma_tables[1][x->a[d] >> 7];
132 while (c < 0x7F80 && x->a[d] >= gamma_tables[0][(c + 0x80) >> 7])
133 c += 0x80;
134 x->a[d] = c;
135 }
136 }
137
138 static const char* __attribute__((used)) kc_debug_str(kcolor x) {
139 static int whichbuf = 0;
140 static char buf[4][8];
141 whichbuf = (whichbuf + 1) % 4;
142 kc_revgamma_transform(&x);
143 sprintf(buf[whichbuf], "#%02X%02X%02X",
144 x.a[0] >> 7, x.a[1] >> 7, x.a[2] >> 7);
145 return buf[whichbuf];
146 }
147
148 void kc_set_gamma(int type, double gamma) {
149 #if HAVE_POW
150 static int cur_type = KC_GAMMA_SRGB;
151 static double cur_gamma = 2.2;
152 int i, j;
153 if (type == cur_type && (type != KC_GAMMA_NUMERIC || gamma == cur_gamma))
154 return;
155 if (type == KC_GAMMA_SRGB) {
156 if (gamma_tables[0] != srgb_gamma_table_256) {
157 Gif_DeleteArray(gamma_tables[0]);
158 Gif_DeleteArray(gamma_tables[1]);
159 }
160 gamma_tables[0] = (uint16_t*) srgb_gamma_table_256;
161 gamma_tables[1] = (uint16_t*) srgb_revgamma_table_256;
162 } else {
163 if (gamma_tables[0] == srgb_gamma_table_256) {
164 gamma_tables[0] = Gif_NewArray(uint16_t, 256);
165 gamma_tables[1] = Gif_NewArray(uint16_t, 256);
166 }
167 for (j = 0; j != 256; ++j) {
168 gamma_tables[0][j] = (int) (pow(i/255.0, gamma) * 32767);
169 gamma_tables[1][j] = (int) (pow(i/256.0, 1/gamma) * 32767);
170 for (i = 0; i != 2; ++i)
171 while (j && gamma_tables[i][j] <= gamma_tables[i][j-1]
172 && gamma_tables[i][j] < 3267)
173 ++gamma_tables[i][j];
174 }
175 }
176 cur_type = type;
177 cur_gamma = gamma;
178 #else
179 (void) type, (void) gamma;
180 #endif
181 }
182
183 #if 0
184 static void kc_test_gamma() {
185 int x, y, z;
186 for (x = 0; x != 256; ++x)
187 for (y = 0; y != 256; ++y)
188 for (z = 0; z != 256; ++z) {
189 kcolor k;
190 kc_set8g(&k, x, y, z);
191 kc_revgamma_transform(&k);
192 if ((k.a[0] >> 7) != x || (k.a[1] >> 7) != y
193 || (k.a[2] >> 7) != z) {
194 kcolor kg;
195 kc_set8g(&kg, x, y, z);
196 fprintf(stderr, "#%02X%02X%02X ->g #%04X%04X%04X ->revg #%02X%02X%02X!\n",
197 x, y, z, kg.a[0], kg.a[1], kg.a[2],
198 k.a[0] >> 7, k.a[1] >> 7, k.a[2] >> 7);
199 assert(0);
200 }
201 }
202 }
203 #endif
204
205 static inline uint32_t kc_distance(const kcolor* x, const kcolor* y) {
206 return (x->a[0] - y->a[0]) * (x->a[0] - y->a[0])
207 + (x->a[1] - y->a[1]) * (x->a[1] - y->a[1])
208 + (x->a[2] - y->a[2]) * (x->a[2] - y->a[2]);
209 }
210
211 static inline int kc_luminance(const kcolor* x) {
212 return (306 * x->a[0] + 601 * x->a[1] + 117 * x->a[2]) >> 10;
213 }
214
215 static inline void kc_luminance_transform(kcolor* x) {
27216 /* For grayscale colormaps, use distance in luminance space instead of
28217 distance in RGB space. The weights for the R,G,B components in
29218 luminance space are 0.299,0.587,0.114. Using the proportional factors
30219 306, 601, and 117 we get a scaled gray value between 0 and 255 *
31220 1024. Thanks to Christian Kumpf, <kumpf@igd.fhg.de>, for providing a
32221 patch. */
33 int gray = (306 * x[0] + 601 * x[1] + 117 * x[2]) >> 10;
34 x[0] = x[1] = x[2] = gray;
35 }
222 x->a[0] = x->a[1] = x->a[2] = kc_luminance(x);
223 }
224
36225
37226 typedef struct Gif_Histogram {
38227 Gif_Color *c;
264453 } adaptive_slot;
265454
266455 Gif_Colormap *
267 colormap_median_cut(Gif_Color *hist, int nhist, int adapt_size, int complain)
456 colormap_median_cut(Gif_Color* hist, int nhist, Gt_OutputData* od)
268457 {
458 int adapt_size = od->colormap_size;
269459 adaptive_slot *slots = Gif_NewArray(adaptive_slot, adapt_size);
270460 Gif_Colormap *gfcm = Gif_NewFullColormap(adapt_size, 256);
271461 Gif_Color *adapt = gfcm->col;
277467
278468 if (adapt_size < 2 || adapt_size > 256)
279469 fatal_error("adaptive palette size must be between 2 and 256");
280 if (adapt_size >= nhist && complain)
470 if (adapt_size >= nhist && !od->colormap_fixed)
281471 warning(1, "trivial adaptive palette (only %d colors in source)", nhist);
282472 if (adapt_size >= nhist)
283473 adapt_size = nhist;
381571 for (i = 0; i < nadapt; i++) {
382572 double red_total = 0, green_total = 0, blue_total = 0;
383573 Gif_Color *slice = &hist[ slots[i].first ];
574 kcolor k;
384575 for (j = 0; j < slots[i].count; j++) {
385 red_total += slice[j].gfc_red * slice[j].pixel;
386 green_total += slice[j].gfc_green * slice[j].pixel;
387 blue_total += slice[j].gfc_blue * slice[j].pixel;
388 }
389 adapt[i].gfc_red = (uint8_t)(red_total / slots[i].pixel);
390 adapt[i].gfc_green = (uint8_t)(green_total / slots[i].pixel);
391 adapt[i].gfc_blue = (uint8_t)(blue_total / slots[i].pixel);
576 kc_set8g(&k, slice[j].gfc_red, slice[j].gfc_green, slice[j].gfc_blue);
577 red_total += k.a[0] * (double) slice[j].pixel;
578 green_total += k.a[1] * (double) slice[j].pixel;
579 blue_total += k.a[2] * (double) slice[j].pixel;
580 }
581 k.a[0] = (int) (red_total / slots[i].pixel);
582 k.a[1] = (int) (green_total / slots[i].pixel);
583 k.a[2] = (int) (blue_total / slots[i].pixel);
584 kc_revgamma_transform(&k);
585 adapt[i].gfc_red = (uint8_t) (k.a[0] >> 7);
586 adapt[i].gfc_green = (uint8_t) (k.a[1] >> 7);
587 adapt[i].gfc_blue = (uint8_t) (k.a[2] >> 7);
392588 adapt[i].haspixel = 0;
393589 }
394590
400596
401597
402598 static Gif_Colormap *
403 colormap_diversity(Gif_Color *hist, int nhist, int adapt_size, int complain,
599 colormap_diversity(Gif_Color *hist, int nhist, Gt_OutputData* od,
404600 int blend)
405601 {
406 uint32_t *min_dist = Gif_NewArray(uint32_t, nhist);
602 int adapt_size = od->colormap_size;
603 uint32_t* min_dist = Gif_NewArray(uint32_t, nhist);
604 uint32_t* min_dither_dist = Gif_NewArray(uint32_t, nhist);
407605 int *closest = Gif_NewArray(int, nhist);
606 kcolor* gchist = Gif_NewArray(kcolor, nhist); /* gamma-corrected */
408607 Gif_Colormap *gfcm = Gif_NewFullColormap(adapt_size, 256);
409608 Gif_Color *adapt = gfcm->col;
410609 int nadapt = 0;
416615
417616 if (adapt_size < 2 || adapt_size > 256)
418617 fatal_error("adaptive palette size must be between 2 and 256");
419 if (adapt_size > nhist && complain)
618 if (adapt_size > nhist && !od->colormap_fixed)
420619 warning(1, "trivial adaptive palette (only %d colors in source)", nhist);
421620 if (adapt_size > nhist)
422621 adapt_size = nhist;
444643
445644 /* 1. initialize min_dist and sort the colors in order of popularity. */
446645 for (i = 0; i < nhist; i++)
447 min_dist[i] = 0x7FFFFFFF;
646 min_dist[i] = min_dither_dist[i] = 0xFFFFFFFF;
448647
449648 qsort(hist, nhist, sizeof(Gif_Color), popularity_sort_compare);
649
650 /* 1.5. gamma-correct hist colors */
651 for (i = 0; i < nhist; ++i)
652 kc_set8g(&gchist[i], hist[i].gfc_red, hist[i].gfc_green,
653 hist[i].gfc_blue);
450654
451655 /* 2. choose colors one at a time */
452656 for (nadapt = 0; nadapt < adapt_size; nadapt++) {
461665 /* 2.1a. want most popular unchosen color; we've sorted them on
462666 popularity, so we're done! */
463667
464 } else {
668 } else if (od->dither_type == dither_none) {
465669 /* 2.1b. choose based on diversity from unchosen colors */
466670 for (i = chosen + 1; i != nhist; ++i)
467671 if (min_dist[i] > min_dist[chosen])
468672 chosen = i;
673
674 } else {
675 /* 2.1c. choose based on diversity from unchosen colors, but allow
676 dithered combinations to stand in for colors, particularly early
677 on in the color finding process */
678 #if HAVE_POW
679 /* Weight assigned to dithered combinations drops as we proceed. */
680 double dweight = 0.05 + pow(0.25, 1 + (nadapt - 1) / 3.);
681 #else
682 double dweight = nadapt < 4 ? 0.25 : 0.125;
683 #endif
684 double max_dist = min_dist[chosen] + min_dither_dist[chosen] * dweight;
685 for (i = chosen + 1; i != nhist; ++i)
686 if (min_dist[i] != 0) {
687 double dist = min_dist[i] + min_dither_dist[i] * dweight;
688 if (dist > max_dist) {
689 chosen = i;
690 max_dist = dist;
691 }
692 }
469693 }
470694
471695 /* 2.2. add the color */
472 min_dist[chosen] = 0;
696 min_dist[chosen] = min_dither_dist[chosen] = 0;
473697 closest[chosen] = nadapt;
698 adapt[nadapt] = hist[chosen];
699 adapt[nadapt].pixel = chosen;
700 adapt[nadapt].haspixel = 0;
474701
475702 /* 2.3. adjust the min_dist array */
476703 for (i = 0; i < nhist; ++i)
477704 if (min_dist[i]) {
478 uint32_t dist = rgb_distance(&hist[i], &hist[chosen]);
705 uint32_t dist = kc_distance(&gchist[i], &gchist[chosen]);
479706 if (dist < min_dist[i]) {
480707 min_dist[i] = dist;
481708 closest[i] = nadapt;
482709 }
483710 }
711
712 /* 2.4. also account for dither distances */
713 if (od->dither_type != dither_none && nadapt > 0 && nadapt < 64)
714 for (j = 0; j < nadapt; ++j) {
715 kcolor x = gchist[chosen], *y = &gchist[adapt[j].pixel];
716 /* penalize combinations with large luminance difference */
717 double dL = fabs(kc_luminance(&x) - kc_luminance(y));
718 dL = (dL > 8192 ? dL * 4 / 32767. : 1);
719 /* create combination */
720 for (i = 0; i < 3; ++i)
721 x.a[i] = (x.a[i] + y->a[i]) >> 1;
722 /* track closeness of combination to other colors */
723 for (i = 0; i < nhist; ++i)
724 if (min_dist[i]) {
725 double dist = kc_distance(&gchist[i], &x) * dL;
726 if (dist < min_dither_dist[i])
727 min_dither_dist[i] = (uint32_t) dist;
728 }
729 }
484730 }
485731
486732 /* 3. make the new palette by choosing one color from each slot. */
487 if (!blend) {
488 for (i = 0; i < nadapt; i++) {
489 for (j = 0; j < nhist; j++)
490 if (closest[j] == i && !min_dist[j])
491 match = j;
492 adapt[i] = hist[match];
493 adapt[i].haspixel = 0;
494 }
495
496 } else {
733 if (blend) {
497734 for (i = 0; i < nadapt; i++) {
498735 double red_total = 0, green_total = 0, blue_total = 0;
499736 uint32_t pixel_total = 0, mismatch_pixel_total = 0;
500737 for (j = 0; j < nhist; j++)
501738 if (closest[j] == i) {
502 uint32_t pixel = hist[j].pixel;
503 red_total += hist[j].gfc_red * pixel;
504 green_total += hist[j].gfc_green * pixel;
505 blue_total += hist[j].gfc_blue * pixel;
739 double pixel = hist[j].pixel;
740 red_total += gchist[j].a[0] * pixel;
741 green_total += gchist[j].a[1] * pixel;
742 blue_total += gchist[j].a[2] * pixel;
506743 pixel_total += pixel;
507744 if (min_dist[j])
508745 mismatch_pixel_total += pixel;
516753 else {
517754 /* Favor, by a smallish amount, the color the plain diversity
518755 algorithm would pick. */
519 uint32_t pixel = hist[match].pixel * 2;
520 red_total += hist[match].gfc_red * pixel;
521 green_total += hist[match].gfc_green * pixel;
522 blue_total += hist[match].gfc_blue * pixel;
756 double pixel = hist[match].pixel * 2;
757 kcolor k;
758 red_total += gchist[match].a[0] * pixel;
759 green_total += gchist[match].a[1] * pixel;
760 blue_total += gchist[match].a[2] * pixel;
523761 pixel_total += pixel;
524 adapt[i].gfc_red = (uint8_t)(red_total / pixel_total);
525 adapt[i].gfc_green = (uint8_t)(green_total / pixel_total);
526 adapt[i].gfc_blue = (uint8_t)(blue_total / pixel_total);
762 k.a[0] = (int) (red_total / pixel_total);
763 k.a[1] = (int) (green_total / pixel_total);
764 k.a[2] = (int) (blue_total / pixel_total);
765 kc_revgamma_transform(&k);
766 adapt[i].gfc_red = (uint8_t) (k.a[0] >> 7);
767 adapt[i].gfc_green = (uint8_t) (k.a[1] >> 7);
768 adapt[i].gfc_blue = (uint8_t) (k.a[2] >> 7);
527769 }
528770 adapt[i].haspixel = 0;
529771 }
530772 }
531773
532774 Gif_DeleteArray(min_dist);
775 Gif_DeleteArray(min_dither_dist);
533776 Gif_DeleteArray(closest);
777 Gif_DeleteArray(gchist);
534778 gfcm->ncol = nadapt;
535779 return gfcm;
536780 }
537781
538782
539 Gif_Colormap *
540 colormap_blend_diversity(Gif_Color *hist, int nhist, int adapt_size,
541 int complain)
542 {
543 return colormap_diversity(hist, nhist, adapt_size, complain, 1);
544 }
545
546 Gif_Colormap *
547 colormap_flat_diversity(Gif_Color *hist, int nhist, int adapt_size,
548 int complain)
549 {
550 return colormap_diversity(hist, nhist, adapt_size, complain, 0);
783 Gif_Colormap* colormap_blend_diversity(Gif_Color* hist, int nhist,
784 Gt_OutputData* od) {
785 return colormap_diversity(hist, nhist, od, 1);
786 }
787
788 Gif_Colormap* colormap_flat_diversity(Gif_Color* hist, int nhist,
789 Gt_OutputData* od) {
790 return colormap_diversity(hist, nhist, od, 0);
551791 }
552792
553793
556796 **/
557797
558798 typedef struct kd3_item {
559 int a[3];
799 kcolor k;
560800 int index;
561801 } kd3_item;
562802
565805 int offset;
566806 } kd3_treepos;
567807
568 typedef struct kd3_tree {
808 struct kd3_tree {
569809 kd3_treepos* tree;
570810 int ntree;
571811 int disabled;
573813 int nitems;
574814 int items_cap;
575815 int maxdepth;
576 unsigned (*distance)(const int[3], const int[3]);
577 void (*transform)(int[3]);
816 void (*transform)(kcolor*);
578817 unsigned* xradius;
579 } kd3_tree;
580
581 void kd3_init(kd3_tree* kd3, unsigned (*distance)(const int[3], const int[3]),
582 void (*transform)(int[3])) {
818 };
819
820 void kd3_init(kd3_tree* kd3, void (*transform)(kcolor*)) {
583821 kd3->tree = NULL;
584822 kd3->items = Gif_NewArray(kd3_item, 256);
585823 kd3->nitems = 0;
586824 kd3->items_cap = 256;
587 kd3->distance = distance;
588825 kd3->transform = transform;
589826 kd3->xradius = NULL;
590827 kd3->disabled = -1;
596833 Gif_DeleteArray(kd3->xradius);
597834 }
598835
599 void kd3_add(kd3_tree* kd3, int a0, int a1, int a2) {
600 assert(!kd3->tree);
836 void kd3_add_transformed(kd3_tree* kd3, const kcolor* k) {
601837 if (kd3->nitems == kd3->items_cap) {
602838 kd3->items_cap *= 2;
603839 Gif_ReArray(kd3->items, kd3_item, kd3->items_cap);
604840 }
605 kd3->items[kd3->nitems].a[0] = a0;
606 kd3->items[kd3->nitems].a[1] = a1;
607 kd3->items[kd3->nitems].a[2] = a2;
608 if (kd3->transform)
609 kd3->transform(kd3->items[kd3->nitems].a);
841 kd3->items[kd3->nitems].k = *k;
610842 kd3->items[kd3->nitems].index = kd3->nitems;
611843 ++kd3->nitems;
612844 }
613845
614 void kd3_add_8to15(kd3_tree* kd3, int a0, int a1, int a2) {
615 kd3_add(kd3, (a0 << 7) | (a0 >> 1), (a1 << 7) | (a1 >> 1),
616 (a2 << 7) | (a2 >> 1));
846 void kd3_add8g(kd3_tree* kd3, int a0, int a1, int a2) {
847 kcolor k;
848 kc_set8g(&k, a0, a1, a2);
849 if (kd3->transform)
850 kd3->transform(&k);
851 kd3_add_transformed(kd3, &k);
617852 }
618853
619854 static int kd3_item_compar_0(const void* a, const void* b) {
620855 const kd3_item* aa = (const kd3_item*) a, *bb = (const kd3_item*) b;
621 return aa->a[0] - bb->a[0];
856 return aa->k.a[0] - bb->k.a[0];
622857 }
623858
624859 static int kd3_item_compar_1(const void* a, const void* b) {
625860 const kd3_item* aa = (const kd3_item*) a, *bb = (const kd3_item*) b;
626 return aa->a[1] - bb->a[1];
861 return aa->k.a[1] - bb->k.a[1];
627862 }
628863
629864 static int kd3_item_compar_2(const void* a, const void* b) {
630865 const kd3_item* aa = (const kd3_item*) a, *bb = (const kd3_item*) b;
631 return aa->a[2] - bb->a[2];
866 return aa->k.a[2] - bb->k.a[2];
632867 }
633868
634869 static int (*kd3_item_compars[])(const void*, const void*) = {
637872
638873 static int kd3_build_range(kd3_tree* kd3, kd3_item* items,
639874 int l, int r, int n, int depth) {
640 int m, aindex = depth % 3;
875 int m, nl, nr, aindex = depth % 3;
641876 if (depth > kd3->maxdepth)
642877 kd3->maxdepth = depth;
643878 while (n >= kd3->ntree) {
651886 }
652887
653888 qsort(&items[l], r - l, sizeof(kd3_item), kd3_item_compars[aindex]);
889
890 /* pick pivot: a color component to split */
654891 m = l + ((r - l) >> 1);
655 while (m > l && items[m].a[aindex] == items[m-1].a[aindex])
892 while (m > l && items[m].k.a[aindex] == items[m-1].k.a[aindex])
656893 --m;
894 if (m == l) { /* don't split entirely to the right (infinite loop) */
895 m = l + ((r - l) >> 1);
896 while (m < r && items[m].k.a[aindex] == items[m-1].k.a[aindex])
897 ++m;
898 }
657899 if (m == l)
658 kd3->tree[n].pivot = items[m].a[aindex];
900 kd3->tree[n].pivot = items[m].k.a[aindex];
659901 else
660 kd3->tree[n].pivot = items[m-1].a[aindex]
661 + ((items[m].a[aindex] - items[m-1].a[aindex]) >> 1);
662 int nl = kd3_build_range(kd3, items, l, m, n+1, depth+1);
902 kd3->tree[n].pivot = items[m-1].k.a[aindex]
903 + ((items[m].k.a[aindex] - items[m-1].k.a[aindex]) >> 1);
904
905 /* recurse */
906 nl = kd3_build_range(kd3, items, l, m, n+1, depth+1);
663907 kd3->tree[n].offset = 1+nl;
664 int nr = kd3_build_range(kd3, items, m, r, n+1+nl, depth+1);
908 nr = kd3_build_range(kd3, items, m, r, n+1+nl, depth+1);
665909 return 1+nl+nr;
666910 }
667911
668912 static int kd3_item_all_compar(const void* a, const void* b) {
669913 const kd3_item* aa = (const kd3_item*) a, *bb = (const kd3_item*) b;
670 if (aa->a[0] - bb->a[0])
671 return aa->a[0] - bb->a[0];
672 else if (aa->a[1] - bb->a[1])
673 return aa->a[1] - bb->a[1];
914 if (aa->k.a[0] - bb->k.a[0])
915 return aa->k.a[0] - bb->k.a[0];
916 else if (aa->k.a[1] - bb->k.a[1])
917 return aa->k.a[1] - bb->k.a[1];
674918 else
675 return aa->a[2] - bb->a[2];
676 }
677
678 void kd3_print(kd3_tree* kd3, int depth, kd3_treepos* p, int* a, int* b) {
919 return aa->k.a[2] - bb->k.a[2];
920 }
921
922 #if 0
923 static void kd3_print_depth(kd3_tree* kd3, int depth, kd3_treepos* p,
924 int* a, int* b) {
679925 int i;
680 char x[10][6];
926 char x[6][10];
681927 for (i = 0; i != 3; ++i) {
682 if (a[i] == 0x80000000)
928 if (a[i] == INT_MIN)
683929 sprintf(x[2*i], "*");
684930 else
685931 sprintf(x[2*i], "%d", a[i]);
686 if (b[i] == 0x7FFFFFFF)
932 if (b[i] == INT_MAX)
687933 sprintf(x[2*i+1], "*");
688934 else
689935 sprintf(x[2*i+1], "%d", b[i]);
692938 x[0], x[1], x[2], x[3], x[4], x[5]);
693939 if (p->offset < 0) {
694940 if (p->pivot >= 0) {
695 assert(kd3->items[p->pivot].a[0] >= a[0]);
696 assert(kd3->items[p->pivot].a[1] >= a[1]);
697 assert(kd3->items[p->pivot].a[2] >= a[2]);
698 assert(kd3->items[p->pivot].a[0] < b[0]);
699 assert(kd3->items[p->pivot].a[1] < b[1]);
700 assert(kd3->items[p->pivot].a[2] < b[2]);
701 printf(" ** @%d: <%d,%d,%d>\n", p->pivot, kd3->items[p->pivot].a[0], kd3->items[p->pivot].a[1], kd3->items[p->pivot].a[2]);
941 assert(kd3->items[p->pivot].k.a[0] >= a[0]);
942 assert(kd3->items[p->pivot].k.a[1] >= a[1]);
943 assert(kd3->items[p->pivot].k.a[2] >= a[2]);
944 assert(kd3->items[p->pivot].k.a[0] < b[0]);
945 assert(kd3->items[p->pivot].k.a[1] < b[1]);
946 assert(kd3->items[p->pivot].k.a[2] < b[2]);
947 printf(" ** @%d: <%d,%d,%d>\n", p->pivot, kd3->items[p->pivot].k.a[0], kd3->items[p->pivot].k.a[1], kd3->items[p->pivot].k.a[2]);
702948 }
703949 } else {
704 int aindex = depth % 3;
950 int aindex = depth % 3, x[3];
705951 assert(p->pivot >= a[aindex]);
706952 assert(p->pivot < b[aindex]);
707953 printf((aindex == 0 ? " | <%d,_,_>\n" :
708954 aindex == 1 ? " | <_,%d,_>\n" : " | <_,_,%d>\n"), p->pivot);
709 int x[3];
710955 memcpy(x, b, sizeof(int) * 3);
711956 x[aindex] = p->pivot;
712 kd3_print(kd3, depth + 1, p + 1, a, x);
957 kd3_print_depth(kd3, depth + 1, p + 1, a, x);
713958 memcpy(x, a, sizeof(int) * 3);
714959 x[aindex] = p->pivot;
715 kd3_print(kd3, depth + 1, p + p->offset, x, b);
716 }
717 }
718
719 void kd3_build(kd3_tree* kd3) {
720 kd3_item* items;
721 int i, j, delta;
722 assert(!kd3->tree);
723
724 // create xradius
960 kd3_print_depth(kd3, depth + 1, p + p->offset, x, b);
961 }
962 }
963
964 static void kd3_print(kd3_tree* kd3) {
965 int a[3], b[3];
966 a[0] = a[1] = a[2] = INT_MIN;
967 b[0] = b[1] = b[2] = INT_MAX;
968 kd3_print_depth(kd3, 0, kd3->tree, a, b);
969 }
970 #endif
971
972 void kd3_build_xradius(kd3_tree* kd3) {
973 int i, j;
974 /* create xradius */
975 if (kd3->xradius)
976 return;
725977 kd3->xradius = Gif_NewArray(unsigned, kd3->nitems);
726978 for (i = 0; i != kd3->nitems; ++i)
727979 kd3->xradius[i] = (unsigned) -1;
728980 for (i = 0; i != kd3->nitems; ++i)
729981 for (j = i + 1; j != kd3->nitems; ++j) {
730 unsigned dist = kd3->distance(kd3->items[i].a, kd3->items[j].a);
982 unsigned dist = kc_distance(&kd3->items[i].k, &kd3->items[j].k);
731983 unsigned radius = dist / 4;
732984 if (radius < kd3->xradius[i])
733985 kd3->xradius[i] = radius;
734986 if (radius < kd3->xradius[j])
735987 kd3->xradius[j] = radius;
736988 }
737
738 // create tree
989 }
990
991 void kd3_build(kd3_tree* kd3) {
992 kd3_item* items;
993 int i, delta;
994 assert(!kd3->tree);
995
996 /* create tree */
739997 kd3->tree = Gif_NewArray(kd3_treepos, 256);
740998 kd3->ntree = 256;
741999 kd3->maxdepth = 0;
7421000
743 // create copy of items; remove duplicates
1001 /* create copy of items; remove duplicates */
7441002 items = Gif_NewArray(kd3_item, kd3->nitems);
7451003 memcpy(items, kd3->items, sizeof(kd3_item) * kd3->nitems);
7461004 qsort(items, kd3->nitems, sizeof(kd3_item), kd3_item_all_compar);
7471005 for (i = 0, delta = 1; i != kd3->nitems - delta; ++i)
748 if (items[i].a[0] == items[i+delta].a[0]
749 && items[i].a[1] == items[i+delta].a[1]
750 && items[i].a[2] == items[i+delta].a[2])
1006 if (items[i].k.a[0] == items[i+delta].k.a[0]
1007 && items[i].k.a[1] == items[i+delta].k.a[1]
1008 && items[i].k.a[2] == items[i+delta].k.a[2])
7511009 ++delta, --i;
7521010 else if (delta > 1)
7531011 items[i+1] = items[i+delta];
7591017 }
7601018
7611019 void kd3_disable(kd3_tree* kd3, int i) {
762 assert(kd3->disabled < 0);
763 kd3->disabled = i;
1020 assert((unsigned) i < (unsigned) kd3->nitems);
1021 if (kd3->items[i].index >= 0) {
1022 kd3->items[i].index = kd3->disabled;
1023 kd3->disabled = -i - 2;
1024 }
1025 }
1026
1027 void kd3_enable(kd3_tree* kd3, int i) {
1028 int* pprev = &kd3->disabled;
1029 assert((unsigned) i < (unsigned) kd3->nitems);
1030 while (*pprev != -1 && *pprev != -i - 2)
1031 pprev = &kd3->items[-*pprev - 2].index;
1032 if (*pprev == -i - 2) {
1033 *pprev = kd3->items[i].index;
1034 kd3->items[i].index = i;
1035 }
7641036 }
7651037
7661038 void kd3_enable_all(kd3_tree* kd3) {
767 kd3->disabled = -1;
768 }
769
770 int kd3_closest_transformed(const kd3_tree* kd3, const int a[3]) {
771 assert(kd3->tree);
1039 while (kd3->disabled != -1) {
1040 int i = -kd3->disabled - 2;
1041 kd3->disabled = kd3->items[i].index;
1042 kd3->items[i].index = i;
1043 }
1044 }
1045
1046 int kd3_closest_transformed(const kd3_tree* kd3, const kcolor* k) {
7721047 const kd3_treepos* stack[32];
7731048 uint8_t state[32];
7741049 int stackpos = 0;
7751050 int result = -1;
7761051 unsigned mindist = (unsigned) -1;
1052 assert(kd3->tree);
7771053 stack[0] = kd3->tree;
7781054 state[0] = 0;
7791055
7801056 while (stackpos >= 0) {
1057 const kd3_treepos* p;
7811058 assert(stackpos < 32);
782 const kd3_treepos* p = stack[stackpos];
1059 p = stack[stackpos];
7831060
7841061 if (p->offset < 0) {
785 if (p->pivot >= 0 && kd3->disabled != p->pivot) {
786 unsigned dist = kd3->distance(kd3->items[p->pivot].a, a);
1062 if (p->pivot >= 0 && kd3->items[p->pivot].index >= 0) {
1063 unsigned dist = kc_distance(&kd3->items[p->pivot].k, k);
7871064 if (dist < mindist) {
7881065 mindist = dist;
7891066 result = p->pivot;
7921069 if (--stackpos >= 0)
7931070 ++state[stackpos];
7941071 } else if (state[stackpos] == 0) {
795 if (a[stackpos % 3] < p->pivot)
1072 if (k->a[stackpos % 3] < p->pivot)
7961073 stack[stackpos + 1] = p + 1;
7971074 else
7981075 stack[stackpos + 1] = p + p->offset;
7991076 ++stackpos;
8001077 state[stackpos] = 0;
8011078 } else {
802 int delta = a[stackpos % 3] - p->pivot;
1079 int delta = k->a[stackpos % 3] - p->pivot;
8031080 if (state[stackpos] == 1
8041081 && (unsigned) (delta * delta) < mindist) {
8051082 if (delta < 0)
8161093 return result;
8171094 }
8181095
819 int kd3_closest(const kd3_tree* kd3, int a0, int a1, int a2) {
820 int a[3] = {a0, a1, a2};
1096 int kd3_closest(const kd3_tree* kd3, kcolor k) {
8211097 if (kd3->transform)
822 kd3->transform(a);
823 return kd3_closest_transformed(kd3, a);
824 }
825
826 int kd3_closest_8to15(const kd3_tree* kd3, int a0, int a1, int a2) {
827 return kd3_closest(kd3, (a0 << 7) | (a0 >> 1), (a1 << 7) | (a1 >> 1),
828 (a2 << 7) | (a2 >> 1));
1098 kd3->transform(&k);
1099 return kd3_closest_transformed(kd3, &k);
1100 }
1101
1102 int kd3_closest8(const kd3_tree* kd3, int a0, int a1, int a2) {
1103 kcolor k;
1104 kc_set8g(&k, a0, a1, a2);
1105 if (kd3->transform)
1106 kd3->transform(&k);
1107 return kd3_closest_transformed(kd3, &k);
8291108 }
8301109
8311110
8421121
8431122 /* find closest colors in new colormap */
8441123 for (i = 0; i < ncol; i++) {
845 map[i] = col[i].pixel = kd3_closest_8to15(kd3, col[i].gfc_red, col[i].gfc_green, col[i].gfc_blue);
1124 map[i] = col[i].pixel = kd3_closest8(kd3, col[i].gfc_red, col[i].gfc_green, col[i].gfc_blue);
8461125 col[i].haspixel = 1;
8471126 }
8481127
8641143 #define DITHER_ITEM2ERR (1<<(DITHER_SHIFT-7))
8651144 #define N_RANDOM_VALUES 512
8661145
867 typedef struct color_erritem {
868 int32_t a[3];
869 } color_erritem;
870
8711146 void
8721147 colormap_image_floyd_steinberg(Gif_Image *gfi, uint8_t *all_new_data,
8731148 Gif_Colormap *old_cm, kd3_tree* kd3,
8791154 int dither_direction = 0;
8801155 int transparent = gfi->transparent;
8811156 int i, j, k;
882 color_erritem *err, *err1;
1157 kcolor *err, *err1;
8831158
8841159 /* Initialize distances */
8851160 for (i = 0; i < old_cm->ncol; ++i) {
8861161 Gif_Color* c = &old_cm->col[i];
887 c->pixel = kd3_closest_8to15(kd3, c->gfc_red, c->gfc_green, c->gfc_blue);
1162 c->pixel = kd3_closest8(kd3, c->gfc_red, c->gfc_green, c->gfc_blue);
8881163 c->haspixel = 1;
8891164 }
8901165
8931168
8941169 /* Initialize Floyd-Steinberg error vectors to small random values, so we
8951170 don't get artifacts on the top row */
896 err = Gif_NewArray(color_erritem, width + 2);
897 err1 = Gif_NewArray(color_erritem, width + 2);
1171 err = Gif_NewArray(kcolor, width + 2);
1172 err1 = Gif_NewArray(kcolor, width + 2);
8981173 /* Use the same random values on each call in an attempt to minimize
8991174 "jumping dithering" effects on animations */
9001175 if (!random_values) {
9091184 }
9101185 /* err1 initialized below */
9111186
1187 kd3_build_xradius(kd3);
1188
9121189 /* Do the image! */
9131190 for (j = 0; j < gfi->height; j++) {
9141191 int d0, d1, d2, d3; /* used for error diffusion */
9311208 /* Do a single row */
9321209 while (x >= 0 && x < width) {
9331210 int e;
934 color_erritem use, usexf;
1211 kcolor use;
9351212
9361213 /* the transparent color never gets adjusted */
9371214 if (*data == transparent)
9381215 goto next;
9391216
940 /* use Floyd-Steinberg errors to adjust actual color */
941 for (k = 0; k < 3; ++k) {
942 use.a[k] = old_cm->col[*data].gfc_array[k];
943 use.a[k] = (use.a[k] << 7) | (use.a[k] >> 1);
1217 /* find desired new color */
1218 kc_set8g(&use, old_cm->col[*data].gfc_red, old_cm->col[*data].gfc_green,
1219 old_cm->col[*data].gfc_blue);
1220 if (kd3->transform)
1221 kd3->transform(&use);
1222 /* use Floyd-Steinberg errors to adjust */
1223 for (k = 0; k < 3; ++k)
9441224 use.a[k] += (err[x+1].a[k] & ~(DITHER_ITEM2ERR-1)) / DITHER_ITEM2ERR;
945 use.a[k] = max(use.a[k], 0);
946 use.a[k] = min(use.a[k], (255 << 7) | (255 >> 1));
947 }
948
949 usexf = use;
950 if (kd3->transform)
951 kd3->transform(usexf.a);
1225 kc_clamp(&use);
1226
9521227 e = old_cm->col[*data].pixel;
953 if (kd3->distance(kd3->items[e].a, usexf.a) < kd3->xradius[e])
1228 if (kc_distance(&kd3->items[e].k, &use) < kd3->xradius[e])
9541229 *new_data = e;
9551230 else
956 *new_data = kd3_closest_transformed(kd3, usexf.a);
1231 *new_data = kd3_closest_transformed(kd3, &use);
9571232 histogram[*new_data]++;
9581233
9591234 /* calculate and propagate the error between desired and selected color.
9611236 image artifacts caused by error accumulation (the fact that the
9621237 error terms might not sum to the error). */
9631238 for (k = 0; k < 3; ++k) {
964 e = (use.a[k] - kd3->items[*new_data].a[k]) * DITHER_ITEM2ERR;
1239 e = (use.a[k] - kd3->items[*new_data].k.a[k]) * DITHER_ITEM2ERR;
9651240 if (e) {
9661241 err [x+d0].a[k] += ((e * 7) & ~15) / 16;
9671242 err1[x+d1].a[k] += ((e * 3) & ~15) / 16;
9801255
9811256 /* change dithering directions */
9821257 {
983 color_erritem *temp = err1;
1258 kcolor *temp = err1;
9841259 err1 = err;
9851260 err = temp;
9861261 dither_direction = !dither_direction;
9931268 }
9941269
9951270
996 /* return value 1 means run the image_changer again */
1271 typedef struct odselect_planitem {
1272 uint8_t plan;
1273 uint16_t frac;
1274 } odselect_planitem;
1275
1276 static int* ordered_dither_lum;
1277
1278 static void plan_from_cplan(uint8_t* plan, int nplan,
1279 const odselect_planitem* cp, int ncp, int whole) {
1280 int i, cfrac_subt = 0, planpos = 0, end_planpos;
1281 for (i = 0; i != ncp; ++i) {
1282 cfrac_subt += cp[i].frac;
1283 end_planpos = cfrac_subt * nplan / whole;
1284 while (planpos != end_planpos)
1285 plan[planpos++] = cp[i].plan;
1286 }
1287 assert(planpos == nplan);
1288 }
1289
1290 static int ordered_dither_plan_compare(const void* xa, const void* xb) {
1291 const uint8_t* a = (const uint8_t*) xa;
1292 const uint8_t* b = (const uint8_t*) xb;
1293 if (ordered_dither_lum[*a] != ordered_dither_lum[*b])
1294 return ordered_dither_lum[*a] - ordered_dither_lum[*b];
1295 else
1296 return *a - *b;
1297 }
1298
1299 static int kc_line_closest(const kcolor* p0, const kcolor* p1,
1300 const kcolor* ref, double* t, unsigned* dist) {
1301 kcolor p01, p0ref;
1302 unsigned den;
1303 int d;
1304 for (d = 0; d != 3; ++d) {
1305 p01.a[d] = p1->a[d] - p0->a[d];
1306 p0ref.a[d] = ref->a[d] - p0->a[d];
1307 }
1308 den = (unsigned)
1309 (p01.a[0]*p01.a[0] + p01.a[1]*p01.a[1] + p01.a[2]*p01.a[2]);
1310 if (den == 0)
1311 return 0;
1312 /* NB: We've run out of bits of precision. We can calculate the
1313 denominator in unsigned arithmetic, but the numerator might
1314 be negative, or it might be so large that it is unsigned.
1315 Calculate the numerator as a double. */
1316 *t = ((double) p01.a[0]*p0ref.a[0] + p01.a[1]*p0ref.a[1]
1317 + p01.a[2]*p0ref.a[2]) / den;
1318 if (*t < 0 || *t > 1)
1319 return 0;
1320 for (d = 0; d != 3; ++d)
1321 p01.a[d] = (int) (p01.a[d] * *t) + p0->a[d];
1322 *dist = kc_distance(&p01, ref);
1323 return 1;
1324 }
1325
1326 static int kc_plane_closest(const kcolor* p0, const kcolor* p1,
1327 const kcolor* p2, const kcolor* ref,
1328 double* t, unsigned* dist) {
1329 kcolor p0ref, p01, p02;
1330 double n[3], pvec[3], det, qvec[3], u, v;
1331 int d;
1332
1333 /* Calculate the non-unit normal of the plane determined by the input
1334 colors (p0-p2) */
1335 for (d = 0; d != 3; ++d) {
1336 p0ref.a[d] = ref->a[d] - p0->a[d];
1337 p01.a[d] = p1->a[d] - p0->a[d];
1338 p02.a[d] = p2->a[d] - p0->a[d];
1339 }
1340 n[0] = p01.a[1]*p02.a[2] - p01.a[2]*p02.a[1];
1341 n[1] = p01.a[2]*p02.a[0] - p01.a[0]*p02.a[2];
1342 n[2] = p01.a[0]*p02.a[1] - p01.a[1]*p02.a[0];
1343
1344 /* Moeller-Trumbore ray tracing algorithm: trace a ray from `ref` along
1345 normal `n`; convert to barycentric coordinates to see if the ray
1346 intersects with the triangle. */
1347 pvec[0] = n[1]*p02.a[2] - n[2]*p02.a[1];
1348 pvec[1] = n[2]*p02.a[0] - n[0]*p02.a[2];
1349 pvec[2] = n[0]*p02.a[1] - n[1]*p02.a[0];
1350
1351 det = pvec[0]*p01.a[0] + pvec[1]*p01.a[1] + pvec[2]*p01.a[2];
1352 if (det > 0.0001 && det < 0.0001)
1353 return 0;
1354 det = 1 / det;
1355
1356 u = (p0ref.a[0]*pvec[0] + p0ref.a[1]*pvec[1] + p0ref.a[2]*pvec[2]) * det;
1357 if (u < 0 || u > 1)
1358 return 0;
1359
1360 qvec[0] = p0ref.a[1]*p01.a[2] - p0ref.a[2]*p01.a[1];
1361 qvec[1] = p0ref.a[2]*p01.a[0] - p0ref.a[0]*p01.a[2];
1362 qvec[2] = p0ref.a[0]*p01.a[1] - p0ref.a[1]*p01.a[0];
1363
1364 v = (n[0]*qvec[0] + n[1]*qvec[1] + n[2]*qvec[2]) * det;
1365 if (v < 0 || v > 1 || u + v > 1)
1366 return 0;
1367
1368 /* Now we know at there is a point in the triangle that is closer to
1369 `ref` than any point along its edges. Return the barycentric
1370 coordinates for that point and the distance to that point. */
1371 t[0] = u;
1372 t[1] = v;
1373 v = (p02.a[0]*qvec[0] + p02.a[1]*qvec[1] + p02.a[2]*qvec[2]) * det;
1374 *dist = (unsigned) (v * v * (n[0]*n[0] + n[1]*n[1] + n[2]*n[2]) + 0.5);
1375 return 1;
1376 }
1377
1378 static void limit_ordered_dither_plan(uint8_t* plan, int nplan, int nc,
1379 const kcolor* want, kd3_tree* kd3) {
1380 unsigned mindist, dist;
1381 int ncp = 0, nbestcp = 0, i, j, k;
1382 double t[2];
1383 odselect_planitem cp[256], bestcp[16];
1384 nc = nc <= 16 ? nc : 16;
1385
1386 /* sort colors */
1387 cp[0].plan = plan[0];
1388 cp[0].frac = 1;
1389 for (ncp = i = 1; i != nplan; ++i)
1390 if (plan[i - 1] == plan[i])
1391 ++cp[ncp - 1].frac;
1392 else {
1393 cp[ncp].plan = plan[i];
1394 cp[ncp].frac = 1;
1395 ++ncp;
1396 }
1397
1398 /* calculate plan */
1399 mindist = (unsigned) -1;
1400 for (i = 0; i != ncp; ++i) {
1401 /* check for closest single color */
1402 dist = kc_distance(&kd3->items[cp[i].plan].k, want);
1403 if (dist < mindist) {
1404 bestcp[0].plan = cp[i].plan;
1405 bestcp[0].frac = KC_WHOLE;
1406 nbestcp = 1;
1407 mindist = dist;
1408 }
1409
1410 for (j = i + 1; nc >= 2 && j < ncp; ++j) {
1411 /* check for closest blend of two colors */
1412 if (kc_line_closest(&kd3->items[cp[i].plan].k,
1413 &kd3->items[cp[j].plan].k,
1414 want, &t[0], &dist)
1415 && dist < mindist) {
1416 bestcp[0].plan = cp[i].plan;
1417 bestcp[1].plan = cp[j].plan;
1418 bestcp[1].frac = (int) (KC_WHOLE * t[0]);
1419 bestcp[0].frac = KC_WHOLE - bestcp[1].frac;
1420 nbestcp = 2;
1421 mindist = dist;
1422 }
1423
1424 for (k = j + 1; nc >= 3 && k < ncp; ++k)
1425 /* check for closest blend of three colors */
1426 if (kc_plane_closest(&kd3->items[cp[i].plan].k,
1427 &kd3->items[cp[j].plan].k,
1428 &kd3->items[cp[k].plan].k,
1429 want, &t[0], &dist)
1430 && dist < mindist) {
1431 bestcp[0].plan = cp[i].plan;
1432 bestcp[1].plan = cp[j].plan;
1433 bestcp[1].frac = (int) (KC_WHOLE * t[0]);
1434 bestcp[2].plan = cp[k].plan;
1435 bestcp[2].frac = (int) (KC_WHOLE * t[1]);
1436 bestcp[0].frac = KC_WHOLE - bestcp[1].frac - bestcp[2].frac;
1437 nbestcp = 3;
1438 mindist = dist;
1439 }
1440 }
1441 }
1442
1443 plan_from_cplan(plan, nplan, bestcp, nbestcp, KC_WHOLE);
1444 }
1445
1446 static void set_ordered_dither_plan(uint8_t* plan, int nplan, int nc,
1447 Gif_Color* gfc, kd3_tree* kd3) {
1448 kcolor want, cur, err;
1449 int i, d;
1450
1451 kc_set8g(&want, gfc->gfc_red, gfc->gfc_green, gfc->gfc_blue);
1452 if (kd3->transform)
1453 kd3->transform(&want);
1454
1455 kc_clear(&err);
1456 for (i = 0; i != nplan; ++i) {
1457 for (d = 0; d != 3; ++d)
1458 cur.a[d] = want.a[d] + err.a[d];
1459 kc_clamp(&cur);
1460 plan[i] = kd3_closest_transformed(kd3, &cur);
1461 for (d = 0; d != 3; ++d)
1462 err.a[d] += want.a[d] - kd3->items[plan[i]].k.a[d];
1463 }
1464
1465 qsort(plan, nplan, 1, ordered_dither_plan_compare);
1466
1467 if (nc < nplan && plan[0] != plan[nplan-1]) {
1468 int ncp = 1;
1469 for (i = 1; i != nplan; ++i)
1470 ncp += plan[i-1] != plan[i];
1471 if (ncp > nc)
1472 limit_ordered_dither_plan(plan, nplan, nc, &want, kd3);
1473 }
1474
1475 gfc->haspixel = 1;
1476 }
1477
1478 static void pow2_ordered_dither(Gif_Image* gfi, uint8_t* all_new_data,
1479 Gif_Colormap* old_cm, kd3_tree* kd3,
1480 uint32_t* histogram, const uint8_t* matrix,
1481 uint8_t* plan) {
1482 int mws, nplans, i, x, y;
1483 for (mws = 0; (1 << mws) != matrix[0]; ++mws)
1484 /* nada */;
1485 for (nplans = 0; (1 << nplans) != matrix[2]; ++nplans)
1486 /* nada */;
1487
1488 for (y = 0; y != gfi->height; ++y) {
1489 uint8_t *data, *new_data, *thisplan;
1490 data = gfi->img[y];
1491 new_data = all_new_data + y * gfi->width;
1492
1493 for (x = 0; x != gfi->width; ++x)
1494 /* the transparent color never gets adjusted */
1495 if (data[x] != gfi->transparent) {
1496 thisplan = &plan[data[x] << nplans];
1497 if (!old_cm->col[data[x]].haspixel)
1498 set_ordered_dither_plan(thisplan, 1 << nplans, matrix[3],
1499 &old_cm->col[data[x]], kd3);
1500 i = matrix[4 + ((x + gfi->left) & (matrix[0] - 1))
1501 + (((y + gfi->top) & (matrix[1] - 1)) << mws)];
1502 new_data[x] = thisplan[i];
1503 histogram[new_data[x]]++;
1504 }
1505 }
1506 }
1507
1508 static void colormap_image_ordered(Gif_Image* gfi, uint8_t* all_new_data,
1509 Gif_Colormap* old_cm, kd3_tree* kd3,
1510 uint32_t* histogram,
1511 const uint8_t* matrix) {
1512 int mw = matrix[0], mh = matrix[1], nplan = matrix[2];
1513 uint8_t* plan = Gif_NewArray(uint8_t, nplan * old_cm->ncol);
1514 int i, x, y;
1515
1516 /* Written with reference to Joel Ylilouma's versions. */
1517
1518 /* Initialize colors */
1519 for (i = 0; i != old_cm->ncol; ++i)
1520 old_cm->col[i].haspixel = 0;
1521
1522 /* Initialize luminances, create luminance sorter */
1523 ordered_dither_lum = Gif_NewArray(int, kd3->nitems);
1524 for (i = 0; i != kd3->nitems; ++i)
1525 ordered_dither_lum[i] = kc_luminance(&kd3->items[i].k);
1526
1527 /* Do the image! */
1528 if ((mw & (mw - 1)) == 0 && (mh & (mh - 1)) == 0
1529 && (nplan & (nplan - 1)) == 0)
1530 pow2_ordered_dither(gfi, all_new_data, old_cm, kd3, histogram,
1531 matrix, plan);
1532 else
1533 for (y = 0; y != gfi->height; ++y) {
1534 uint8_t *data, *new_data, *thisplan;
1535 data = gfi->img[y];
1536 new_data = all_new_data + y * gfi->width;
1537
1538 for (x = 0; x != gfi->width; ++x)
1539 /* the transparent color never gets adjusted */
1540 if (data[x] != gfi->transparent) {
1541 thisplan = &plan[nplan * data[x]];
1542 if (!old_cm->col[data[x]].haspixel)
1543 set_ordered_dither_plan(thisplan, nplan, matrix[3],
1544 &old_cm->col[data[x]], kd3);
1545 i = matrix[4 + (x + gfi->left) % mw
1546 + ((y + gfi->top) % mh) * mw];
1547 new_data[x] = thisplan[i];
1548 histogram[new_data[x]]++;
1549 }
1550 }
1551
1552 /* delete temporary storage */
1553 Gif_DeleteArray(ordered_dither_lum);
1554 Gif_DeleteArray(plan);
1555 }
1556
1557
1558 static void dither(Gif_Image* gfi, uint8_t* new_data, Gif_Colormap* old_cm,
1559 kd3_tree* kd3, uint32_t* histogram, Gt_OutputData* od) {
1560 if (od->dither_type == dither_default
1561 || od->dither_type == dither_floyd_steinberg)
1562 colormap_image_floyd_steinberg(gfi, new_data, old_cm, kd3, histogram);
1563 else if (od->dither_type == dither_ordered
1564 || od->dither_type == dither_ordered_new)
1565 colormap_image_ordered(gfi, new_data, old_cm, kd3, histogram,
1566 od->dither_data);
1567 else
1568 colormap_image_posterize(gfi, new_data, old_cm, kd3, histogram);
1569 }
1570
1571 /* return value 1 means run the dither again */
9971572 static int
9981573 try_assign_transparency(Gif_Image *gfi, Gif_Colormap *old_cm, uint8_t *new_data,
9991574 Gif_Colormap *new_cm, int *new_ncol,
10581633 }
10591634
10601635 void
1061 colormap_stream(Gif_Stream *gfs, Gif_Colormap *new_cm,
1062 colormap_image_func image_changer)
1636 colormap_stream(Gif_Stream* gfs, Gif_Colormap* new_cm, Gt_OutputData* od)
10631637 {
10641638 kd3_tree kd3;
10651639 int background_transparent = gfs->images[0]->transparent >= 0;
10891663 || new_col[j].gfc_red != new_col[j].gfc_blue)
10901664 new_gray = 0;
10911665 if (new_gray)
1092 kd3_init(&kd3, kd3_distance, kd3_luminance_transform);
1666 kd3_init(&kd3, kc_luminance_transform);
10931667 else
1094 kd3_init(&kd3, kd3_distance, NULL);
1668 kd3_init(&kd3, NULL);
10951669 for (j = 0; j < new_cm->ncol; ++j)
1096 kd3_add_8to15(&kd3, new_col[j].gfc_red, new_col[j].gfc_green, new_col[j].gfc_blue);
1670 kd3_add8g(&kd3, new_col[j].gfc_red, new_col[j].gfc_green,
1671 new_col[j].gfc_blue);
10971672 kd3_build(&kd3);
10981673
10991674 for (imagei = 0; imagei < gfs->nimages; imagei++) {
11151690 do {
11161691 for (j = 0; j < 256; j++)
11171692 histogram[j] = 0;
1118 image_changer(gfi, new_data, gfcm, &kd3, histogram);
1693 dither(gfi, new_data, gfcm, &kd3, histogram, od);
11191694 } while (try_assign_transparency(gfi, gfcm, new_data, new_cm, &new_ncol,
11201695 &kd3, histogram));
11211696
11601735 gfs->background = gfs->images[0]->transparent;
11611736 else if (gfs->global && gfs->background < gfs->global->ncol) {
11621737 Gif_Color *c = &gfs->global->col[gfs->background];
1163 gfs->background = kd3_closest_8to15(&kd3, c->gfc_red, c->gfc_green, c->gfc_blue);
1738 gfs->background = kd3_closest8(&kd3, c->gfc_red, c->gfc_green, c->gfc_blue);
11641739 new_col[gfs->background].pixel++;
11651740 }
11661741
12261801 }
12271802 }
12281803 }
1804
1805
1806 /* Halftone algorithms */
1807
1808 static const uint8_t dither_matrix_o3x3[4 + 3*3] = {
1809 3, 3, 9, 9,
1810 2, 6, 3,
1811 5, 0, 8,
1812 1, 7, 4
1813 };
1814
1815 static const uint8_t dither_matrix_o4x4[4 + 4*4] = {
1816 4, 4, 16, 16,
1817 0, 8, 3, 10,
1818 12, 4, 14, 6,
1819 2, 11, 1, 9,
1820 15, 7, 13, 5
1821 };
1822
1823 static const uint8_t dither_matrix_o8x8[4 + 8*8] = {
1824 8, 8, 64, 64,
1825 0, 48, 12, 60, 3, 51, 15, 63,
1826 32, 16, 44, 28, 35, 19, 47, 31,
1827 8, 56, 4, 52, 11, 59, 7, 55,
1828 40, 24, 36, 20, 43, 27, 39, 23,
1829 2, 50, 14, 62, 1, 49, 13, 61,
1830 34, 18, 46, 30, 33, 17, 45, 29,
1831 10, 58, 6, 54, 9, 57, 5, 53,
1832 42, 26, 38, 22, 41, 25, 37, 21
1833 };
1834
1835 static const uint8_t dither_matrix_ro64x64[4 + 64*64] = {
1836 64, 64, 16, 16,
1837 6, 15, 2, 15, 2, 14, 1, 13, 2, 14, 5, 13, 0, 14, 0, 9, 6, 10, 7, 13, 6, 13, 3, 10, 5, 15, 4, 11, 0, 11, 6, 10, 7, 12, 7, 13, 0, 9, 6, 15, 6, 10, 0, 15, 1, 15, 0, 8, 0, 15, 6, 15, 7, 15, 7, 9, 1, 15, 3, 8, 1, 8, 0, 14,
1838 9, 3, 10, 5, 10, 6, 10, 5, 9, 6, 9, 2, 9, 4, 13, 4, 13, 3, 8, 3, 10, 1, 13, 6, 11, 1, 12, 3, 14, 5, 15, 3, 8, 3, 8, 3, 12, 4, 11, 3, 13, 3, 8, 4, 9, 6, 12, 4, 11, 6, 11, 3, 10, 0, 12, 1, 11, 7, 12, 4, 12, 4, 11, 5,
1839 1, 14, 0, 10, 2, 9, 2, 11, 1, 8, 1, 8, 3, 9, 4, 15, 7, 13, 7, 14, 7, 14, 0, 10, 0, 14, 7, 9, 0, 11, 1, 15, 0, 11, 0, 11, 3, 15, 7, 14, 6, 10, 5, 8, 0, 11, 0, 8, 7, 11, 0, 15, 0, 12, 1, 13, 6, 9, 0, 15, 4, 9, 1, 8,
1840 10, 5, 15, 6, 13, 6, 14, 7, 14, 4, 12, 5, 15, 6, 10, 2, 11, 3, 10, 3, 11, 3, 13, 6, 11, 5, 14, 3, 14, 6, 8, 5, 14, 5, 14, 7, 10, 7, 11, 3, 13, 3, 13, 2, 14, 4, 15, 5, 15, 3, 8, 4, 11, 4, 9, 5, 12, 3, 8, 5, 15, 2, 13, 5,
1841 3, 10, 2, 9, 5, 15, 4, 9, 0, 11, 7, 11, 0, 14, 5, 11, 5, 14, 7, 15, 6, 9, 0, 9, 0, 8, 4, 14, 6, 12, 0, 11, 4, 15, 5, 8, 6, 10, 6, 11, 6, 10, 3, 12, 5, 9, 6, 9, 5, 12, 6, 12, 7, 14, 0, 14, 2, 15, 5, 8, 2, 10, 3, 9,
1842 14, 7, 14, 7, 8, 1, 12, 2, 14, 4, 15, 3, 11, 5, 12, 2, 8, 0, 10, 3, 12, 1, 13, 5, 14, 5, 11, 0, 11, 3, 13, 7, 8, 1, 12, 3, 15, 3, 14, 2, 15, 3, 11, 6, 15, 1, 12, 1, 9, 3, 9, 3, 11, 3, 11, 7, 11, 5, 12, 0, 14, 6, 13, 6,
1843 5, 10, 6, 12, 3, 15, 3, 8, 7, 10, 0, 15, 7, 10, 5, 8, 1, 14, 5, 10, 7, 14, 2, 14, 0, 14, 1, 8, 3, 8, 5, 10, 5, 15, 0, 8, 6, 14, 0, 8, 2, 15, 4, 11, 6, 10, 0, 8, 5, 9, 4, 14, 1, 15, 3, 10, 1, 15, 0, 15, 5, 8, 7, 13,
1844 15, 3, 8, 0, 9, 6, 12, 6, 15, 0, 11, 4, 14, 3, 15, 3, 10, 5, 12, 3, 10, 3, 9, 6, 9, 5, 13, 5, 15, 6, 14, 0, 9, 0, 12, 4, 11, 3, 15, 4, 11, 6, 15, 2, 15, 3, 14, 4, 13, 2, 11, 1, 8, 5, 12, 7, 9, 4, 8, 5, 12, 2, 11, 0,
1845 0, 13, 5, 11, 5, 14, 5, 15, 7, 9, 5, 8, 2, 10, 3, 15, 6, 9, 3, 12, 5, 11, 6, 14, 3, 13, 6, 13, 0, 9, 1, 11, 3, 8, 3, 9, 4, 9, 6, 14, 7, 8, 6, 12, 7, 13, 6, 9, 5, 13, 3, 15, 5, 14, 3, 15, 4, 12, 4, 12, 2, 13, 0, 15,
1846 10, 7, 14, 1, 8, 2, 10, 2, 12, 0, 13, 1, 13, 5, 11, 6, 12, 3, 9, 6, 15, 1, 9, 1, 10, 6, 10, 3, 15, 6, 15, 5, 15, 7, 12, 6, 12, 0, 9, 3, 12, 3, 11, 3, 8, 3, 13, 2, 9, 3, 9, 6, 10, 2, 11, 6, 9, 0, 9, 1, 9, 6, 10, 4,
1847 3, 10, 4, 9, 4, 9, 6, 13, 3, 15, 0, 8, 4, 10, 0, 14, 5, 15, 7, 15, 2, 12, 7, 10, 5, 15, 7, 8, 0, 9, 0, 8, 6, 14, 4, 15, 2, 15, 1, 15, 0, 9, 5, 14, 0, 12, 7, 10, 6, 8, 6, 11, 0, 13, 7, 14, 1, 13, 2, 10, 5, 9, 0, 14,
1848 14, 6, 13, 1, 12, 3, 8, 3, 9, 6, 12, 4, 15, 2, 8, 5, 9, 1, 10, 1, 8, 5, 15, 0, 8, 2, 12, 3, 12, 5, 12, 5, 11, 2, 10, 2, 8, 5, 10, 5, 12, 4, 9, 3, 8, 4, 13, 1, 15, 0, 12, 3, 8, 4, 10, 3, 9, 5, 13, 5, 13, 3, 11, 4,
1849 4, 12, 3, 10, 6, 9, 0, 14, 0, 8, 1, 9, 1, 9, 6, 15, 0, 10, 2, 9, 6, 10, 7, 10, 2, 14, 4, 8, 0, 13, 4, 8, 1, 11, 6, 14, 7, 14, 0, 8, 4, 14, 7, 14, 4, 9, 2, 12, 0, 12, 3, 8, 5, 9, 6, 14, 0, 9, 2, 14, 5, 10, 1, 15,
1850 10, 2, 15, 6, 14, 3, 11, 6, 15, 4, 15, 4, 13, 5, 11, 3, 12, 4, 14, 5, 12, 0, 13, 3, 8, 6, 15, 2, 10, 6, 13, 2, 12, 6, 8, 3, 10, 3, 14, 5, 8, 0, 10, 3, 13, 2, 9, 6, 10, 6, 15, 4, 13, 2, 8, 3, 14, 6, 11, 7, 13, 0, 10, 5,
1851 2, 13, 1, 9, 5, 10, 3, 15, 6, 10, 0, 15, 4, 15, 4, 15, 6, 9, 0, 14, 1, 9, 6, 12, 0, 11, 5, 9, 0, 14, 5, 14, 6, 9, 3, 11, 7, 11, 1, 15, 1, 9, 3, 13, 5, 12, 0, 9, 2, 9, 6, 13, 2, 9, 6, 13, 7, 11, 7, 8, 0, 13, 3, 9,
1852 9, 6, 13, 6, 13, 0, 8, 5, 14, 2, 11, 7, 11, 2, 11, 2, 12, 3, 11, 4, 13, 4, 10, 3, 15, 5, 13, 0, 11, 6, 10, 0, 13, 3, 15, 7, 14, 3, 8, 4, 12, 6, 9, 6, 10, 3, 14, 5, 13, 5, 11, 3, 13, 6, 8, 2, 14, 3, 15, 3, 11, 4, 12, 6,
1853 4, 10, 7, 11, 1, 10, 2, 14, 7, 14, 0, 14, 4, 15, 0, 8, 0, 15, 5, 15, 7, 11, 7, 14, 6, 12, 0, 8, 1, 15, 1, 14, 2, 8, 0, 11, 4, 8, 5, 11, 1, 15, 0, 12, 7, 14, 0, 11, 4, 8, 2, 8, 0, 14, 2, 14, 4, 9, 4, 10, 7, 15, 5, 14,
1854 14, 0, 13, 2, 14, 5, 11, 5, 10, 2, 10, 6, 11, 3, 12, 5, 11, 7, 11, 1, 12, 3, 11, 3, 9, 3, 12, 4, 11, 6, 9, 5, 14, 5, 12, 7, 14, 2, 12, 1, 8, 4, 11, 7, 10, 3, 14, 4, 14, 0, 14, 5, 11, 7, 11, 5, 15, 1, 14, 0, 10, 3, 10, 0,
1855 5, 12, 7, 10, 7, 11, 0, 14, 5, 14, 1, 14, 3, 8, 0, 15, 0, 9, 5, 9, 1, 8, 6, 15, 6, 15, 7, 13, 7, 9, 4, 11, 0, 10, 6, 10, 7, 12, 7, 15, 0, 9, 7, 14, 2, 11, 0, 12, 7, 11, 7, 13, 0, 9, 6, 14, 2, 11, 1, 15, 0, 8, 0, 10,
1856 10, 3, 15, 3, 15, 3, 8, 4, 11, 3, 11, 6, 15, 6, 11, 5, 12, 5, 13, 0, 15, 4, 8, 1, 11, 3, 10, 3, 15, 3, 14, 1, 14, 6, 13, 3, 11, 3, 11, 3, 13, 6, 8, 3, 12, 5, 8, 4, 13, 3, 8, 2, 13, 4, 8, 3, 14, 7, 8, 5, 14, 4, 15, 5,
1857 3, 9, 0, 10, 0, 12, 3, 11, 7, 10, 6, 8, 7, 12, 0, 11, 1, 8, 5, 12, 5, 12, 7, 11, 2, 14, 0, 10, 0, 12, 0, 15, 2, 9, 5, 9, 0, 15, 4, 14, 6, 9, 7, 11, 6, 10, 0, 9, 1, 9, 0, 14, 4, 12, 5, 9, 6, 10, 4, 11, 6, 12, 5, 12,
1858 12, 6, 15, 4, 8, 4, 15, 7, 15, 3, 14, 0, 9, 3, 13, 5, 14, 5, 11, 1, 9, 0, 15, 3, 8, 7, 12, 7, 8, 5, 9, 4, 12, 6, 12, 1, 10, 6, 9, 0, 15, 3, 14, 0, 15, 3, 13, 5, 15, 5, 9, 6, 10, 0, 14, 0, 13, 1, 15, 1, 8, 3, 8, 1,
1859 2, 8, 7, 15, 0, 11, 1, 12, 1, 12, 0, 15, 0, 11, 2, 13, 1, 10, 5, 8, 7, 13, 6, 10, 0, 11, 4, 12, 7, 10, 1, 9, 1, 9, 0, 12, 2, 11, 7, 15, 1, 11, 0, 9, 2, 8, 4, 12, 2, 12, 6, 14, 4, 14, 3, 13, 3, 15, 1, 14, 4, 15, 6, 12,
1860 13, 6, 11, 3, 12, 4, 8, 4, 9, 4, 9, 5, 12, 6, 10, 5, 14, 7, 14, 3, 10, 2, 13, 3, 14, 5, 8, 2, 13, 1, 15, 6, 15, 4, 8, 4, 15, 5, 10, 1, 14, 5, 12, 4, 13, 5, 11, 1, 9, 5, 9, 3, 9, 0, 10, 7, 10, 7, 11, 6, 10, 3, 9, 0,
1861 3, 15, 5, 8, 1, 9, 5, 8, 4, 13, 6, 8, 4, 15, 6, 10, 6, 14, 7, 11, 0, 9, 1, 12, 0, 8, 6, 12, 6, 10, 3, 12, 7, 13, 7, 11, 3, 8, 0, 13, 7, 12, 0, 15, 4, 12, 5, 8, 4, 15, 5, 10, 0, 15, 3, 15, 1, 8, 1, 15, 4, 14, 6, 15,
1862 10, 6, 14, 0, 13, 4, 13, 1, 9, 1, 13, 3, 11, 2, 12, 1, 8, 3, 12, 3, 14, 6, 8, 4, 15, 4, 8, 3, 15, 1, 9, 6, 11, 2, 14, 3, 13, 7, 10, 4, 10, 3, 8, 7, 11, 2, 12, 1, 11, 1, 14, 3, 9, 6, 9, 7, 13, 5, 11, 7, 10, 2, 9, 3,
1863 1, 9, 0, 14, 7, 12, 7, 14, 5, 9, 6, 10, 6, 14, 6, 15, 1, 14, 7, 10, 3, 12, 0, 14, 5, 9, 6, 8, 1, 12, 0, 13, 2, 8, 4, 9, 6, 15, 0, 14, 4, 10, 7, 11, 5, 14, 2, 8, 4, 15, 3, 8, 7, 13, 1, 9, 0, 15, 0, 14, 5, 14, 0, 14,
1864 15, 4, 10, 6, 11, 1, 10, 2, 14, 3, 15, 1, 10, 3, 10, 3, 8, 4, 12, 3, 10, 6, 9, 6, 14, 2, 12, 3, 11, 4, 9, 6, 12, 5, 15, 0, 10, 3, 8, 4, 14, 1, 14, 3, 11, 2, 12, 7, 11, 2, 12, 6, 10, 1, 13, 4, 11, 4, 10, 5, 11, 2, 11, 7,
1865 0, 8, 1, 11, 4, 8, 4, 10, 6, 11, 3, 10, 6, 10, 6, 8, 1, 11, 1, 15, 7, 15, 6, 9, 1, 9, 7, 8, 0, 14, 5, 12, 3, 13, 4, 12, 0, 15, 5, 12, 1, 12, 7, 9, 6, 8, 3, 15, 0, 13, 6, 15, 7, 15, 7, 13, 2, 15, 1, 14, 2, 15, 0, 8,
1866 12, 5, 13, 5, 15, 1, 12, 1, 15, 1, 14, 6, 14, 2, 14, 2, 14, 6, 11, 6, 11, 3, 12, 2, 13, 6, 15, 3, 9, 5, 8, 2, 8, 5, 9, 1, 9, 4, 9, 2, 8, 4, 13, 1, 13, 0, 11, 6, 11, 6, 9, 2, 11, 3, 10, 1, 10, 6, 9, 6, 11, 7, 15, 5,
1867 5, 12, 0, 9, 5, 8, 5, 9, 0, 10, 2, 13, 4, 8, 5, 14, 2, 9, 2, 15, 4, 8, 2, 8, 0, 12, 6, 12, 0, 10, 5, 15, 4, 9, 3, 13, 0, 9, 4, 15, 1, 14, 1, 9, 0, 9, 2, 14, 6, 12, 0, 15, 7, 9, 2, 9, 0, 15, 6, 10, 3, 15, 3, 13,
1868 9, 1, 15, 5, 12, 3, 14, 0, 15, 7, 8, 5, 14, 1, 11, 1, 13, 6, 10, 7, 13, 0, 14, 5, 10, 7, 11, 3, 15, 6, 11, 1, 12, 2, 8, 4, 13, 5, 10, 2, 10, 6, 13, 5, 13, 4, 10, 5, 9, 3, 8, 4, 12, 1, 12, 5, 11, 6, 14, 3, 11, 7, 11, 7,
1869 2, 11, 4, 12, 7, 8, 3, 15, 3, 11, 4, 11, 7, 10, 1, 10, 2, 10, 0, 11, 4, 12, 0, 10, 1, 8, 7, 11, 1, 10, 1, 15, 7, 10, 2, 11, 1, 9, 6, 14, 2, 11, 1, 14, 4, 12, 2, 13, 1, 9, 5, 8, 7, 11, 7, 10, 7, 15, 4, 13, 3, 10, 1, 11,
1870 13, 5, 8, 0, 15, 3, 11, 6, 12, 7, 15, 3, 15, 1, 15, 4, 14, 5, 13, 6, 8, 1, 15, 6, 13, 5, 12, 2, 15, 4, 9, 4, 15, 3, 14, 6, 14, 5, 9, 3, 12, 6, 11, 5, 8, 2, 9, 5, 12, 5, 15, 1, 13, 3, 14, 2, 8, 0, 8, 0, 12, 7, 15, 5,
1871 0, 14, 1, 8, 2, 8, 2, 15, 2, 9, 6, 12, 0, 12, 7, 12, 7, 13, 0, 15, 6, 14, 5, 11, 1, 12, 5, 8, 5, 8, 1, 14, 0, 10, 4, 12, 6, 9, 6, 8, 0, 9, 0, 15, 4, 15, 5, 13, 1, 15, 5, 12, 7, 10, 6, 14, 4, 9, 6, 15, 0, 15, 7, 13,
1872 10, 4, 13, 5, 13, 5, 11, 5, 12, 5, 9, 3, 9, 4, 8, 3, 9, 3, 10, 6, 11, 1, 15, 2, 8, 5, 15, 1, 13, 2, 11, 6, 14, 6, 8, 2, 15, 3, 14, 3, 13, 6, 9, 6, 9, 0, 10, 2, 10, 7, 11, 1, 15, 3, 9, 3, 13, 3, 10, 3, 9, 4, 10, 1,
1873 4, 11, 7, 10, 2, 14, 4, 15, 3, 15, 2, 15, 7, 10, 2, 14, 1, 8, 0, 15, 2, 8, 1, 12, 2, 13, 1, 8, 7, 12, 6, 11, 1, 10, 4, 11, 2, 15, 0, 13, 0, 12, 7, 11, 5, 12, 7, 8, 6, 15, 4, 12, 7, 10, 6, 10, 0, 10, 0, 11, 4, 12, 7, 10,
1874 13, 2, 14, 2, 10, 7, 11, 1, 11, 7, 11, 7, 12, 3, 11, 7, 13, 4, 11, 6, 12, 5, 11, 6, 10, 7, 13, 4, 11, 3, 15, 3, 14, 4, 15, 3, 8, 5, 10, 7, 10, 6, 15, 3, 9, 3, 15, 1, 11, 3, 9, 0, 15, 1, 15, 3, 15, 4, 13, 5, 8, 3, 15, 3,
1875 3, 9, 1, 12, 4, 14, 0, 11, 7, 15, 1, 11, 3, 14, 0, 11, 5, 10, 2, 10, 2, 8, 6, 14, 7, 11, 0, 10, 7, 14, 7, 15, 6, 9, 6, 9, 1, 12, 7, 9, 4, 8, 7, 13, 0, 13, 6, 12, 6, 8, 1, 9, 1, 15, 4, 12, 0, 12, 4, 10, 0, 13, 0, 12,
1876 13, 5, 10, 6, 9, 1, 13, 6, 11, 0, 14, 7, 11, 7, 14, 5, 15, 2, 13, 5, 15, 4, 9, 2, 13, 3, 14, 7, 10, 3, 10, 3, 12, 3, 12, 2, 8, 5, 15, 3, 13, 3, 11, 3, 10, 4, 9, 3, 15, 1, 14, 4, 11, 6, 10, 3, 8, 4, 13, 0, 10, 4, 8, 5,
1877 5, 8, 3, 13, 4, 14, 1, 13, 7, 9, 2, 14, 4, 14, 4, 12, 7, 10, 6, 10, 5, 12, 2, 11, 6, 12, 7, 13, 4, 11, 2, 11, 3, 8, 5, 15, 2, 10, 1, 9, 2, 12, 0, 12, 0, 10, 1, 12, 0, 9, 7, 10, 0, 15, 4, 9, 0, 8, 1, 14, 4, 14, 4, 13,
1878 12, 2, 8, 6, 10, 0, 8, 5, 13, 3, 8, 5, 10, 3, 11, 2, 15, 0, 13, 3, 8, 2, 15, 6, 9, 1, 8, 3, 14, 1, 15, 5, 14, 7, 8, 0, 12, 6, 15, 5, 8, 5, 9, 4, 15, 5, 8, 5, 15, 4, 12, 3, 9, 6, 12, 3, 13, 5, 11, 7, 10, 1, 8, 3,
1879 4, 15, 2, 11, 2, 10, 6, 11, 3, 14, 7, 15, 0, 10, 0, 14, 3, 12, 4, 8, 7, 9, 3, 11, 0, 13, 2, 12, 2, 13, 5, 8, 5, 8, 2, 11, 4, 12, 2, 10, 7, 8, 6, 10, 7, 12, 7, 11, 0, 15, 7, 8, 7, 15, 0, 9, 2, 12, 6, 13, 0, 9, 4, 9,
1880 8, 3, 12, 5, 15, 5, 13, 1, 8, 7, 8, 3, 12, 5, 9, 5, 9, 6, 14, 1, 12, 3, 15, 7, 10, 7, 8, 5, 8, 5, 15, 0, 13, 1, 14, 7, 9, 1, 14, 7, 13, 2, 12, 3, 8, 1, 13, 3, 8, 4, 12, 0, 11, 3, 12, 5, 11, 5, 9, 3, 12, 6, 14, 2,
1881 5, 13, 2, 8, 6, 12, 7, 10, 5, 14, 4, 11, 2, 11, 2, 13, 2, 13, 5, 10, 5, 9, 0, 10, 7, 13, 4, 15, 2, 9, 1, 9, 5, 9, 6, 10, 4, 12, 5, 12, 4, 10, 3, 14, 3, 15, 1, 8, 4, 12, 5, 8, 5, 14, 7, 11, 7, 15, 5, 11, 2, 13, 1, 9,
1882 10, 0, 13, 6, 10, 2, 15, 3, 8, 1, 12, 2, 14, 6, 8, 5, 10, 7, 13, 1, 13, 1, 12, 7, 9, 1, 9, 2, 12, 5, 12, 4, 12, 3, 12, 2, 9, 0, 8, 1, 15, 1, 10, 7, 10, 6, 12, 4, 11, 1, 14, 2, 11, 0, 14, 1, 9, 2, 12, 2, 8, 5, 13, 5,
1883 6, 10, 7, 11, 0, 9, 3, 9, 5, 11, 0, 8, 0, 13, 2, 13, 4, 13, 5, 9, 4, 8, 2, 8, 0, 10, 0, 14, 6, 9, 6, 9, 4, 14, 7, 9, 0, 11, 7, 10, 7, 11, 7, 14, 4, 14, 5, 15, 4, 8, 4, 11, 5, 14, 0, 8, 1, 14, 7, 14, 2, 11, 7, 13,
1884 12, 3, 13, 3, 14, 5, 15, 6, 12, 0, 15, 4, 11, 5, 9, 5, 9, 2, 14, 1, 12, 1, 13, 5, 15, 4, 11, 7, 12, 1, 13, 2, 8, 1, 12, 0, 15, 6, 14, 2, 14, 3, 10, 1, 11, 3, 11, 0, 12, 1, 15, 2, 11, 1, 12, 4, 9, 4, 10, 2, 13, 6, 10, 2,
1885 2, 8, 4, 8, 4, 9, 0, 9, 2, 15, 5, 9, 6, 11, 7, 14, 0, 9, 2, 12, 2, 8, 0, 10, 1, 9, 7, 8, 2, 9, 1, 11, 2, 11, 2, 8, 1, 9, 1, 11, 7, 13, 6, 11, 1, 11, 0, 9, 2, 13, 4, 14, 1, 15, 2, 8, 7, 15, 0, 13, 6, 9, 4, 13,
1886 13, 5, 13, 1, 14, 0, 12, 6, 9, 6, 12, 0, 13, 0, 11, 3, 13, 6, 11, 7, 12, 5, 14, 6, 14, 5, 15, 3, 13, 6, 14, 7, 15, 6, 15, 5, 13, 4, 14, 5, 8, 2, 14, 3, 14, 6, 14, 5, 10, 6, 10, 2, 9, 5, 15, 5, 11, 1, 8, 5, 13, 3, 11, 2,
1887 2, 8, 6, 8, 0, 9, 1, 15, 0, 11, 4, 15, 7, 8, 4, 8, 1, 13, 7, 11, 1, 13, 5, 15, 1, 15, 2, 9, 0, 13, 5, 12, 3, 12, 2, 8, 1, 10, 1, 13, 5, 15, 3, 9, 3, 9, 2, 12, 5, 14, 6, 13, 1, 9, 6, 9, 1, 8, 4, 15, 7, 10, 7, 15,
1888 14, 5, 14, 3, 12, 4, 10, 7, 12, 7, 8, 2, 12, 1, 13, 2, 11, 4, 13, 3, 8, 5, 8, 1, 10, 7, 12, 6, 9, 5, 8, 0, 8, 7, 14, 5, 13, 6, 8, 4, 8, 2, 12, 6, 13, 5, 8, 7, 8, 3, 10, 3, 13, 4, 12, 1, 13, 4, 11, 1, 14, 3, 8, 1,
1889 2, 13, 6, 10, 0, 9, 1, 15, 0, 12, 4, 11, 2, 9, 0, 9, 0, 13, 1, 8, 0, 11, 5, 9, 6, 13, 2, 15, 2, 12, 7, 12, 6, 15, 2, 14, 1, 13, 1, 14, 4, 11, 2, 14, 1, 9, 0, 15, 1, 12, 5, 14, 6, 13, 2, 15, 3, 9, 1, 15, 7, 8, 1, 14,
1890 11, 7, 13, 3, 15, 6, 8, 4, 8, 4, 14, 2, 14, 6, 13, 6, 11, 4, 14, 4, 15, 4, 14, 3, 10, 2, 10, 5, 9, 6, 9, 3, 9, 1, 11, 6, 9, 4, 8, 4, 15, 0, 8, 4, 13, 4, 9, 4, 9, 5, 9, 3, 10, 2, 9, 5, 12, 6, 8, 4, 12, 0, 11, 4,
1891 4, 10, 4, 13, 1, 12, 7, 8, 0, 13, 4, 12, 2, 13, 1, 14, 7, 15, 3, 8, 7, 12, 3, 10, 4, 9, 4, 11, 7, 8, 2, 11, 2, 10, 0, 12, 1, 14, 6, 14, 7, 13, 7, 11, 3, 10, 0, 10, 4, 9, 3, 13, 0, 13, 7, 8, 7, 9, 7, 11, 2, 8, 1, 14,
1892 15, 0, 11, 1, 9, 6, 15, 3, 10, 7, 9, 1, 9, 7, 10, 7, 10, 1, 12, 5, 8, 1, 15, 7, 13, 3, 12, 2, 13, 2, 14, 7, 14, 5, 10, 4, 8, 4, 11, 1, 10, 3, 14, 0, 14, 6, 14, 5, 13, 2, 8, 7, 10, 7, 13, 2, 14, 2, 13, 2, 14, 5, 11, 6,
1893 7, 11, 5, 13, 1, 11, 7, 8, 5, 14, 4, 13, 1, 14, 5, 10, 2, 15, 4, 13, 7, 11, 7, 10, 1, 8, 5, 9, 4, 12, 7, 10, 1, 13, 7, 13, 7, 11, 0, 14, 5, 14, 2, 14, 4, 12, 4, 13, 7, 13, 7, 8, 2, 14, 2, 13, 5, 9, 5, 9, 2, 8, 1, 10,
1894 12, 0, 8, 2, 13, 4, 12, 1, 11, 1, 10, 1, 10, 4, 12, 2, 11, 5, 8, 1, 15, 3, 14, 1, 13, 4, 14, 2, 9, 2, 12, 2, 8, 4, 8, 2, 12, 3, 10, 6, 11, 0, 11, 7, 10, 1, 9, 2, 10, 0, 13, 1, 11, 7, 10, 6, 13, 1, 12, 1, 12, 6, 14, 7,
1895 2, 14, 4, 15, 7, 14, 5, 8, 4, 13, 2, 10, 4, 13, 0, 13, 1, 11, 1, 12, 7, 12, 6, 13, 4, 13, 4, 13, 2, 12, 2, 13, 1, 13, 7, 10, 2, 11, 2, 10, 7, 15, 7, 11, 5, 13, 2, 8, 2, 14, 4, 9, 2, 14, 0, 8, 1, 8, 7, 10, 5, 15, 6, 14,
1896 11, 7, 10, 2, 11, 1, 13, 0, 11, 1, 15, 7, 8, 1, 9, 4, 13, 4, 8, 4, 8, 3, 10, 0, 9, 0, 9, 2, 9, 7, 9, 6, 10, 7, 13, 1, 13, 7, 14, 6, 11, 3, 12, 2, 8, 2, 12, 5, 11, 5, 12, 2, 10, 5, 14, 4, 12, 4, 13, 2, 9, 1, 10, 0,
1897 2, 12, 0, 13, 7, 13, 2, 12, 4, 8, 1, 12, 4, 13, 6, 11, 7, 13, 7, 13, 1, 9, 7, 10, 2, 10, 1, 9, 2, 10, 1, 11, 6, 9, 4, 13, 2, 10, 0, 10, 2, 14, 0, 13, 7, 10, 7, 10, 0, 12, 0, 9, 0, 13, 2, 13, 1, 9, 0, 15, 2, 14, 2, 13,
1898 11, 7, 8, 4, 10, 2, 10, 7, 12, 1, 11, 7, 8, 2, 13, 1, 10, 0, 10, 2, 13, 6, 14, 0, 14, 7, 13, 6, 14, 5, 13, 4, 15, 1, 10, 2, 13, 7, 13, 7, 9, 4, 9, 6, 13, 3, 13, 3, 8, 4, 13, 4, 10, 6, 10, 5, 12, 4, 10, 7, 11, 6, 9, 6,
1899 4, 14, 6, 11, 7, 13, 6, 10, 4, 8, 4, 11, 6, 8, 5, 13, 7, 14, 7, 14, 1, 9, 0, 12, 1, 9, 1, 12, 4, 14, 7, 10, 4, 13, 7, 13, 7, 11, 4, 10, 1, 11, 7, 13, 4, 12, 1, 10, 4, 12, 2, 8, 2, 12, 2, 10, 2, 12, 1, 12, 4, 12, 2, 12,
1900 8, 2, 13, 2, 8, 1, 13, 1, 12, 1, 12, 2, 12, 2, 11, 1, 9, 2, 11, 3, 12, 4, 8, 4, 12, 4, 10, 6, 10, 1, 13, 2, 11, 2, 10, 1, 12, 0, 14, 2, 14, 4, 9, 2, 8, 1, 13, 4, 8, 0, 12, 4, 11, 6, 12, 6, 11, 7, 10, 7, 11, 2, 10, 7
1901 };
1902
1903 /*static const uint8_t dither_matrix_halftone8[4 + 8*8] = {
1904 8, 8, 64, 3,
1905 60, 53, 42, 26, 27, 43, 54, 61,
1906 52, 41, 25, 13, 14, 28, 44, 55,
1907 40, 24, 12, 5, 6, 15, 29, 45,
1908 39, 23, 4, 0, 1, 7, 16, 30,
1909 38, 22, 11, 3, 2, 8, 17, 31,
1910 51, 37, 21, 10, 9, 18, 32, 46,
1911 59, 50, 36, 20, 19, 33, 47, 56,
1912 63, 58, 49, 35, 34, 48, 57, 62
1913 }; */
1914
1915 static const uint8_t dither_matrix_diagonal45_8[4 + 8*8] = {
1916 8, 8, 64, 2,
1917 16, 32, 48, 56, 40, 24, 8, 0,
1918 36, 52, 60, 44, 28, 12, 4, 20,
1919 49, 57, 41, 25, 9, 1, 17, 33,
1920 61, 45, 29, 13, 5, 21, 37, 53,
1921 42, 26, 10, 2, 18, 34, 50, 58,
1922 30, 14, 6, 22, 38, 54, 62, 46,
1923 11, 3, 19, 35, 51, 59, 43, 27,
1924 7, 23, 39, 55, 63, 47, 31, 15
1925 };
1926
1927
1928 typedef struct halftone_pixelinfo {
1929 int x;
1930 int y;
1931 double distance;
1932 double angle;
1933 } halftone_pixelinfo;
1934
1935 static inline halftone_pixelinfo* halftone_pixel_make(int w, int h) {
1936 int x, y, k;
1937 halftone_pixelinfo* hp = Gif_NewArray(halftone_pixelinfo, w * h);
1938 for (y = k = 0; y != h; ++y)
1939 for (x = 0; x != w; ++x, ++k) {
1940 hp[k].x = x;
1941 hp[k].y = y;
1942 hp[k].distance = -1;
1943 }
1944 return hp;
1945 }
1946
1947 static inline void halftone_pixel_combine(halftone_pixelinfo* hp,
1948 double cx, double cy) {
1949 double d = (hp->x - cx) * (hp->x - cx) + (hp->y - cy) * (hp->y - cy);
1950 if (hp->distance < 0 || d < hp->distance) {
1951 hp->distance = d;
1952 hp->angle = atan2(hp->y - cy, hp->x - cx);
1953 }
1954 }
1955
1956 static inline int halftone_pixel_compare(const void* va, const void* vb) {
1957 const halftone_pixelinfo* a = (const halftone_pixelinfo*) va;
1958 const halftone_pixelinfo* b = (const halftone_pixelinfo*) vb;
1959 if (fabs(a->distance - b->distance) > 0.01)
1960 return a->distance < b->distance ? -1 : 1;
1961 else
1962 return a->angle < b->angle ? -1 : 1;
1963 }
1964
1965 static uint8_t* halftone_pixel_matrix(halftone_pixelinfo* hp,
1966 int w, int h, int nc) {
1967 int i;
1968 uint8_t* m = Gif_NewArray(uint8_t, 4 + w * h);
1969 m[0] = w;
1970 m[1] = h;
1971 m[3] = nc;
1972 if (w * h > 255) {
1973 double s = 255. / (w * h);
1974 m[2] = 255;
1975 for (i = 0; i != w * h; ++i)
1976 m[4 + hp[i].x + hp[i].y*w] = (int) (i * s);
1977 } else {
1978 m[2] = w * h;
1979 for (i = 0; i != w * h; ++i)
1980 m[4 + hp[i].x + hp[i].y*w] = i;
1981 }
1982 Gif_DeleteArray(hp);
1983 return m;
1984 }
1985
1986 static uint8_t* make_halftone_matrix_square(int w, int h, int nc) {
1987 halftone_pixelinfo* hp = halftone_pixel_make(w, h);
1988 int i;
1989 for (i = 0; i != w * h; ++i)
1990 halftone_pixel_combine(&hp[i], (w-1)/2.0, (h-1)/2.0);
1991 qsort(hp, w * h, sizeof(*hp), halftone_pixel_compare);
1992 return halftone_pixel_matrix(hp, w, h, nc);
1993 }
1994
1995 static uint8_t* make_halftone_matrix_triangular(int w, int h, int nc) {
1996 halftone_pixelinfo* hp = halftone_pixel_make(w, h);
1997 int i;
1998 for (i = 0; i != w * h; ++i) {
1999 halftone_pixel_combine(&hp[i], (w-1)/2.0, (h-1)/2.0);
2000 halftone_pixel_combine(&hp[i], -0.5, -0.5);
2001 halftone_pixel_combine(&hp[i], w-0.5, -0.5);
2002 halftone_pixel_combine(&hp[i], -0.5, h-0.5);
2003 halftone_pixel_combine(&hp[i], w-0.5, h-0.5);
2004 }
2005 qsort(hp, w * h, sizeof(*hp), halftone_pixel_compare);
2006 return halftone_pixel_matrix(hp, w, h, nc);
2007 }
2008
2009 int set_dither_type(Gt_OutputData* od, const char* name) {
2010 int parm[4], nparm = 0;
2011 const char* comma = strchr(name, ',');
2012 char buf[256];
2013
2014 /* separate arguments from dither name */
2015 if (comma && (size_t) (comma - name) < sizeof(buf)) {
2016 memcpy(buf, name, comma - name);
2017 buf[comma - name] = 0;
2018 name = buf;
2019 }
2020 for (nparm = 0;
2021 comma && *comma && isdigit((unsigned char) comma[1]);
2022 ++nparm)
2023 parm[nparm] = strtol(&comma[1], (char**) &comma, 10);
2024
2025 /* parse dither name */
2026 if (od->dither_type == dither_ordered_new)
2027 Gif_DeleteArray(od->dither_data);
2028 od->dither_type = dither_none;
2029
2030 if (strcmp(name, "none") == 0 || strcmp(name, "posterize") == 0)
2031 /* ok */;
2032 else if (strcmp(name, "default") == 0)
2033 od->dither_type = dither_default;
2034 else if (strcmp(name, "floyd-steinberg") == 0
2035 || strcmp(name, "fs") == 0)
2036 od->dither_type = dither_floyd_steinberg;
2037 else if (strcmp(name, "o3") == 0 || strcmp(name, "o3x3") == 0
2038 || (strcmp(name, "o") == 0 && nparm >= 1 && parm[0] == 3)) {
2039 od->dither_type = dither_ordered;
2040 od->dither_data = dither_matrix_o3x3;
2041 } else if (strcmp(name, "o4") == 0 || strcmp(name, "o4x4") == 0
2042 || (strcmp(name, "o") == 0 && nparm >= 1 && parm[0] == 4)) {
2043 od->dither_type = dither_ordered;
2044 od->dither_data = dither_matrix_o4x4;
2045 } else if (strcmp(name, "o8") == 0 || strcmp(name, "o8x8") == 0
2046 || (strcmp(name, "o") == 0 && nparm >= 1 && parm[0] == 8)) {
2047 od->dither_type = dither_ordered;
2048 od->dither_data = dither_matrix_o8x8;
2049 } else if (strcmp(name, "ro64") == 0 || strcmp(name, "ro64x64") == 0
2050 || strcmp(name, "o") == 0 || strcmp(name, "ordered") == 0) {
2051 od->dither_type = dither_ordered;
2052 od->dither_data = dither_matrix_ro64x64;
2053 } else if (strcmp(name, "diag45") == 0 || strcmp(name, "diagonal") == 0) {
2054 od->dither_type = dither_ordered;
2055 od->dither_data = dither_matrix_diagonal45_8;
2056 } else if (strcmp(name, "halftone") == 0 || strcmp(name, "half") == 0
2057 || strcmp(name, "trihalftone") == 0
2058 || strcmp(name, "trihalf") == 0) {
2059 int size = nparm >= 1 && parm[0] > 0 ? parm[0] : 6;
2060 int ncol = nparm >= 2 && parm[1] > 1 ? parm[1] : 2;
2061 od->dither_type = dither_ordered_new;
2062 od->dither_data = make_halftone_matrix_triangular(size, (int) (size * sqrt(3) + 0.5), ncol);
2063 } else if (strcmp(name, "sqhalftone") == 0 || strcmp(name, "sqhalf") == 0
2064 || strcmp(name, "squarehalftone") == 0) {
2065 int size = nparm >= 1 && parm[0] > 0 ? parm[0] : 6;
2066 int ncol = nparm >= 2 && parm[1] > 1 ? parm[1] : 2;
2067 od->dither_type = dither_ordered_new;
2068 od->dither_data = make_halftone_matrix_square(size, size, ncol);
2069 } else
2070 return -1;
2071
2072 if (od->dither_type == dither_ordered
2073 && nparm >= 2 && parm[1] > 1 && parm[1] != od->dither_data[3]) {
2074 int size = od->dither_data[0] * od->dither_data[1];
2075 uint8_t* dd = Gif_NewArray(uint8_t, 4 + size);
2076 memcpy(dd, od->dither_data, 4 + size);
2077 dd[3] = parm[1];
2078 od->dither_data = dd;
2079 od->dither_type = dither_ordered_new;
2080 }
2081 return 0;
2082 }
150150 single images into animations, adding transparency, optimizing animations for\n\
151151 space, and printing information about GIFs.\n\
152152 \n\
153 Usage: %s [OPTION | FILE | FRAME]...\n\
154 \n\
153 Usage: %s [OPTION | FILE | FRAME]...\n\n", program_name);
154 printf("\
155155 Mode options: at most one, before any filenames.\n\
156156 -m, --merge Merge mode: combine inputs, write stdout.\n\
157157 -b, --batch Batch mode: modify inputs, write back to\n\
158158 same filenames.\n\
159159 -e, --explode Explode mode: write N files for each input,\n\
160160 one per frame, to 'input.frame-number'.\n\
161 -E, --explode-by-name Explode mode, but write 'input.name'.\n\
162 \n\
161 -E, --explode-by-name Explode mode, but write 'input.name'.\n\n");
162 printf("\
163163 General options: Also --no-OPTION for info and verbose.\n\
164164 -I, --info Print info about input GIFs. Two -I's means\n\
165165 normal output is not suppressed.\n\
166166 --color-info, --cinfo --info plus colormap details.\n\
167167 --extension-info, --xinfo --info plus extension details.\n\
168168 --size-info, --sinfo --info plus compression information.\n\
169 -V, --verbose Prints progress information.\n\
169 -V, --verbose Prints progress information.\n");
170 printf("\
170171 -h, --help Print this message and exit.\n\
171172 --version Print version number and exit.\n\
172173 -o, --output FILE Write output to FILE.\n\
173174 -w, --no-warnings Don't report warnings.\n\
174175 --conserve-memory Conserve memory at the expense of speed.\n\
175176 --multifile Support concatenated GIF files.\n\
176 \n", program_name);
177 \n");
177178 printf("\
178179 Frame selections: #num, #num1-num2, #num1-, #name\n\
179180 \n\
182183 --insert-before FRAME GIFS Insert GIFS before FRAMES in input.\n\
183184 --append GIFS Append GIFS to input.\n\
184185 --replace FRAMES GIFS Replace FRAMES with GIFS in input.\n\
185 --done Done with frame changes.\n\
186 \n\
186 --done Done with frame changes.\n\n");
187 printf("\
187188 Image options: Also --no-OPTION and --same-OPTION.\n\
188189 -B, --background COL Make COL the background color.\n\
189190 --crop X,Y+WxH, --crop X,Y-X2,Y2\n\
190191 Crop the image.\n\
191192 --crop-transparency Crop transparent borders off the image.\n\
192193 --flip-horizontal, --flip-vertical\n\
193 Flip the image.\n\
194 Flip the image.\n");
195 printf("\
194196 -i, --interlace Turn on interlacing.\n\
195197 -S, --logical-screen WxH Set logical screen to WxH.\n\
196198 -p, --position X,Y Set frame position to (X,Y).\n\
197199 --rotate-90, --rotate-180, --rotate-270, --no-rotate\n\
198200 Rotate the image.\n\
199 -t, --transparent COL Make COL transparent.\n\
200 \n");
201 -t, --transparent COL Make COL transparent.\n\n");
201202 printf("\
202203 Extension options: Also --no-OPTION and --same-OPTION.\n\
203204 -x, --app-extension N D Add an app extension named N with data D.\n\
204205 -c, --comment TEXT Add a comment before the next frame.\n\
205206 --extension N D Add an extension number N with data D.\n\
206 -n, --name TEXT Set next frame's name.\n\
207 \n\
207 -n, --name TEXT Set next frame's name.\n\n");
208 printf("\
208209 Animation options: Also --no-OPTION and --same-OPTION.\n\
209210 -d, --delay TIME Set frame delay to TIME (in 1/100sec).\n\
210211 -D, --disposal METHOD Set frame disposal to METHOD.\n\
219220 --change-color COL1 COL2 Change COL1 to COL2 throughout.\n\
220221 -k, --colors N Reduce the number of colors to N.\n\
221222 --color-method METHOD Set method for choosing reduced colors.\n\
222 -f, --dither Dither image after changing colormap.\n\
223 -f, --dither Dither image after changing colormap.\n");
224 #if HAVE_POW
225 printf("\
226 --gamma G Set gamma for color reduction [2.2].\n");
227 #endif
228 printf("\
223229 --resize WxH Resize the output GIF to WxH.\n\
224230 --resize-width W Resize to width W and proportional height.\n\
225 --resize-height H Resize to height H and proportional width.\n\
231 --resize-height H Resize to height H and proportional width.\n");
232 printf("\
226233 --scale XFACTOR[xYFACTOR] Scale the output GIF by XFACTORxYFACTOR.\n\
227234 --transform-colormap CMD Transform each output colormap by shell CMD.\n\
228235 --use-colormap CMAP Set output GIF's colormap to CMAP, which can\n\
229 be 'web', 'gray', 'bw', or a GIF file.\n\
230 \n\
236 be 'web', 'gray', 'bw', or a GIF file.\n\n");
237 printf("\
231238 Report bugs to <ekohler@gmail.com>.\n\
232239 Too much information? Try '%s --help | more'.\n", program_name);
233240 #ifdef GIF_UNGIF
281288
282289 const char* debug_color_str(const Gif_Color* gfc) {
283290 static int whichbuf = 0;
284 static char buf[8][8];
285 whichbuf = (whichbuf + 1) % 8;
291 static char buf[4][8];
292 whichbuf = (whichbuf + 1) % 4;
286293 sprintf(buf[whichbuf], "#%02X%02X%02X",
287294 gfc->gfc_red, gfc->gfc_green, gfc->gfc_blue);
288295 return buf[whichbuf];
7070 #define PACKAGE_NAME "gifsicle"
7171
7272 /* Define to the full name and version of this package. */
73 #define PACKAGE_STRING "gifsicle 1.76"
73 #define PACKAGE_STRING "gifsicle 1.77"
7474
7575 /* Define to the one symbol short name of this package. */
7676 #define PACKAGE_TARNAME "gifsicle"
7979 #define PACKAGE_URL ""
8080
8181 /* Define to the version of this package. */
82 #define PACKAGE_VERSION "1.76"
82 #define PACKAGE_VERSION "1.77"
8383
8484 /* Pathname separator character ('/' on Unix). */
8585 #define PATHNAME_SEPARATOR '\\'
108108 #define STDC_HEADERS 1
109109
110110 /* Version number of package */
111 #define VERSION "1.76 (Windows)"
111 #define VERSION "1.77 (Windows)"
112112
113113 /* Define if X is not available. */
114114 #define X_DISPLAY_MISSING 1