diff options
author | ijliao <ijliao@FreeBSD.org> | 2002-05-21 07:41:54 +0000 |
---|---|---|
committer | ijliao <ijliao@FreeBSD.org> | 2002-05-21 07:41:54 +0000 |
commit | 0c3276726a4360219122b630dba18e5b327579b1 (patch) | |
tree | 5efca470dbb74c89a18448432bff18e99c8a2e3c /graphics/gd2 | |
parent | 06bc2ae5ff02e3754aa726f65ab0ec9334ba18c8 (diff) | |
download | FreeBSD-ports-0c3276726a4360219122b630dba18e5b327579b1.zip FreeBSD-ports-0c3276726a4360219122b630dba18e5b327579b1.tar.gz |
Improved GIF support.
New GIF output functions, w/ or w/o LZW compression.
LZW compression is OFF by default to make the package legal in US and Canada.
Updated documentation
PR: 37455
Submitted by: Alex Dupre <sysadmin@alexdupre.com>
Diffstat (limited to 'graphics/gd2')
24 files changed, 3427 insertions, 50 deletions
diff --git a/graphics/gd2/Makefile b/graphics/gd2/Makefile index bde979b..731f676 100644 --- a/graphics/gd2/Makefile +++ b/graphics/gd2/Makefile @@ -7,21 +7,15 @@ PORTNAME= gd PORTVERSION= 2.0.1 -PORTREVISION= 2 +PORTREVISION= 3 CATEGORIES+= graphics MASTER_SITES= http://www.boutell.com/gd/http/ \ ftp://ftp.boutell.com/pub/boutell/gd/ \ - http://virtual-estates.net/~mi/port-stuff/ \ ${MASTER_SITE_RINGSERVER} MASTER_SITE_SUBDIR= graphics/gd -DISTFILES= ${DISTNAME}${EXTRACT_SUFX} gd_gif_in.c.bz2 -EXTRACT_ONLY= ${DISTNAME}${EXTRACT_SUFX} MAINTAINER?= ports@FreeBSD.org -.if !exists(/usr/bin/bzip2) -BUILD_DEPENDS+= bzip2:${PORTSDIR}/archivers/bzip2 -.endif LIB_DEPENDS= png:${PORTSDIR}/graphics/png \ jpeg:${PORTSDIR}/graphics/jpeg \ freetype:${PORTSDIR}/print/freetype2 @@ -46,10 +40,29 @@ MAKE_ARGS+= -j2 MAKE_ARGS+= $v="${$v}" .endfor +pre-fetch: +.if !defined(WITH_LZW) + @${ECHO_CMD} "************************************************************" + @${ECHO_CMD} "* If you live outside US and Canada, you can set *" + @${ECHO_CMD} "* WITH_LZW=1 to enable GIF compression support. *" + @${ECHO_CMD} "************************************************************" +.endif + post-extract: - ${BZIP2_CMD} -d < ${_DISTDIR}/gd_gif_in.c.bz2 > ${WRKSRC}/gd_gif_in.c + @${CP} ${FILESDIR}/g* ${WRKSRC} + +post-patch: +.if !defined(WITH_LZW) + @${PERL} -pi -e "s|#define LZW_LICENCED||g" ${WRKSRC}/gd_gif_out.c +.endif + +post-install: +.if !defined(NOPORTDOCS) + @${MKDIR} ${DOCSDIR} + @${INSTALL_DATA} ${WRKSRC}/index.html ${DOCSDIR} +.endif -.ifdef GD_FONTS +.if defined(GD_FONTS) SCRIPTS_ENV+= GD_FONTS="${GD_FONTS}" .endif diff --git a/graphics/gd2/distinfo b/graphics/gd2/distinfo index 25da3c3..8bc97eb 100644 --- a/graphics/gd2/distinfo +++ b/graphics/gd2/distinfo @@ -1,2 +1 @@ MD5 (gd-2.0.1.tar.gz) = 43af994a97f3300a1165ca4888176ece -MD5 (gd_gif_in.c.bz2) = 54132aea09471bb997672436dd9a1a96 diff --git a/graphics/gd2/files/Makefile.bsd b/graphics/gd2/files/Makefile.bsd index 718ca5c..8d8f201 100644 --- a/graphics/gd2/files/Makefile.bsd +++ b/graphics/gd2/files/Makefile.bsd @@ -1,10 +1,9 @@ PROGS!= make -V BIN_PROGRAMS -f ${WRKSRC}/Makefile TESTS!= make -V TEST_PROGRAMS -f ${WRKSRC}/Makefile OBJS!= make -V LIBOBJS -f ${WRKSRC}/Makefile -OBJS+= gd_gif_in.o SRCS= ${OBJS:.o=.c} LIB=gd -SHLIB_MAJOR=3 +SHLIB_MAJOR=4 SHLIB_MINOR=0 INCS= gd.h gd_io.h gdcache.h gdfontg.h gdfontl.h gdfontmb.h \ gdfonts.h gdfontt.h @@ -42,12 +41,12 @@ ${PROGS} ${TESTS}: ${SHLIB_NAME} lib${LIB}.a install: mkdir -p ${PREFIX}/include - make LIB=${LIB} LIBDIR="${PREFIX}/lib" NOPROFILE=true \ + make LIB=${LIB} LIBDIR=${PREFIX}/lib NOPROFILE=true \ SHLIB_MAJOR=${SHLIB_MAJOR} SHLIB_MINOR=${SHLIB_MINOR} \ -f bsd.lib.mk install cd ${.CURDIR} && ${INSTALL_DATA} ${INCS} ${PREFIX}/include - cd ${.CURDIR} && ${INSTALL_PROGRAM} ${PROGS} "${PREFIX}/bin/" - ${INSTALL_SCRIPT} "${.CURDIR}/bdftogd" "${PREFIX}/bin/" + cd ${.CURDIR} && ${INSTALL_PROGRAM} ${PROGS} ${PREFIX}/bin/ + ${INSTALL_SCRIPT} ${.CURDIR}/bdftogd ${PREFIX}/bin/ .if exists(${.CURDIR}/Makefile.fonts) .include "Makefile.fonts" diff --git a/graphics/gd2/files/gd2togif.c b/graphics/gd2/files/gd2togif.c new file mode 100644 index 0000000..d5fbb89 --- /dev/null +++ b/graphics/gd2/files/gd2togif.c @@ -0,0 +1,40 @@ +#include <stdio.h> +#include "gd.h" + +/* A short program which converts a .gif file into a .gd file, for + your convenience in creating images on the fly from a + basis image that must be loaded quickly. The .gd format + is not intended to be a general-purpose format. */ + +int main(int argc, char **argv) +{ + gdImagePtr im; + FILE *in, *out; + if (argc != 3) { + fprintf(stderr, "Usage: gd2togif filename.gd2 filename.gif\n"); + exit(1); + } + in = fopen(argv[1], "rb"); + if (!in) { + fprintf(stderr, "Input file does not exist!\n"); + exit(1); + } + im = gdImageCreateFromGd2(in); + fclose(in); + if (!im) { + fprintf(stderr, "Input is not in GIF format!\n"); + exit(1); + } + out = fopen(argv[2], "wb"); + if (!out) { + fprintf(stderr, "Output file cannot be written to!\n"); + gdImageDestroy(im); + exit(1); + } + gdImageGif(im, out); + fclose(out); + gdImageDestroy(im); + + return 0; +} + diff --git a/graphics/gd2/files/gd_biggif_out.c b/graphics/gd2/files/gd_biggif_out.c new file mode 100644 index 0000000..3f4ac1f --- /dev/null +++ b/graphics/gd2/files/gd_biggif_out.c @@ -0,0 +1,823 @@ +#include <stdio.h> +#include <math.h> +#include <string.h> +#include <stdlib.h> +#include "gd.h" + +/* +** Wrapper functions for this module. +*/ + +void gdImageBigGif(gdImagePtr im, FILE *outFile) +{ + gdIOCtx *out = gdNewFileCtx(outFile); + gdImageBigGifCtx(im, out); + out->free(out); +} + +void* gdImageBigGifPtr(gdImagePtr im, int *size) +{ + void *rv; + gdIOCtx *out = gdNewDynamicCtx(2048, NULL); + gdImageBigGifCtx(im, out); + rv = gdDPExtractData(out,size); + out->free(out); + return rv; +} + +/* Code drawn from ppmtogif.c, from the pbmplus package +** +** Based on GIFENCOD by David Rowley <mgardi@watdscu.waterloo.edu>. A +** Lempel-Zim compression based on "compress". +** +** Modified by Marcel Wijkstra <wijkstra@fwi.uva.nl> +** +** Copyright (C) 1989 by Jef Poskanzer. +** +** Permission to use, copy, modify, and distribute this software and its +** documentation for any purpose and without fee is hereby granted, provided +** that the above copyright notice appear in all copies and that both that +** copyright notice and this permission notice appear in supporting +** documentation. This software is provided "as is" without express or +** implied warranty. +** +** The Graphics Interchange Format(c) is the Copyright property of +** CompuServe Incorporated. GIF(sm) is a Service Mark property of +** CompuServe Incorporated. +* +* Heavily modified by Mouse, 1998-02-12. +* Remove LZW compression. +* Added miGIF run length compression. +* +*/ + +/* + * a code_int must be able to hold 2**GIFBITS values of type int, and also -1 + */ +typedef int code_int; + +static int colorstobpp(int colors); +static void BumpPixel (void); +static int GIFNextPixel (gdImagePtr im); +static void GIFEncode (gdIOCtx *fp, int GWidth, int GHeight, int GInterlace, int Background, int Transparent, int BitsPerPixel, int *Red, int *Green, int *Blue, gdImagePtr im); +/*static void Putword (int w, gdIOCtx *fp); */ +static void GIFcompress (int, gdIOCtx *, gdImagePtr, int); +static void output (code_int code); + +/* UNUSED +* static void char_init (void); +* static void char_out (int c); +*/ + +/* Allows for reuse */ +static void init_statics(void); + +void gdImageBigGifCtx(gdImagePtr im, gdIOCtx *out) +{ + int interlace, transparent, BitsPerPixel; + + interlace = im->interlace; + transparent = im->transparent; + + BitsPerPixel = colorstobpp(im->colorsTotal); + /* Clear any old values in statics strewn through the GIF code */ + init_statics(); + /* All set, let's do it. */ + GIFEncode( + out, im->sx, im->sy, interlace, 0, transparent, BitsPerPixel, + im->red, im->green, im->blue, im); +} + +static int +colorstobpp(int colors) +{ + int bpp = 0; + + if ( colors <= 2 ) + bpp = 1; + else if ( colors <= 4 ) + bpp = 2; + else if ( colors <= 8 ) + bpp = 3; + else if ( colors <= 16 ) + bpp = 4; + else if ( colors <= 32 ) + bpp = 5; + else if ( colors <= 64 ) + bpp = 6; + else if ( colors <= 128 ) + bpp = 7; + else if ( colors <= 256 ) + bpp = 8; + return bpp; + } + +/***************************************************************************** + * + * GIFENCODE.C - GIF Image compression interface + * + * GIFEncode( FName, GHeight, GWidth, GInterlace, Background, Transparent, + * BitsPerPixel, Red, Green, Blue, gdImagePtr ) + * + *****************************************************************************/ + +#define TRUE 1 +#define FALSE 0 + +static int Width, Height; +static int curx, cury; +static long CountDown; +static int Pass = 0; +static int Interlace; + +/* + * Bump the 'curx' and 'cury' to point to the next pixel + */ +static void +BumpPixel(void) +{ + /* + * Bump the current X position + */ + ++curx; + + /* + * If we are at the end of a scan line, set curx back to the beginning + * If we are interlaced, bump the cury to the appropriate spot, + * otherwise, just increment it. + */ + if( curx == Width ) { + curx = 0; + + if( !Interlace ) + ++cury; + else { + switch( Pass ) { + + case 0: + cury += 8; + if( cury >= Height ) { + ++Pass; + cury = 4; + } + break; + + case 1: + cury += 8; + if( cury >= Height ) { + ++Pass; + cury = 2; + } + break; + + case 2: + cury += 4; + if( cury >= Height ) { + ++Pass; + cury = 1; + } + break; + + case 3: + cury += 2; + break; + } + } + } +} + +/* + * Return the next pixel from the image + */ +static int +GIFNextPixel(gdImagePtr im) +{ + int r; + + if( CountDown == 0 ) + return EOF; + + --CountDown; + + r = gdImageGetPixel(im, curx, cury); + + BumpPixel(); + + return r; +} + +/* public */ + +static void +GIFEncode(gdIOCtx *fp, int GWidth, int GHeight, int GInterlace, int Background, int Transparent, int BitsPerPixel, int *Red, int *Green, int *Blue, gdImagePtr im) +{ + int B; + int RWidth, RHeight; + int LeftOfs, TopOfs; + int Resolution; + int ColorMapSize; + int InitCodeSize; + int i; + + Interlace = GInterlace; + + ColorMapSize = 1 << BitsPerPixel; + + RWidth = Width = GWidth; + RHeight = Height = GHeight; + LeftOfs = TopOfs = 0; + + Resolution = BitsPerPixel; + + /* + * Calculate number of bits we are expecting + */ + CountDown = (long)Width * (long)Height; + + /* + * Indicate which pass we are on (if interlace) + */ + Pass = 0; + + /* + * The initial code size + */ + if( BitsPerPixel <= 1 ) + InitCodeSize = 2; + else + InitCodeSize = BitsPerPixel; + + /* + * Set up the current x and y position + */ + curx = cury = 0; + + /* + * Write the Magic header + */ + gdPutBuf( Transparent < 0 ? "GIF87a" : "GIF89a", 6, fp ); + + /* + * Write out the screen width and height + */ + Putword( RWidth, fp ); + Putword( RHeight, fp ); + + /* + * Indicate that there is a global colour map + */ + B = 0x80; /* Yes, there is a color map */ + + /* + * OR in the resolution + */ + B |= (Resolution - 1) << 4; + + /* + * OR in the Bits per Pixel + */ + B |= (BitsPerPixel - 1); + + /* + * Write it out + */ + gdPutC( B, fp ); + + /* + * Write out the Background colour + */ + gdPutC( Background, fp ); + + /* + * Byte of 0's (future expansion) + */ + gdPutC( 0, fp ); + + /* + * Write out the Global Colour Map + */ + for( i=0; i<ColorMapSize; ++i ) { + gdPutC( Red[i], fp ); + gdPutC( Green[i], fp ); + gdPutC( Blue[i], fp ); + } + + /* + * Write out extension for transparent colour index, if necessary. + */ + if ( Transparent >= 0 ) { + gdPutC( '!', fp ); + gdPutC( 0xf9, fp ); + gdPutC( 4, fp ); + gdPutC( 1, fp ); + gdPutC( 0, fp ); + gdPutC( 0, fp ); + gdPutC( (unsigned char) Transparent, fp ); + gdPutC( 0, fp ); + } + + /* + * Write an Image separator + */ + gdPutC( ',', fp ); + + /* + * Write the Image header + */ + + Putword( LeftOfs, fp ); + Putword( TopOfs, fp ); + Putword( Width, fp ); + Putword( Height, fp ); + + /* + * Write out whether or not the image is interlaced + */ + if( Interlace ) + gdPutC( 0x40, fp ); + else + gdPutC( 0x00, fp ); + + /* + * Write out the initial code size + */ + gdPutC( InitCodeSize, fp ); + + /* + * Go and actually compress the data + */ + GIFcompress( InitCodeSize+1, fp, im, Background ); + + /* + * Write out a Zero-length packet (to end the series) + */ + gdPutC( 0, fp ); + + /* + * Write the GIF file terminator + */ + gdPutC( ';', fp ); +} + +/* Write out a word to the GIF file */ +/*static void */ +/*Putword(int w, gdIOCtx *fp) */ +/*{ */ +/* fputc( w & 0xff, fp ); */ +/* fputc( (w / 256) & 0xff, fp ); */ +/*} */ + +#define GIFBITS 12 + +/*----------------------------------------------------------------------- + * + * miGIF Compression - mouse and ivo's GIF-compatible compression + * + * -run length encoding compression routines- + * + * Copyright (C) 1998 Hutchison Avenue Software Corporation + * http://www.hasc.com + * info@hasc.com + * + * Permission to use, copy, modify, and distribute this software and its + * documentation for any purpose and without fee is hereby granted, provided + * that the above copyright notice appear in all copies and that both that + * copyright notice and this permission notice appear in supporting + * documentation. This software is provided "AS IS." The Hutchison Avenue + * Software Corporation disclaims all warranties, either express or implied, + * including but not limited to implied warranties of merchantability and + * fitness for a particular purpose, with respect to this code and accompanying + * documentation. + * + * The miGIF compression routines do not, strictly speaking, generate files + * conforming to the GIF spec, since the image data is not LZW-compressed + * (this is the point: in order to avoid transgression of the Unisys patent + * on the LZW algorithm.) However, miGIF generates data streams that any + * reasonably sane LZW decompresser will decompress to what we want. + * + * miGIF compression uses run length encoding. It compresses horizontal runs + * of pixels of the same color. This type of compression gives good results + * on images with many runs, for example images with lines, text and solid + * shapes on a solid-colored background. It gives little or no compression + * on images with few runs, for example digital or scanned photos. + * + * der Mouse + * mouse@rodents.montreal.qc.ca + * 7D C8 61 52 5D E7 2D 39 4E F1 31 3E E8 B3 27 4B + * + * ivo@hasc.com + * + * The Graphics Interchange Format(c) is the Copyright property of + * CompuServe Incorporated. GIF(sm) is a Service Mark property of + * CompuServe Incorporated. + * + */ + +static int rl_pixel; +static int rl_basecode; +static int rl_count; +static int rl_table_pixel; +static int rl_table_max; +static int just_cleared; +static int out_bits; +static int out_bits_init; +static int out_count; +static int out_bump; +static int out_bump_init; +static int out_clear; +static int out_clear_init; +static int max_ocodes; +static int code_clear; +static int code_eof; +static unsigned int obuf; +static int obits; +static gdIOCtx *ofile; +static unsigned char oblock[256]; +static int oblen; + +/* Used only when debugging GIF compression code */ +/* #define DEBUGGING_ENVARS */ + +#ifdef DEBUGGING_ENVARS + +static int verbose_set = 0; +static int verbose; +#define VERBOSE (verbose_set?verbose:set_verbose()) + +static int set_verbose(void) +{ + verbose = !!getenv("GIF_VERBOSE"); + verbose_set = 1; + return(verbose); +} + +#else + +#define VERBOSE 0 + +#endif + + +static const char *binformat(unsigned int v, int nbits) +{ + static char bufs[8][64]; + static int bhand = 0; + unsigned int bit; + int bno; + char *bp; + + bhand --; + if (bhand < 0) bhand = (sizeof(bufs)/sizeof(bufs[0]))-1; + bp = &bufs[bhand][0]; + for (bno=nbits-1,bit=1U<<bno;bno>=0;bno--,bit>>=1) + { *bp++ = (v & bit) ? '1' : '0'; + if (((bno&3) == 0) && (bno != 0)) *bp++ = '.'; + } + *bp = '\0'; + return(&bufs[bhand][0]); +} + +static void write_block(void) +{ + int i; + + if (VERBOSE) + { printf("write_block %d:",oblen); + for (i=0;i<oblen;i++) printf(" %02x",oblock[i]); + printf("\n"); + } + gdPutC(oblen,ofile); + gdPutBuf(&oblock[0],oblen,ofile); + oblen = 0; +} + +static void block_out(unsigned char c) +{ + if (VERBOSE) printf("block_out %s\n",binformat(c,8)); + oblock[oblen++] = c; + if (oblen >= 255) write_block(); +} + +static void block_flush(void) +{ + if (VERBOSE) printf("block_flush\n"); + if (oblen > 0) write_block(); +} + +static void output(int val) +{ + if (VERBOSE) printf("output %s [%s %d %d]\n",binformat(val,out_bits),binformat(obuf,obits),obits,out_bits); + obuf |= val << obits; + obits += out_bits; + while (obits >= 8) + { block_out(obuf&0xff); + obuf >>= 8; + obits -= 8; + } + if (VERBOSE) printf("output leaving [%s %d]\n",binformat(obuf,obits),obits); +} + +static void output_flush(void) +{ + if (VERBOSE) printf("output_flush\n"); + if (obits > 0) block_out(obuf); + block_flush(); +} + +static void did_clear(void) +{ + if (VERBOSE) printf("did_clear\n"); + out_bits = out_bits_init; + out_bump = out_bump_init; + out_clear = out_clear_init; + out_count = 0; + rl_table_max = 0; + just_cleared = 1; +} + +static void output_plain(int c) +{ + if (VERBOSE) printf("output_plain %s\n",binformat(c,out_bits)); + just_cleared = 0; + output(c); + out_count ++; + if (out_count >= out_bump) + { out_bits ++; + out_bump += 1 << (out_bits - 1); + } + if (out_count >= out_clear) + { output(code_clear); + did_clear(); + } +} + +static unsigned int isqrt(unsigned int x) +{ + unsigned int r; + unsigned int v; + + if (x < 2) return(x); + for (v=x,r=1;v;v>>=2,r<<=1) ; + while (1) + { v = ((x / r) + r) / 2; + if ((v == r) || (v == r+1)) return(r); + r = v; + } +} + +static unsigned int compute_triangle_count(unsigned int count, unsigned int nrepcodes) +{ + unsigned int perrep; + unsigned int cost; + + cost = 0; + perrep = (nrepcodes * (nrepcodes+1)) / 2; + while (count >= perrep) + { cost += nrepcodes; + count -= perrep; + } + if (count > 0) + { unsigned int n; + n = isqrt(count); + while ((n*(n+1)) >= 2*count) n --; + while ((n*(n+1)) < 2*count) n ++; + cost += n; + } + return(cost); +} + +static void max_out_clear(void) +{ + out_clear = max_ocodes; +} + +static void reset_out_clear(void) +{ + out_clear = out_clear_init; + if (out_count >= out_clear) + { output(code_clear); + did_clear(); + } +} + +static void rl_flush_fromclear(int count) +{ + int n; + + if (VERBOSE) printf("rl_flush_fromclear %d\n",count); + max_out_clear(); + rl_table_pixel = rl_pixel; + n = 1; + while (count > 0) + { if (n == 1) + { rl_table_max = 1; + output_plain(rl_pixel); + count --; + } + else if (count >= n) + { rl_table_max = n; + output_plain(rl_basecode+n-2); + count -= n; + } + else if (count == 1) + { rl_table_max ++; + output_plain(rl_pixel); + count = 0; + } + else + { rl_table_max ++; + output_plain(rl_basecode+count-2); + count = 0; + } + if (out_count == 0) n = 1; else n ++; + } + reset_out_clear(); + if (VERBOSE) printf("rl_flush_fromclear leaving table_max=%d\n",rl_table_max); +} + +static void rl_flush_clearorrep(int count) +{ + int withclr; + + if (VERBOSE) printf("rl_flush_clearorrep %d\n",count); + withclr = 1 + compute_triangle_count(count,max_ocodes); + if (withclr < count) + { output(code_clear); + did_clear(); + rl_flush_fromclear(count); + } + else + { for (;count>0;count--) output_plain(rl_pixel); + } +} + +static void rl_flush_withtable(int count) +{ + int repmax; + int repleft; + int leftover; + + if (VERBOSE) printf("rl_flush_withtable %d\n",count); + repmax = count / rl_table_max; + leftover = count % rl_table_max; + repleft = (leftover ? 1 : 0); + if (out_count+repmax+repleft > max_ocodes) + { repmax = max_ocodes - out_count; + leftover = count - (repmax * rl_table_max); + repleft = 1 + compute_triangle_count(leftover,max_ocodes); + } + if (VERBOSE) printf("rl_flush_withtable repmax=%d leftover=%d repleft=%d\n",repmax,leftover,repleft); + if (1+compute_triangle_count(count,max_ocodes) < repmax+repleft) + { output(code_clear); + did_clear(); + rl_flush_fromclear(count); + return; + } + max_out_clear(); + for (;repmax>0;repmax--) output_plain(rl_basecode+rl_table_max-2); + if (leftover) + { if (just_cleared) + { rl_flush_fromclear(leftover); + } + else if (leftover == 1) + { output_plain(rl_pixel); + } + else + { output_plain(rl_basecode+leftover-2); + } + } + reset_out_clear(); +} + +static void rl_flush(void) +{ + /* UNUSED int table_reps; */ + /* UNUSED int table_extra; */ + + if (VERBOSE) printf("rl_flush [ %d %d\n",rl_count,rl_pixel); + if (rl_count == 1) + { output_plain(rl_pixel); + rl_count = 0; + if (VERBOSE) printf("rl_flush ]\n"); + return; + } + if (just_cleared) + { rl_flush_fromclear(rl_count); + } + else if ((rl_table_max < 2) || (rl_table_pixel != rl_pixel)) + { rl_flush_clearorrep(rl_count); + } + else + { rl_flush_withtable(rl_count); + } + if (VERBOSE) printf("rl_flush ]\n"); + rl_count = 0; +} + +static void GIFcompress(int init_bits, gdIOCtx *outfile, gdImagePtr im, int background) +{ + int c; + + ofile = outfile; + obuf = 0; + obits = 0; + oblen = 0; + code_clear = 1 << (init_bits - 1); + code_eof = code_clear + 1; + rl_basecode = code_eof + 1; + out_bump_init = (1 << (init_bits - 1)) - 1; + /* for images with a lot of runs, making out_clear_init larger will + give better compression. */ + out_clear_init = (init_bits <= 3) ? 9 : (out_bump_init-1); +#ifdef DEBUGGING_ENVARS + { const char *ocienv; + ocienv = getenv("GIF_OUT_CLEAR_INIT"); + if (ocienv) + { out_clear_init = atoi(ocienv); + if (VERBOSE) printf("[overriding out_clear_init to %d]\n",out_clear_init); + } + } +#endif + out_bits_init = init_bits; + max_ocodes = (1 << GIFBITS) - ((1 << (out_bits_init - 1)) + 3); + did_clear(); + output(code_clear); + rl_count = 0; + while (1) + { c = GIFNextPixel(im); + if ((rl_count > 0) && (c != rl_pixel)) rl_flush(); + if (c == EOF) break; + if (rl_pixel == c) + { rl_count ++; + } + else + { rl_pixel = c; + rl_count = 1; + } + } + output(code_eof); + output_flush(); +} + +/*----------------------------------------------------------------------- + * + * End of miGIF section - See copyright notice at start of section. + * + *----------------------------------------------------------------------- +*/ + +/****************************************************************************** + * + * GIF Specific routines + * + ******************************************************************************/ + +/* + * Number of characters so far in this 'packet' + */ +static int a_count; + +/* + * Set up the 'byte output' routine + */ + +/* UNUSED +* static void +* char_init(void) +* { +* a_count = 0; +* } +*/ + +/* + * Define the storage for the packet accumulator + */ + +/* UNUSED static char accum[ 256 ]; */ + +static void init_statics(void) { + /* Some of these are properly initialized later. What I'm doing + here is making sure code that depends on C's initialization + of statics doesn't break when the code gets called more + than once. */ + Width = 0; + Height = 0; + curx = 0; + cury = 0; + CountDown = 0; + Pass = 0; + Interlace = 0; + a_count = 0; +} + + +/* +-------------------------------------------------------------------+ */ +/* | Copyright 1990, 1991, 1993, David Koblas. (koblas@netcom.com) | */ +/* | Permission to use, copy, modify, and distribute this software | */ +/* | and its documentation for any purpose and without fee is hereby | */ +/* | granted, provided that the above copyright notice appear in all | */ +/* | copies and that both that copyright notice and this permission | */ +/* | notice appear in supporting documentation. This software is | */ +/* | provided "as is" without express or implied warranty. | */ +/* +-------------------------------------------------------------------+ */ + diff --git a/graphics/gd2/files/gd_gif_in.c b/graphics/gd2/files/gd_gif_in.c new file mode 100644 index 0000000..e600b80 --- /dev/null +++ b/graphics/gd2/files/gd_gif_in.c @@ -0,0 +1,573 @@ +#include <stdio.h> +#include <math.h> +#include <string.h> +#include <stdlib.h> +#include "gd.h" + +/* Used only when debugging GIF compression code */ +/* #define DEBUGGING_ENVARS */ + +#ifdef DEBUGGING_ENVARS + +static int verbose_set = 0; +static int verbose; +#define VERBOSE (verbose_set?verbose:set_verbose()) + +static int set_verbose(void) +{ + verbose = !!getenv("GIF_VERBOSE"); + verbose_set = 1; + return(verbose); +} + +#else + +#define VERBOSE 0 + +#endif + + +#define MAXCOLORMAPSIZE 256 + +#define TRUE 1 +#define FALSE 0 + +#define CM_RED 0 +#define CM_GREEN 1 +#define CM_BLUE 2 + +#define MAX_LWZ_BITS 12 + +#define INTERLACE 0x40 +#define LOCALCOLORMAP 0x80 +#define BitSet(byte, bit) (((byte) & (bit)) == (bit)) + +#define ReadOK(file,buffer,len) (gdGetBuf(buffer, len, file) != 0) + +#define LM_to_uint(a,b) (((b)<<8)|(a)) + +/* We may eventually want to use this information, but def it out for now */ +#if 0 +static struct { + unsigned int Width; + unsigned int Height; + unsigned char ColorMap[3][MAXCOLORMAPSIZE]; + unsigned int BitPixel; + unsigned int ColorResolution; + unsigned int Background; + unsigned int AspectRatio; +} GifScreen; +#endif + +static struct { + int transparent; + int delayTime; + int inputFlag; + int disposal; +} Gif89 = { -1, -1, -1, 0 }; + +static int ReadColorMap (gdIOCtx *fd, int number, unsigned char (*buffer)[256]); +static int DoExtension (gdIOCtx *fd, int label, int *Transparent); +static int GetDataBlock (gdIOCtx *fd, unsigned char *buf); +static int GetCode (gdIOCtx *fd, int code_size, int flag); +static int LWZReadByte (gdIOCtx *fd, int flag, int input_code_size); + +static void ReadImage (gdImagePtr im, gdIOCtx *fd, int len, int height, unsigned char (*cmap)[256], int interlace); /*1.4//, int ignore); */ + +int ZeroDataBlock; + +gdImagePtr gdImageCreateFromGifSource(gdSourcePtr inSource) +{ + gdIOCtx *in = gdNewSSCtx(inSource, NULL); + gdImagePtr im; + + im = gdImageCreateFromGifCtx(in); + + in->free(in); + + return im; +} + +gdImagePtr +gdImageCreateFromGif(FILE *fdFile) +{ + gdIOCtx *fd = gdNewFileCtx(fdFile); + gdImagePtr im = 0; + + im = gdImageCreateFromGifCtx(fd); + + fd->free(fd); + + return im; +} + +gdImagePtr +gdImageCreateFromGifCtx(gdIOCtxPtr fd) +{ +/* 1.4 int imageNumber; */ + int BitPixel; + int ColorResolution; + int Background; + int AspectRatio; + int Transparent = (-1); + unsigned char buf[16]; + unsigned char c; + unsigned char ColorMap[3][MAXCOLORMAPSIZE]; + unsigned char localColorMap[3][MAXCOLORMAPSIZE]; + int imw, imh; + int useGlobalColormap; + int bitPixel; + int i; + /*1.4//int imageCount = 0; */ + char version[4]; + + gdImagePtr im = 0; + ZeroDataBlock = FALSE; + + /*1.4//imageNumber = 1; */ + if (! ReadOK(fd,buf,6)) { + return 0; + } + if (strncmp((char *)buf,"GIF",3) != 0) { + return 0; + } + strncpy(version, (char *)buf + 3, 3); + version[3] = '\0'; + + if ((strcmp(version, "87a") != 0) && (strcmp(version, "89a") != 0)) { + return 0; + } + if (! ReadOK(fd,buf,7)) { + return 0; + } + BitPixel = 2<<(buf[4]&0x07); + ColorResolution = (int) (((buf[4]&0x70)>>3)+1); + Background = buf[5]; + AspectRatio = buf[6]; + + if (BitSet(buf[4], LOCALCOLORMAP)) { /* Global Colormap */ + if (ReadColorMap(fd, BitPixel, ColorMap)) { + return 0; + } + } + for (;;) { + if (! ReadOK(fd,&c,1)) { + return 0; + } + if (c == ';') { /* GIF terminator */ + goto terminated; + } + + if (c == '!') { /* Extension */ + if (! ReadOK(fd,&c,1)) { + return 0; + } + DoExtension(fd, c, &Transparent); + continue; + } + + if (c != ',') { /* Not a valid start character */ + continue; + } + + /*1.4//++imageCount; */ + + if (! ReadOK(fd,buf,9)) { + return 0; + } + + useGlobalColormap = ! BitSet(buf[8], LOCALCOLORMAP); + + bitPixel = 1<<((buf[8]&0x07)+1); + + imw = LM_to_uint(buf[4],buf[5]); + imh = LM_to_uint(buf[6],buf[7]); + if (!(im = gdImageCreate(imw, imh))) { + return 0; + } + im->interlace = BitSet(buf[8], INTERLACE); + if (! useGlobalColormap) { + if (ReadColorMap(fd, bitPixel, localColorMap)) { + return 0; + } + ReadImage(im, fd, imw, imh, localColorMap, + BitSet(buf[8], INTERLACE)); + /*1.4//imageCount != imageNumber); */ + } else { + ReadImage(im, fd, imw, imh, + ColorMap, + BitSet(buf[8], INTERLACE)); + /*1.4//imageCount != imageNumber); */ + } + if (Transparent != (-1)) { + gdImageColorTransparent(im, Transparent); + } + goto terminated; + } + +terminated: + /* Terminator before any image was declared! */ + if (!im) { + return 0; + } + /* Check for open colors at the end, so + we can reduce colorsTotal and ultimately + BitsPerPixel */ + for (i=((im->colorsTotal-1)); (i>=0); i--) { + if (im->open[i]) { + im->colorsTotal--; + } else { + break; + } + } + return im; +} + +static int +ReadColorMap(gdIOCtx *fd, int number, unsigned char (*buffer)[256]) +{ + int i; + unsigned char rgb[3]; + + + for (i = 0; i < number; ++i) { + if (! ReadOK(fd, rgb, sizeof(rgb))) { + return TRUE; + } + buffer[CM_RED][i] = rgb[0] ; + buffer[CM_GREEN][i] = rgb[1] ; + buffer[CM_BLUE][i] = rgb[2] ; + } + + + return FALSE; +} + +static int +DoExtension(gdIOCtx *fd, int label, int *Transparent) +{ + static unsigned char buf[256]; + + switch (label) { + case 0xf9: /* Graphic Control Extension */ + (void) GetDataBlock(fd, (unsigned char*) buf); + Gif89.disposal = (buf[0] >> 2) & 0x7; + Gif89.inputFlag = (buf[0] >> 1) & 0x1; + Gif89.delayTime = LM_to_uint(buf[1],buf[2]); + if ((buf[0] & 0x1) != 0) + *Transparent = buf[3]; + + while (GetDataBlock(fd, (unsigned char*) buf) != 0) + ; + return FALSE; + default: + break; + } + while (GetDataBlock(fd, (unsigned char*) buf) != 0) + ; + + return FALSE; +} + +static int +GetDataBlock_(gdIOCtx *fd, unsigned char *buf) +{ + unsigned char count; + + if (! ReadOK(fd,&count,1)) { + return -1; + } + + ZeroDataBlock = count == 0; + + if ((count != 0) && (! ReadOK(fd, buf, count))) { + return -1; + } + + return count; +} + +static int +GetDataBlock(gdIOCtx *fd, unsigned char *buf) +{ + int rv; + int i; + + rv = GetDataBlock_(fd,buf); + if (VERBOSE) + { printf("[GetDataBlock returning %d",rv); + if (rv > 0) + { printf(":"); + for (i=0;i<rv;i++) printf(" %02x",buf[i]); + } + printf("]\n"); + } + return(rv); +} + +static int +GetCode_(gdIOCtx *fd, int code_size, int flag) +{ + static unsigned char buf[280]; + static int curbit, lastbit, done, last_byte; + int i, j, ret; + unsigned char count; + + if (flag) { + curbit = 0; + lastbit = 0; + done = FALSE; + return 0; + } + + if ( (curbit+code_size) >= lastbit) { + if (done) { + if (curbit >= lastbit) { + /* Oh well */ + } + return -1; + } + buf[0] = buf[last_byte-2]; + buf[1] = buf[last_byte-1]; + + if ((count = GetDataBlock(fd, &buf[2])) == 0) + done = TRUE; + + last_byte = 2 + count; + curbit = (curbit - lastbit) + 16; + lastbit = (2+count)*8 ; + } + + ret = 0; + for (i = curbit, j = 0; j < code_size; ++i, ++j) + ret |= ((buf[ i / 8 ] & (1 << (i % 8))) != 0) << j; + + curbit += code_size; + return ret; +} + +static int +GetCode(gdIOCtx *fd, int code_size, int flag) +{ + int rv; + + rv = GetCode_(fd,code_size,flag); + if (VERBOSE) printf("[GetCode(,%d,%d) returning %d]\n",code_size,flag,rv); + return(rv); +} + +#define STACK_SIZE ((1<<(MAX_LWZ_BITS))*2) +static int +LWZReadByte_(gdIOCtx *fd, int flag, int input_code_size) +{ + static int fresh = FALSE; + int code, incode; + static int code_size, set_code_size; + static int max_code, max_code_size; + static int firstcode, oldcode; + static int clear_code, end_code; + static int table[2][(1<< MAX_LWZ_BITS)]; + static int stack[STACK_SIZE], *sp; + register int i; + + if (flag) { + set_code_size = input_code_size; + code_size = set_code_size+1; + clear_code = 1 << set_code_size ; + end_code = clear_code + 1; + max_code_size = 2*clear_code; + max_code = clear_code+2; + + GetCode(fd, 0, TRUE); + + fresh = TRUE; + + for (i = 0; i < clear_code; ++i) { + table[0][i] = 0; + table[1][i] = i; + } + for (; i < (1<<MAX_LWZ_BITS); ++i) + table[0][i] = table[1][0] = 0; + + sp = stack; + + return 0; + } else if (fresh) { + fresh = FALSE; + do { + firstcode = oldcode = + GetCode(fd, code_size, FALSE); + } while (firstcode == clear_code); + return firstcode; + } + + if (sp > stack) + return *--sp; + + while ((code = GetCode(fd, code_size, FALSE)) >= 0) { + if (code == clear_code) { + for (i = 0; i < clear_code; ++i) { + table[0][i] = 0; + table[1][i] = i; + } + for (; i < (1<<MAX_LWZ_BITS); ++i) + table[0][i] = table[1][i] = 0; + code_size = set_code_size+1; + max_code_size = 2*clear_code; + max_code = clear_code+2; + sp = stack; + firstcode = oldcode = + GetCode(fd, code_size, FALSE); + return firstcode; + } else if (code == end_code) { + int count; + unsigned char buf[260]; + + if (ZeroDataBlock) + return -2; + + while ((count = GetDataBlock(fd, buf)) > 0) + ; + + if (count != 0) + return -2; + } + + incode = code; + + if (sp == (stack + STACK_SIZE)) { + /* Bad compressed data stream */ + return -1; + } + + if (code >= max_code) { + *sp++ = firstcode; + code = oldcode; + } + + while (code >= clear_code) { + if (sp == (stack + STACK_SIZE)) { + /* Bad compressed data stream */ + return -1; + } + *sp++ = table[1][code]; + if (code == table[0][code]) { + /* Oh well */ + } + code = table[0][code]; + } + + *sp++ = firstcode = table[1][code]; + + if ((code = max_code) <(1<<MAX_LWZ_BITS)) { + table[0][code] = oldcode; + table[1][code] = firstcode; + ++max_code; + if ((max_code >= max_code_size) && + (max_code_size < (1<<MAX_LWZ_BITS))) { + max_code_size *= 2; + ++code_size; + } + } + + oldcode = incode; + + if (sp > stack) + return *--sp; + } + return code; +} + +static int +LWZReadByte(gdIOCtx *fd, int flag, int input_code_size) +{ + int rv; + + rv = LWZReadByte_(fd,flag,input_code_size); + if (VERBOSE) printf("[LWZReadByte(,%d,%d) returning %d]\n",flag,input_code_size,rv); + return(rv); +} + +static void +ReadImage(gdImagePtr im, gdIOCtx *fd, int len, int height, unsigned char (*cmap)[256], int interlace) /*1.4//, int ignore) */ +{ + unsigned char c; + int v; + int xpos = 0, ypos = 0, pass = 0; + int i; + /* Stash the color map into the image */ + for (i=0; (i<gdMaxColors); i++) { + im->red[i] = cmap[CM_RED][i]; + im->green[i] = cmap[CM_GREEN][i]; + im->blue[i] = cmap[CM_BLUE][i]; + im->open[i] = 1; + } + /* Many (perhaps most) of these colors will remain marked open. */ + im->colorsTotal = gdMaxColors; + /* + ** Initialize the Compression routines + */ + if (! ReadOK(fd,&c,1)) { + return; + } + if (LWZReadByte(fd, TRUE, c) < 0) { + return; + } + + /* + ** If this is an "uninteresting picture" ignore it. + ** REMOVED For 1.4 + */ + /*if (ignore) { */ + /* while (LWZReadByte(fd, FALSE, c) >= 0) */ + /* ; */ + /* return; */ + /*} */ + + while ((v = LWZReadByte(fd,FALSE,c)) >= 0 ) { + /* This how we recognize which colors are actually used. */ + if (im->open[v]) { + im->open[v] = 0; + } + gdImageSetPixel(im, xpos, ypos, v); + ++xpos; + if (xpos == len) { + xpos = 0; + if (interlace) { + switch (pass) { + case 0: + case 1: + ypos += 8; break; + case 2: + ypos += 4; break; + case 3: + ypos += 2; break; + } + + if (ypos >= height) { + ++pass; + switch (pass) { + case 1: + ypos = 4; break; + case 2: + ypos = 2; break; + case 3: + ypos = 1; break; + default: + goto fini; + } + } + } else { + ++ypos; + } + } + if (ypos >= height) + break; + } + +fini: + if (LWZReadByte(fd,FALSE,c)>=0) { + /* Ignore extra */ + } +} + diff --git a/graphics/gd2/files/gd_gif_out.c b/graphics/gd2/files/gd_gif_out.c new file mode 100644 index 0000000..7ab2f21 --- /dev/null +++ b/graphics/gd2/files/gd_gif_out.c @@ -0,0 +1,46 @@ +#include <stdio.h> +#include <math.h> +#include <string.h> +#include <stdlib.h> +#include "gd.h" + +/* +** Wrapper functions for GIF output. +*/ + +#define LZW_LICENCED + +void gdImageGifToSink(gdImagePtr im, gdSinkPtr outSink) +{ + gdIOCtx *out = gdNewSSCtx(NULL,outSink); + gdImageGifCtx(im, out); + out->free(out); +} + +void gdImageGifCtx(gdImagePtr im, gdIOCtx *out) +{ +#ifdef LZW_LICENCED + gdImageLzwCtx(im, out); +#else + gdImageBigGifCtx(im, out); +#endif +} + +void gdImageGif(gdImagePtr im, FILE *outFile) +{ +#ifdef LZW_LICENCED + gdImageLzw(im, outFile); +#else + gdImageBigGif(im, outFile); +#endif +} + +void* gdImageGifPtr(gdImagePtr im, int *size) +{ +#ifdef LZW_LICENCED + return gdImageLzwPtr(im, size); +#else + return gdImageBigGifPtr(im, size); +#endif +} + diff --git a/graphics/gd2/files/gd_lzw_out.c b/graphics/gd2/files/gd_lzw_out.c new file mode 100644 index 0000000..8c58bdf --- /dev/null +++ b/graphics/gd2/files/gd_lzw_out.c @@ -0,0 +1,795 @@ +#include <stdio.h> +#include <math.h> +#include <string.h> +#include <stdlib.h> +#include "gd.h" + +/* Code drawn from ppmtogif.c, from the pbmplus package +** +** Based on GIFENCOD by David Rowley <mgardi@watdscu.waterloo.edu>. A +** Lempel-Zim compression based on "compress". +** +** Modified by Marcel Wijkstra <wijkstra@fwi.uva.nl> +** +** Copyright (C) 1989 by Jef Poskanzer. +** +** Permission to use, copy, modify, and distribute this software and its +** documentation for any purpose and without fee is hereby granted, provided +** that the above copyright notice appear in all copies and that both that +** copyright notice and this permission notice appear in supporting +** documentation. This software is provided "as is" without express or +** implied warranty. +** +** The Graphics Interchange Format(c) is the Copyright property of +** CompuServe Incorporated. GIF(sm) is a Service Mark property of +** CompuServe Incorporated. +*/ + +/* + * a code_int must be able to hold 2**GIFBITS values of type int, and also -1 + */ +typedef int code_int; + +#ifdef SIGNED_COMPARE_SLOW +typedef unsigned long int count_int; +typedef unsigned short int count_short; +#else /*SIGNED_COMPARE_SLOW*/ +typedef long int count_int; +#endif /*SIGNED_COMPARE_SLOW*/ + +static int colorstobpp(int colors); +static void BumpPixel (void); +static int GIFNextPixel (gdImagePtr im); +static void GIFEncode (gdIOCtx *fp, int GWidth, int GHeight, int GInterlace, int Background, int Transparent, int BitsPerPixel, int *Red, int *Green, int *Blue, gdImagePtr im); +/*static void Putword (int w, gdIOCtx *fp); */ +static void compress (int init_bits, gdIOCtx *outfile, gdImagePtr im); +static void output (code_int code); +static void cl_block (void); +static void cl_hash (register count_int hsize); +static void char_init (void); +static void char_out (int c); +static void flush_char (void); +/* Allows for reuse */ +static void init_statics(void); + +void gdImageLzwCtx(gdImagePtr im, gdIOCtx *out) +{ + int interlace, transparent, BitsPerPixel; + + interlace = im->interlace; + transparent = im->transparent; + + BitsPerPixel = colorstobpp(im->colorsTotal); + /* Clear any old values in statics strewn through the GIF code */ + init_statics(); + /* All set, let's do it. */ + GIFEncode( + out, im->sx, im->sy, interlace, 0, transparent, BitsPerPixel, + im->red, im->green, im->blue, im); +} + +void gdImageLzw(gdImagePtr im, FILE *outFile) +{ + gdIOCtx *out = gdNewFileCtx(outFile); + gdImageLzwCtx(im, out); + out->free(out); +} + +void* gdImageLzwPtr(gdImagePtr im, int *size) +{ + void *rv; + gdIOCtx *out = gdNewDynamicCtx(2048, NULL); + gdImageLzwCtx(im, out); + rv = gdDPExtractData(out,size); + out->free(out); + return rv; +} + + + +static int +colorstobpp(int colors) +{ + int bpp = 0; + + if ( colors <= 2 ) + bpp = 1; + else if ( colors <= 4 ) + bpp = 2; + else if ( colors <= 8 ) + bpp = 3; + else if ( colors <= 16 ) + bpp = 4; + else if ( colors <= 32 ) + bpp = 5; + else if ( colors <= 64 ) + bpp = 6; + else if ( colors <= 128 ) + bpp = 7; + else if ( colors <= 256 ) + bpp = 8; + return bpp; + } + +/***************************************************************************** + * + * GIFENCODE.C - GIF Image compression interface + * + * GIFEncode( FName, GHeight, GWidth, GInterlace, Background, Transparent, + * BitsPerPixel, Red, Green, Blue, gdImagePtr ) + * + *****************************************************************************/ + +#define TRUE 1 +#define FALSE 0 + +static int Width, Height; +static int curx, cury; +static long CountDown; +static int Pass = 0; +static int Interlace; + +/* + * Bump the 'curx' and 'cury' to point to the next pixel + */ +static void +BumpPixel(void) +{ + /* + * Bump the current X position + */ + ++curx; + + /* + * If we are at the end of a scan line, set curx back to the beginning + * If we are interlaced, bump the cury to the appropriate spot, + * otherwise, just increment it. + */ + if( curx == Width ) { + curx = 0; + + if( !Interlace ) + ++cury; + else { + switch( Pass ) { + + case 0: + cury += 8; + if( cury >= Height ) { + ++Pass; + cury = 4; + } + break; + + case 1: + cury += 8; + if( cury >= Height ) { + ++Pass; + cury = 2; + } + break; + + case 2: + cury += 4; + if( cury >= Height ) { + ++Pass; + cury = 1; + } + break; + + case 3: + cury += 2; + break; + } + } + } +} + +/* + * Return the next pixel from the image + */ +static int +GIFNextPixel(gdImagePtr im) +{ + int r; + + if( CountDown == 0 ) + return EOF; + + --CountDown; + + r = gdImageGetPixel(im, curx, cury); + + BumpPixel(); + + return r; +} + +/* public */ + +static void +GIFEncode(gdIOCtx *fp, int GWidth, int GHeight, int GInterlace, int Background, int Transparent, int BitsPerPixel, int *Red, int *Green, int *Blue, gdImagePtr im) +{ + int B; + int RWidth, RHeight; + int LeftOfs, TopOfs; + int Resolution; + int ColorMapSize; + int InitCodeSize; + int i; + + Interlace = GInterlace; + + ColorMapSize = 1 << BitsPerPixel; + + RWidth = Width = GWidth; + RHeight = Height = GHeight; + LeftOfs = TopOfs = 0; + + Resolution = BitsPerPixel; + + /* + * Calculate number of bits we are expecting + */ + CountDown = (long)Width * (long)Height; + + /* + * Indicate which pass we are on (if interlace) + */ + Pass = 0; + + /* + * The initial code size + */ + if( BitsPerPixel <= 1 ) + InitCodeSize = 2; + else + InitCodeSize = BitsPerPixel; + + /* + * Set up the current x and y position + */ + curx = cury = 0; + + /* + * Write the Magic header + */ + gdPutBuf( Transparent < 0 ? "GIF87a" : "GIF89a", 6, fp ); + + /* + * Write out the screen width and height + */ + Putword( RWidth, fp ); + Putword( RHeight, fp ); + + /* + * Indicate that there is a global colour map + */ + B = 0x80; /* Yes, there is a color map */ + + /* + * OR in the resolution + */ + B |= (Resolution - 1) << 5; + + /* + * OR in the Bits per Pixel + */ + B |= (BitsPerPixel - 1); + + /* + * Write it out + */ + gdPutC( B, fp ); + + /* + * Write out the Background colour + */ + gdPutC( Background, fp ); + + /* + * Byte of 0's (future expansion) + */ + gdPutC( 0, fp ); + + /* + * Write out the Global Colour Map + */ + for( i=0; i<ColorMapSize; ++i ) { + gdPutC( Red[i], fp ); + gdPutC( Green[i], fp ); + gdPutC( Blue[i], fp ); + } + + /* + * Write out extension for transparent colour index, if necessary. + */ + if ( Transparent >= 0 ) { + gdPutC( '!', fp ); + gdPutC( 0xf9, fp ); + gdPutC( 4, fp ); + gdPutC( 1, fp ); + gdPutC( 0, fp ); + gdPutC( 0, fp ); + gdPutC( (unsigned char) Transparent, fp ); + gdPutC( 0, fp ); + } + + /* + * Write an Image separator + */ + gdPutC( ',', fp ); + + /* + * Write the Image header + */ + + Putword( LeftOfs, fp ); + Putword( TopOfs, fp ); + Putword( Width, fp ); + Putword( Height, fp ); + + /* + * Write out whether or not the image is interlaced + */ + if( Interlace ) + gdPutC( 0x40, fp ); + else + gdPutC( 0x00, fp ); + + /* + * Write out the initial code size + */ + gdPutC( InitCodeSize, fp ); + + /* + * Go and actually compress the data + */ + compress( InitCodeSize+1, fp, im ); + + /* + * Write out a Zero-length packet (to end the series) + */ + gdPutC( 0, fp ); + + /* + * Write the GIF file terminator + */ + gdPutC( ';', fp ); +} + +/* */ +/* * Write out a word to the GIF file */ +/* */ +/*static void */ +/*Putword(int w, FILE *fp) */ +/*{ */ +/* fputc( w & 0xff, fp ); */ +/* fputc( (w / 256) & 0xff, fp ); */ +/*} */ + + +/*************************************************************************** + * + * GIFCOMPR.C - GIF Image compression routines + * + * Lempel-Ziv compression based on 'compress'. GIF modifications by + * David Rowley (mgardi@watdcsu.waterloo.edu) + * + ***************************************************************************/ + +/* + * General DEFINEs + */ + +#define GIFBITS 12 + +#define HSIZE 5003 /* 80% occupancy */ + +#ifdef NO_UCHAR + typedef char char_type; +#else /*NO_UCHAR*/ + typedef unsigned char char_type; +#endif /*NO_UCHAR*/ + +/* + * + * GIF Image compression - modified 'compress' + * + * Based on: compress.c - File compression ala IEEE Computer, June 1984. + * + * By Authors: Spencer W. Thomas (decvax!harpo!utah-cs!utah-gr!thomas) + * Jim McKie (decvax!mcvax!jim) + * Steve Davies (decvax!vax135!petsd!peora!srd) + * Ken Turkowski (decvax!decwrl!turtlevax!ken) + * James A. Woods (decvax!ihnp4!ames!jaw) + * Joe Orost (decvax!vax135!petsd!joe) + * + */ +#include <ctype.h> + +#define ARGVAL() (*++(*argv) || (--argc && *++argv)) + +static int n_bits; /* number of bits/code */ +static int maxbits = GIFBITS; /* user settable max # bits/code */ +static code_int maxcode; /* maximum code, given n_bits */ +static code_int maxmaxcode = (code_int)1 << GIFBITS; /* should NEVER generate this code */ +#ifdef COMPATIBLE /* But wrong! */ +# define MAXCODE(n_bits) ((code_int) 1 << (n_bits) - 1) +#else /*COMPATIBLE*/ +# define MAXCODE(n_bits) (((code_int) 1 << (n_bits)) - 1) +#endif /*COMPATIBLE*/ + +static count_int htab [HSIZE]; +static unsigned short codetab [HSIZE]; +#define HashTabOf(i) htab[i] +#define CodeTabOf(i) codetab[i] + +static code_int hsize = HSIZE; /* for dynamic table sizing */ + +/* + * To save much memory, we overlay the table used by compress() with those + * used by decompress(). The tab_prefix table is the same size and type + * as the codetab. The tab_suffix table needs 2**GIFBITS characters. We + * get this from the beginning of htab. The output stack uses the rest + * of htab, and contains characters. There is plenty of room for any + * possible stack (stack used to be 8000 characters). + */ + +#define tab_prefixof(i) CodeTabOf(i) +#define tab_suffixof(i) ((char_type*)(htab))[i] +#define de_stack ((char_type*)&tab_suffixof((code_int)1<<GIFBITS)) + +static code_int free_ent = 0; /* first unused entry */ + +/* + * block compression parameters -- after all codes are used up, + * and compression rate changes, start over. + */ +static int clear_flg = 0; + +static int offset; +static long int in_count = 1; /* length of input */ +static long int out_count = 0; /* # of codes output (for debugging) */ + +/* + * compress stdin to stdout + * + * Algorithm: use open addressing double hashing (no chaining) on the + * prefix code / next character combination. We do a variant of Knuth's + * algorithm D (vol. 3, sec. 6.4) along with G. Knott's relatively-prime + * secondary probe. Here, the modular division first probe is gives way + * to a faster exclusive-or manipulation. Also do block compression with + * an adaptive reset, whereby the code table is cleared when the compression + * ratio decreases, but after the table fills. The variable-length output + * codes are re-sized at this point, and a special CLEAR code is generated + * for the decompressor. Late addition: construct the table according to + * file size for noticeable speed improvement on small files. Please direct + * questions about this implementation to ames!jaw. + */ + +static int g_init_bits; +static gdIOCtx* g_outfile; + +static int ClearCode; +static int EOFCode; + +static void +compress(int init_bits, gdIOCtx *outfile, gdImagePtr im) +{ + register long fcode; + register code_int i /* = 0 */; + register int c; + register code_int ent; + register code_int disp; + register code_int hsize_reg; + register int hshift; + + /* + * Set up the globals: g_init_bits - initial number of bits + * g_outfile - pointer to output file + */ + g_init_bits = init_bits; + g_outfile = outfile; + + /* + * Set up the necessary values + */ + offset = 0; + out_count = 0; + clear_flg = 0; + in_count = 1; + maxcode = MAXCODE(n_bits = g_init_bits); + + ClearCode = (1 << (init_bits - 1)); + EOFCode = ClearCode + 1; + free_ent = ClearCode + 2; + + char_init(); + + ent = GIFNextPixel( im ); + + hshift = 0; + for ( fcode = (long) hsize; fcode < 65536L; fcode *= 2L ) + ++hshift; + hshift = 8 - hshift; /* set hash code range bound */ + + hsize_reg = hsize; + cl_hash( (count_int) hsize_reg); /* clear hash table */ + + output( (code_int)ClearCode ); + +#ifdef SIGNED_COMPARE_SLOW + while ( (c = GIFNextPixel( im )) != (unsigned) EOF ) { +#else /*SIGNED_COMPARE_SLOW*/ + while ( (c = GIFNextPixel( im )) != EOF ) { /* } */ +#endif /*SIGNED_COMPARE_SLOW*/ + + ++in_count; + + fcode = (long) (((long) c << maxbits) + ent); + i = (((code_int)c << hshift) ^ ent); /* xor hashing */ + + if ( HashTabOf (i) == fcode ) { + ent = CodeTabOf (i); + continue; + } else if ( (long)HashTabOf (i) < 0 ) /* empty slot */ + goto nomatch; + disp = hsize_reg - i; /* secondary hash (after G. Knott) */ + if ( i == 0 ) + disp = 1; +probe: + if ( (i -= disp) < 0 ) + i += hsize_reg; + + if ( HashTabOf (i) == fcode ) { + ent = CodeTabOf (i); + continue; + } + if ( (long)HashTabOf (i) > 0 ) + goto probe; +nomatch: + output ( (code_int) ent ); + ++out_count; + ent = c; +#ifdef SIGNED_COMPARE_SLOW + if ( (unsigned) free_ent < (unsigned) maxmaxcode) { +#else /*SIGNED_COMPARE_SLOW*/ + if ( free_ent < maxmaxcode ) { /* } */ +#endif /*SIGNED_COMPARE_SLOW*/ + CodeTabOf (i) = free_ent++; /* code -> hashtable */ + HashTabOf (i) = fcode; + } else + cl_block(); + } + /* + * Put out the final code. + */ + output( (code_int)ent ); + ++out_count; + output( (code_int) EOFCode ); +} + +/***************************************************************** + * TAG( output ) + * + * Output the given code. + * Inputs: + * code: A n_bits-bit integer. If == -1, then EOF. This assumes + * that n_bits =< (long)wordsize - 1. + * Outputs: + * Outputs code to the file. + * Assumptions: + * Chars are 8 bits long. + * Algorithm: + * Maintain a GIFBITS character long buffer (so that 8 codes will + * fit in it exactly). Use the VAX insv instruction to insert each + * code in turn. When the buffer fills up empty it and start over. + */ + +static unsigned long cur_accum = 0; +static int cur_bits = 0; + +static unsigned long masks[] = { 0x0000, 0x0001, 0x0003, 0x0007, 0x000F, + 0x001F, 0x003F, 0x007F, 0x00FF, + 0x01FF, 0x03FF, 0x07FF, 0x0FFF, + 0x1FFF, 0x3FFF, 0x7FFF, 0xFFFF }; + +static void +output(code_int code) +{ + cur_accum &= masks[ cur_bits ]; + + if( cur_bits > 0 ) + cur_accum |= ((long)code << cur_bits); + else + cur_accum = code; + + cur_bits += n_bits; + + while( cur_bits >= 8 ) { + char_out( (unsigned int)(cur_accum & 0xff) ); + cur_accum >>= 8; + cur_bits -= 8; + } + + /* + * If the next entry is going to be too big for the code size, + * then increase it, if possible. + */ + if ( free_ent > maxcode || clear_flg ) { + + if( clear_flg ) { + + maxcode = MAXCODE (n_bits = g_init_bits); + clear_flg = 0; + + } else { + + ++n_bits; + if ( n_bits == maxbits ) + maxcode = maxmaxcode; + else + maxcode = MAXCODE(n_bits); + } + } + + if( code == EOFCode ) { + /* + * At EOF, write the rest of the buffer. + */ + while( cur_bits > 0 ) { + char_out( (unsigned int)(cur_accum & 0xff) ); + cur_accum >>= 8; + cur_bits -= 8; + } + + flush_char(); + +/* fflush( g_outfile ); */ +/* */ +/* if( ferror( g_outfile ) ) */ +/* return; */ + } +} + +/* + * Clear out the hash table + */ +static void +cl_block (void) /* table clear for block compress */ +{ + + cl_hash ( (count_int) hsize ); + free_ent = ClearCode + 2; + clear_flg = 1; + + output( (code_int)ClearCode ); +} + +static void +cl_hash(register count_int hsize) /* reset code table */ + +{ + + register count_int *htab_p = htab+hsize; + + register long i; + register long m1 = -1; + + i = hsize - 16; + do { /* might use Sys V memset(3) here */ + *(htab_p-16) = m1; + *(htab_p-15) = m1; + *(htab_p-14) = m1; + *(htab_p-13) = m1; + *(htab_p-12) = m1; + *(htab_p-11) = m1; + *(htab_p-10) = m1; + *(htab_p-9) = m1; + *(htab_p-8) = m1; + *(htab_p-7) = m1; + *(htab_p-6) = m1; + *(htab_p-5) = m1; + *(htab_p-4) = m1; + *(htab_p-3) = m1; + *(htab_p-2) = m1; + *(htab_p-1) = m1; + htab_p -= 16; + } while ((i -= 16) >= 0); + + for ( i += 16; i > 0; --i ) + *--htab_p = m1; +} + +/****************************************************************************** + * + * GIF Specific routines + * + ******************************************************************************/ + +/* + * Number of characters so far in this 'packet' + */ +static int a_count; + +/* + * Set up the 'byte output' routine + */ +static void +char_init(void) +{ + a_count = 0; +} + +/* + * Define the storage for the packet accumulator + */ +static char accum[ 256 ]; + +/* + * Add a character to the end of the current packet, and if it is 254 + * characters, flush the packet to disk. + */ +static void +char_out(int c) +{ + accum[ a_count++ ] = c; + if( a_count >= 254 ) + flush_char(); +} + +/* + * Flush the packet to disk, and reset the accumulator + */ +static void +flush_char(void) +{ + if( a_count > 0 ) { + gdPutC( a_count, g_outfile ); + gdPutBuf( accum, a_count, g_outfile ); + a_count = 0; + } +} + +static void init_statics(void) { + /* Some of these are properly initialized later. What I'm doing + here is making sure code that depends on C's initialization + of statics doesn't break when the code gets called more + than once. */ + Width = 0; + Height = 0; + curx = 0; + cury = 0; + CountDown = 0; + Pass = 0; + Interlace = 0; + a_count = 0; + cur_accum = 0; + cur_bits = 0; + g_init_bits = 0; + g_outfile = 0; + ClearCode = 0; + EOFCode = 0; + free_ent = 0; + clear_flg = 0; + offset = 0; + in_count = 1; + out_count = 0; + hsize = HSIZE; + n_bits = 0; + maxbits = GIFBITS; + maxcode = 0; + maxmaxcode = (code_int)1 << GIFBITS; +} + + +/* +-------------------------------------------------------------------+ */ +/* | Copyright 1990, 1991, 1993, David Koblas. (koblas@netcom.com) | */ +/* | Permission to use, copy, modify, and distribute this software | */ +/* | and its documentation for any purpose and without fee is hereby | */ +/* | granted, provided that the above copyright notice appear in all | */ +/* | copies and that both that copyright notice and this permission | */ +/* | notice appear in supporting documentation. This software is | */ +/* | provided "as is" without express or implied warranty. | */ +/* +-------------------------------------------------------------------+ */ diff --git a/graphics/gd2/files/gdcmpgif.c b/graphics/gd2/files/gdcmpgif.c new file mode 100644 index 0000000..13c2430 --- /dev/null +++ b/graphics/gd2/files/gdcmpgif.c @@ -0,0 +1,85 @@ +#include <stdio.h> +#include <unistd.h> /* For unlink function */ +#include "gd.h" + +/* A short program which converts a .png file into a .gd file, for + your convenience in creating images on the fly from a + basis image that must be loaded quickly. The .gd format + is not intended to be a general-purpose format. */ + +void CompareImages(char *msg, gdImagePtr im1, gdImagePtr im2); + + +int main(int argc, char **argv) +{ + gdImagePtr im1, im2; + FILE *in; + + if (argc != 3) { + fprintf(stderr, "Usage: gdcmpgif filename.gif filename.gif\n"); + exit(1); + } + in = fopen(argv[1], "rb"); + if (!in) { + fprintf(stderr, "Input file does not exist!\n"); + exit(1); + } + im1 = gdImageCreateFromGif(in); + fclose(in); + + if (!im1) { + fprintf(stderr, "Input is not in GIF format!\n"); + exit(1); + } + + in = fopen(argv[2], "rb"); + if (!in) { + fprintf(stderr, "Input file 2 does not exist!\n"); + exit(1); + } + im2 = gdImageCreateFromGif(in); + fclose(in); + + if (!im2) { + fprintf(stderr, "Input 2 is not in GIF format!\n"); + exit(1); + } + + CompareImages("gdcmpgif", im1, im2); + + gdImageDestroy(im1); + gdImageDestroy(im2); + + return 0; +} + +void CompareImages(char *msg, gdImagePtr im1, gdImagePtr im2) +{ + int cmpRes; + + cmpRes = gdImageCompare(im1, im2); + + if (cmpRes & GD_CMP_IMAGE) { + printf("%%%s: ERROR images differ: BAD\n",msg); + } else if (cmpRes != 0) { + printf("%%%s: WARNING images differ: WARNING - Probably OK\n",msg); + } else { + printf("%%%s: OK\n",msg); + return; + } + + if (cmpRes & (GD_CMP_SIZE_X + GD_CMP_SIZE_Y)) { + printf("-%s: INFO image sizes differ\n",msg); + } + + if (cmpRes & GD_CMP_NUM_COLORS) { + printf("-%s: INFO number of pallette entries differ %d Vs. %d\n",msg, + im1->colorsTotal, im2->colorsTotal); + } + + if (cmpRes & GD_CMP_COLOR) { + printf("-%s: INFO actual colours of pixels differ\n",msg); + } +} + + diff --git a/graphics/gd2/files/giftogd2.c b/graphics/gd2/files/giftogd2.c new file mode 100644 index 0000000..3753b56 --- /dev/null +++ b/graphics/gd2/files/giftogd2.c @@ -0,0 +1,48 @@ +#include <stdio.h> +#include <stdlib.h> + +#include "gd.h" + +/* A short program which converts a .gif file into a .gd file, for + your convenience in creating images on the fly from a + basis image that must be loaded quickly. The .gd format + is not intended to be a general-purpose format. */ + +int main(int argc, char **argv) +{ + gdImagePtr im; + FILE *in, *out; + int cs, fmt; + + if (argc != 5) { + fprintf(stderr, "Usage: giftogd2 filename.gif filename.gd2 cs fmt\n"); + fprintf(stderr, " where cs is the chunk size\n"); + fprintf(stderr, " fmt is 1 for raw, 2 for compressed\n"); + exit(1); + } + in = fopen(argv[1], "rb"); + if (!in) { + fprintf(stderr, "Input file does not exist!\n"); + exit(1); + } + im = gdImageCreateFromGif(in); + fclose(in); + if (!im) { + fprintf(stderr, "Input is not in GIF format!\n"); + exit(1); + } + out = fopen(argv[2], "wb"); + if (!out) { + fprintf(stderr, "Output file cannot be written to!\n"); + gdImageDestroy(im); + exit(1); + } + cs = atoi(argv[3]); + fmt = atoi(argv[4]); + gdImageGd2(im, out, cs, fmt); + fclose(out); + gdImageDestroy(im); + + return 0; +} + diff --git a/graphics/gd2/files/patch-Makefile b/graphics/gd2/files/patch-Makefile new file mode 100644 index 0000000..487b38c --- /dev/null +++ b/graphics/gd2/files/patch-Makefile @@ -0,0 +1,47 @@ +--- Makefile.orig Thu Apr 25 14:14:43 2002 ++++ Makefile Thu Apr 25 14:10:10 2002 +@@ -67,7 +67,7 @@ + + PROGRAMS=$(BIN_PROGRAMS) $(TEST_PROGRAMS) + +-BIN_PROGRAMS=pngtogd pngtogd2 gdtopng gd2topng gd2copypal gdparttopng webpng ++BIN_PROGRAMS=pngtogd pngtogd2 gdtopng gd2topng gd2copypal gdparttopng webpng gd2togif gdcmpgif giftogd2 + TEST_PROGRAMS=gdtest gddemo gd2time gdtestft testac + + default: instructions +@@ -94,6 +94,9 @@ + sh ./install-item 755 gd2topng $(INSTALL_BIN)/gd2topng + sh ./install-item 755 gd2copypal $(INSTALL_BIN)/gd2copypal + sh ./install-item 755 gdparttopng $(INSTALL_BIN)/gdparttopng ++ sh ./install-item 755 gd2togif $(INSTALL_BIN)/gd2togif ++ sh ./install-item 755 gdcmpgif $(INSTALL_BIN)/gdcmpgif ++ sh ./install-item 755 giftogd2 $(INSTALL_BIN)/giftogd2 + sh ./install-item 755 webpng $(INSTALL_BIN)/webpng + sh ./install-item 755 bdftogd $(INSTALL_BIN)/bdftogd + sh ./install-item 644 gd.h $(INSTALL_INCLUDE)/gd.h +@@ -141,8 +144,18 @@ + gdtestft: gdtestft.o + $(CC) --verbose gdtestft.o -o gdtestft $(LIBDIRS) $(LIBS) + ++gd2togif: gd2togif.o libgd.a ++ $(CC) --verbose gd2togif.o -o gd2togif $(LIBDIRS) $(LIBS) ++ ++gdcmpgif: gdcmpgif.o libgd.a ++ $(CC) --verbose gdcmpgif.o -o gdcmpgif $(LIBDIRS) $(LIBS) ++ ++giftogd2: giftogd2.o libgd.a ++ $(CC) --verbose giftogd2.o -o giftogd2 $(LIBDIRS) $(LIBS) ++ + LIBOBJS=gd.o gd_gd.o gd_gd2.o gd_io.o gd_io_dp.o \ + gd_io_file.o gd_ss.o gd_io_ss.o gd_png.o gd_jpeg.o gdxpm.o \ ++ gd_gif_in.o gd_gif_out.o gd_biggif_out.o gd_lzw_out.o \ + gdfontt.o gdfonts.o gdfontmb.o gdfontl.o gdfontg.o \ + gdtables.o gdft.o gdcache.o gdkanji.o wbmp.o \ + gd_wbmp.o gdhelpers.o gd_topal.o +@@ -171,5 +184,4 @@ + -ranlib libgd.a + + clean: +- rm -f *.o *.a *.so ${PROGRAMS} test/gdtest.jpg test/gdtest.wbmp +- ++ rm -f *.o *.a *.so ${PROGRAMS} test/gdtest.jpg test/gdtest.wbmp demoout.png test/fttest.png diff --git a/graphics/gd2/files/patch-gd.c b/graphics/gd2/files/patch-gd.c new file mode 100644 index 0000000..ff3512f --- /dev/null +++ b/graphics/gd2/files/patch-gd.c @@ -0,0 +1,104 @@ +--- gd.c.orig Thu Apr 25 14:15:15 2002 ++++ gd.c Thu Apr 25 12:43:55 2002 +@@ -1651,18 +1651,37 @@ + if (dst->trueColor) + { + /* 2.0: much easier when the destination is truecolor. */ ++ ++ if (src->trueColor) { + for (y = 0; (y < h); y++) + { + for (x = 0; (x < w); x++) + { + int c = gdImageGetTrueColorPixel (src, srcX + x, + srcY + y); ++ gdImageSetPixel (dst, ++ dstX + x, ++ dstY + y, ++ c); ++ } ++ } ++ ++ } ++ else { ++ /* source is palette based */ ++ for (y = 0; (y < h); y++) ++ { ++ for (x = 0; (x < w); x++) ++ { ++ int c = gdImageGetPixel (src, srcX + x, ++ srcY + y); + if (c != src->transparent) + { + gdImageSetPixel (dst, + dstX + x, + dstY + y, +- c); ++ gdTrueColor(src->red[c], src->green[c], src->blue[c])); ++ } + } + } + } +@@ -1795,18 +1814,18 @@ + else + { + dc = gdImageGetPixel (dst, tox, toy); +- g = 0.29900 * dst->red[dc] +- + 0.58700 * dst->green[dc] +- + 0.11400 * dst->blue[dc]; ++ g = 0.29900 * gdImageRed(dst,dc) ++ + 0.58700 * gdImageGreen(dst,dc) ++ + 0.11400 * gdImageBlue(dst, dc); + + ncR = gdImageRed (src, c) * (pct / 100.0) +- + gdImageRed (dst, dc) * g * ++ + g * + ((100 - pct) / 100.0); + ncG = gdImageGreen (src, c) * (pct / 100.0) +- + gdImageGreen (dst, dc) * g * ++ + g * + ((100 - pct) / 100.0); + ncB = gdImageBlue (src, c) * (pct / 100.0) +- + gdImageBlue (dst, dc) * g * ++ + g * + ((100 - pct) / 100.0); + + /* First look for an exact match */ +@@ -2211,7 +2230,17 @@ + } + + void +-gdImagePolygon (gdImagePtr im, gdPointPtr p, int n, int c) ++gdImagePolygon(gdImagePtr im, gdPointPtr p, int n, int c) ++{ ++ if (!n) { ++ return; ++ } ++ gdImageLine(im, p->x, p->y, p[n-1].x, p[n-1].y, c); ++ gdImageOpenPolygon(im, p, n, c); ++} ++ ++void ++gdImageOpenPolygon (gdImagePtr im, gdPointPtr p, int n, int c) + { + int i; + int lx, ly; +@@ -2221,7 +2250,6 @@ + } + lx = p->x; + ly = p->y; +- gdImageLine (im, lx, ly, p[n - 1].x, p[n - 1].y, c); + for (i = 1; (i < n); i++) + { + p++; +@@ -2461,8 +2489,8 @@ + { + for (x = 0; (x < sx); x++) + { +- p1 = im1->pixels[y][x]; +- p2 = im2->pixels[y][x]; ++ p1 = im1->trueColor ? gdImageTrueColorPixel(im1, x, y) : gdImagePalettePixel(im1, x, y); ++ p2 = im2->trueColor ? gdImageTrueColorPixel(im2, x, y) : gdImagePalettePixel(im2, x, y); + if (gdImageRed (im1, p1) != gdImageRed (im2, p2)) + { + cmpStatus |= GD_CMP_COLOR + GD_CMP_IMAGE; diff --git a/graphics/gd2/files/patch-gd.h b/graphics/gd2/files/patch-gd.h new file mode 100644 index 0000000..d44b8c9 --- /dev/null +++ b/graphics/gd2/files/patch-gd.h @@ -0,0 +1,67 @@ +--- gd.h.orig Thu Apr 25 14:15:24 2002 ++++ gd.h Thu Apr 25 12:43:55 2002 +@@ -201,6 +201,10 @@ + + gdImagePtr gdImageCreateFromPngSource(gdSourcePtr in); + ++gdImagePtr gdImageCreateFromGif(FILE *fd); ++gdImagePtr gdImageCreateFromGifCtx(gdIOCtxPtr in); ++gdImagePtr gdImageCreateFromGifSource(gdSourcePtr in); ++ + gdImagePtr gdImageCreateFromGd(FILE *in); + gdImagePtr gdImageCreateFromGdCtx(gdIOCtxPtr in); + +@@ -251,12 +255,26 @@ + char *gdImageStringFT(gdImage *im, int *brect, int fg, char *fontlist, + double ptsize, double angle, int x, int y, char *string); + ++typedef struct { ++ int flags; /* for future expansion logical OR of gdFTEX_ values */ ++ double linespacing; /* fine tune line spacing for '\n' */ ++} gdFTStringExtra, *gdFTStringExtraPtr; ++#define gdFTEX_LINESPACE 1 ++ ++/* FreeType 2 text output with fine tuning */ ++char * ++gdImageStringFTEx(gdImage * im, int *brect, int fg, char * fontlist, ++ double ptsize, double angle, int x, int y, char * string, ++ gdFTStringExtraPtr strex); ++ ++ + /* Point type for use in polygon drawing. */ + typedef struct { + int x, y; + } gdPoint, *gdPointPtr; + + void gdImagePolygon(gdImagePtr im, gdPointPtr p, int n, int c); ++void gdImageOpenPolygon(gdImagePtr im, gdPointPtr p, int n, int c); + void gdImageFilledPolygon(gdImagePtr im, gdPointPtr p, int n, int c); + + /* These functions still work with truecolor images, +@@ -347,6 +365,14 @@ + /* Best to free this memory with gdFree(), not free() */ + void *gdImageJpegPtr(gdImagePtr im, int *size, int quality); + ++void gdImageLzw(gdImagePtr im, FILE *out); ++void* gdImageLzwPtr(gdImagePtr im, int *size); ++void gdImageLzwCtx(gdImagePtr im, gdIOCtxPtr out); ++ ++void gdImageBigGif(gdImagePtr im, FILE *out); ++void* gdImageBigGifPtr(gdImagePtr im, int *size); ++void gdImageBigGifCtx(gdImagePtr im, gdIOCtxPtr out); ++ + /* A custom data sink. For backwards compatibility. Use + gdIOCtx instead. */ + /* The sink function must return -1 on error, otherwise the number +@@ -358,6 +384,11 @@ + } gdSink, *gdSinkPtr; + + void gdImagePngToSink(gdImagePtr im, gdSinkPtr out); ++ ++void gdImageGif(gdImagePtr im, FILE *out); ++void* gdImageGifPtr(gdImagePtr im, int *size); ++void gdImageGifCtx(gdImagePtr im, gdIOCtxPtr out); ++void gdImageGifToSink(gdImagePtr im, gdSinkPtr out); + + void gdImageGd(gdImagePtr im, FILE *out); + void gdImageGd2(gdImagePtr im, FILE *out, int cs, int fmt); diff --git a/graphics/gd2/files/patch-gd_png.c b/graphics/gd2/files/patch-gd_png.c new file mode 100644 index 0000000..f81c6db --- /dev/null +++ b/graphics/gd2/files/patch-gd_png.c @@ -0,0 +1,11 @@ +--- gd_png.c.orig Thu Apr 25 14:15:42 2002 ++++ gd_png.c Thu Apr 25 12:43:55 2002 +@@ -225,7 +225,7 @@ + im->alpha[i] = gdAlphaMax - (trans[i] >> 1); + if ((trans[i] == 0) && (firstZero)) + { +- im->transparent = i; ++ transparent = i; + firstZero = 0; + } + } diff --git a/graphics/gd2/files/patch-gdcache.h b/graphics/gd2/files/patch-gdcache.h new file mode 100644 index 0000000..c0ea11e --- /dev/null +++ b/graphics/gd2/files/patch-gdcache.h @@ -0,0 +1,11 @@ +--- gdcache.h.orig Thu Apr 25 14:16:05 2002 ++++ gdcache.h Thu Apr 25 12:48:41 2002 +@@ -40,7 +40,7 @@ + /* header */ + /*********************************************************/ + +-#include <malloc.h> ++#include <stdlib.h> + #ifndef NULL + #define NULL (void *)0 + #endif diff --git a/graphics/gd2/files/patch-gdft.c b/graphics/gd2/files/patch-gdft.c new file mode 100644 index 0000000..1426fb7 --- /dev/null +++ b/graphics/gd2/files/patch-gdft.c @@ -0,0 +1,166 @@ +--- gdft.c.orig Thu Apr 25 14:16:21 2002 ++++ gdft.c Thu Apr 25 12:43:55 2002 +@@ -513,7 +513,8 @@ + gdTrueColorGetRed (fg), + gdTrueColorGetGreen (fg), + gdTrueColorGetBlue (fg), +- gdAlphaMax - (gdTrueColorGetAlpha (fg) * pixel / NUMCOLORS)); ++ gdAlphaMax - ((gdAlphaMax - gdTrueColorGetAlpha (fg)) * pixel / NUMCOLORS) ++ ); + } + else + { +@@ -566,76 +567,53 @@ + + for (col = 0; col < bitmap.width; col++, pc++) + { +- if (bitmap.pixel_mode == ft_pixel_mode_grays) +- { ++ x = pen_x + col; ++ ++ /* clip if out of bounds */ ++ if (x >= im->sx || x < 0) ++ continue; ++ ++ switch(bitmap.pixel_mode) { ++ case ft_pixel_mode_grays: + /* + * Round to NUMCOLORS levels of antialiasing for + * index color images since only 256 colors are + * available. + */ ++ + tc_key.pixel = ((bitmap.buffer[pc] * NUMCOLORS) + + bitmap.num_grays / 2) + / (bitmap.num_grays - 1); +- } +- else if (bitmap.pixel_mode == ft_pixel_mode_mono) +- { ++ break; ++ case ft_pixel_mode_mono: + tc_key.pixel = ((bitmap.buffer[pc / 8] + << (pc % 8)) & 128) ? NUMCOLORS : 0; +- } +- else +- { ++ break; ++ default: + return "Unsupported ft_pixel_mode"; + } + + if (tc_key.pixel > 0) +- { /* if not background */ +- x = pen_x + col; +- +- /* clip if out of bounds */ +- if (x >= im->sx || x < 0) +- continue; +- /* get pixel location in gd buffer */ +- if (im->trueColor) + { +- tpixel = &im->tpixels[y][x]; ++ ++ if (im->trueColor) { ++ tc_elem = (tweencolor_t *) gdCacheGet ( ++ tc_cache, &tc_key); ++ ++ gdImageSetPixel(im, x, y, tc_elem->tweencolor); + } +- else +- { ++ else { + pixel = &im->pixels[y][x]; +- } + if (tc_key.pixel == NUMCOLORS) +- { +- /* use fg color directly */ +- if (im->trueColor) +- { +- *tpixel = fg; +- } +- else +- { + *pixel = fg; +- } +- } +- else +- { +- /* find antialised color */ +- if (im->trueColor) +- { +- tc_key.bgcolor = *tpixel; +- } +- else +- { ++ else { + tc_key.bgcolor = *pixel; +- } + tc_elem = (tweencolor_t *) gdCacheGet ( + tc_cache, &tc_key); +- if (im->trueColor) +- { +- *tpixel = tc_elem->tweencolor; +- } +- else +- { + *pixel = tc_elem->tweencolor; ++ + } ++ + } + } + } +@@ -647,11 +625,18 @@ + + /********************************************************************/ + /* gdImageStringFT - render a utf8 string onto a gd image */ +- + char * + gdImageStringFT (gdImage * im, int *brect, int fg, char *fontlist, + double ptsize, double angle, int x, int y, char *string) + { ++ return gdImageStringFTEx(im, brect, fg, fontlist, ptsize, angle, x, y, string, NULL); ++} ++ ++char * ++gdImageStringFTEx (gdImage * im, int *brect, int fg, char *fontlist, ++ double ptsize, double angle, int x, int y, char *string, ++ gdFTStringExtra * strex) ++{ + FT_BBox bbox, glyph_bbox; + FT_Matrix matrix; + FT_Vector pen, delta, penf; +@@ -672,6 +657,9 @@ + int render = (im && (im->trueColor || (fg <= 255 && fg >= -255))); + FT_BitmapGlyph bm; + ++ /* fine tuning */ ++ double linespace = LINESPACE; ++ + /***** initialize font library and font cache on first call ******/ + static gdCache_head_t *fontCache; + static FT_Library library; +@@ -704,6 +692,14 @@ + return "Could not set character size"; + } + ++ /* pull in supplied extended settings */ ++ if (strex) { ++ if (strex->flags & gdFTEX_LINESPACE == gdFTEX_LINESPACE) ++ linespace = strex->linespacing; ++ ++ } ++ ++ + matrix.xx = (FT_Fixed) (cos_a * (1 << 16)); + matrix.yx = (FT_Fixed) (sin_a * (1 << 16)); + matrix.xy = -matrix.yx; +@@ -754,7 +750,7 @@ + /* newlines */ + if (ch == '\n') + { +- penf.y -= face->size->metrics.height * LINESPACE; ++ penf.y -= face->size->metrics.height * linespace; + penf.y = (penf.y - 32) & -64; /* round to next pixel row */ + x1 = (penf.x * cos_a - penf.y * sin_a + 32) / 64; + y1 = (penf.x * sin_a + penf.y * cos_a + 32) / 64; diff --git a/graphics/gd2/files/patch-gdtest.c b/graphics/gd2/files/patch-gdtest.c new file mode 100644 index 0000000..292daae --- /dev/null +++ b/graphics/gd2/files/patch-gdtest.c @@ -0,0 +1,81 @@ +--- gdtest.c.orig Thu Apr 25 14:16:47 2002 ++++ gdtest.c Tue Nov 6 15:53:38 2001 +@@ -84,6 +84,35 @@ + gdImageDestroy (im2); + ctx->free (ctx); + ++ /* */ ++ /* Send to GIF File then Ptr */ ++ /* */ ++ sprintf(of, "%s.gif", argv[1]); ++ out = fopen(of, "wb"); ++ gdImageGif(im, out); ++ fclose(out); ++ ++ in = fopen(of, "rb"); ++ if (!in) { ++ fprintf(stderr, "GIF Output file does not exist!\n"); ++ exit(1); ++ } ++ im2 = gdImageCreateFromGif(in); ++ fclose(in); ++ ++ CompareImages("GD->GIF File->GD", ref, im2); ++ ++ unlink(of); ++ gdImageDestroy(im2); ++ ++ iptr = gdImageGifPtr(im,&sz); ++ ctx = gdNewDynamicCtx(sz,iptr); ++ im2 = gdImageCreateFromGifCtx(ctx); ++ ++ CompareImages("GD->GIF ptr->GD", ref, im2); ++ ++ gdImageDestroy(im2); ++ ctx->free(ctx); + + /* */ + /* Send to GD2 File then Ptr */ +@@ -200,7 +229,30 @@ + gdImageDestroy (im2); + }; + +- unlink (of); ++ /* ++ ** Test gdImageCreateFromGifSource ++ **/ ++ ++ in = fopen(of, "rb"); ++ ++ if (!in) ++ { ++ fprintf (stderr, "GD Source: ERROR - GD Source input file does not exist - Sink may have failed!\n"); ++ }; ++ ++ imgsrc.source = freadWrapper; ++ imgsrc.context = in; ++ im2 = gdImageCreateFromGifSource(&imgsrc); ++ fclose(in); ++ ++ if (im2 == NULL) { ++ printf("GD Source (GIF): ERROR Null returned by gdImageCreateFromGifSource\n"); ++ } else { ++ CompareImages("GD Source (GIF)", ref, im2); ++ gdImageDestroy(im2); ++ }; ++ ++ unlink(of); + + /* */ + /* Test Extraction */ +@@ -266,6 +318,10 @@ + + printf ("[Merged Image has %d colours]\n", im2->colorsTotal); + CompareImages ("Merged (gdtest.png, gdtest_merge.png)", im2, im3); ++ ++ out = fopen ("test/gdtest_merge_out.png", "wb"); ++ gdImagePng(im2, out); ++ close(out); + + gdImageDestroy (im2); + gdImageDestroy (im3); diff --git a/graphics/gd2/files/patch-gdtestft.c b/graphics/gd2/files/patch-gdtestft.c new file mode 100644 index 0000000..9f71e2a --- /dev/null +++ b/graphics/gd2/files/patch-gdtestft.c @@ -0,0 +1,99 @@ +--- gdtestft.c.orig Thu Apr 25 14:17:03 2002 ++++ gdtestft.c Wed Nov 7 00:43:02 2001 +@@ -18,6 +18,8 @@ + #define MAXY(x) MAX4(x[1],x[3],x[5],x[7]) + #define MINY(x) MIN4(x[1],x[3],x[5],x[7]) + ++void CompareImages(char *msg, gdImagePtr im1, gdImagePtr im2); ++ + int + main (int argc, char *argv[]) + { +@@ -28,13 +30,13 @@ + fprintf (stderr, "make clean, and type make again.\n"); + return 1; + #else +- gdImagePtr im; ++ gdImagePtr im, ref; + int black; + int white; + int brect[8]; + int x, y; + char *err; +- FILE *out; ++ FILE *out, *in; + #ifdef JISX0208 + char *s = "Hello. こんにちは Qyjpqg,"; /* String to draw. */ + #else +@@ -67,8 +69,8 @@ + /* create an image just big enough for the string */ + x = MAXX (brect) - MINX (brect) + 6; + y = MAXY (brect) - MINY (brect) + 6; +-#if 0 +- im = gdImageCreate (500, 500); ++#if 0 ++ im = gdImageCreate (x, y); + #else + /* gd 2.0: true color images can use freetype too */ + im = gdImageCreateTrueColor (x, y); +@@ -90,6 +92,16 @@ + fprintf (stderr, err); + return 1; + } ++ ++ in = fopen("test/fttestref.png", "rb"); ++ if (!in) { ++ fprintf(stderr, "Input file does not exist!\n"); ++ exit(1); ++ } ++ ref = gdImageCreateFromPng(in); ++ ++ fclose(in); ++ + /* TBB: Write img to test/fttest.png */ + out = fopen ("test/fttest.png", "wb"); + if (!out) +@@ -100,9 +112,43 @@ + gdImagePng (im, out); + fclose (out); + fprintf (stderr, "Test image written to test/fttest.png\n"); ++ ++ CompareImages("FTTest Image", ref, im); ++ + /* Destroy it */ + gdImageDestroy (im); ++ gdImageDestroy(ref); + + return 0; + #endif /* HAVE_FREETYPE */ + } ++ ++void CompareImages(char *msg, gdImagePtr im1, gdImagePtr im2) ++{ ++ int cmpRes; ++ ++ cmpRes = gdImageCompare(im1, im2); ++ ++ if (cmpRes & GD_CMP_IMAGE) { ++ printf("%%%s: ERROR images differ: BAD\n",msg); ++ } else if (cmpRes != 0) { ++ printf("%%%s: WARNING images differ: WARNING - Probably OK\n",msg); ++ } else { ++ printf("%%%s: OK\n",msg); ++ return; ++ } ++ ++ if (cmpRes & (GD_CMP_SIZE_X + GD_CMP_SIZE_Y)) { ++ printf("-%s: INFO image sizes differ\n",msg); ++ } ++ ++ if (cmpRes & GD_CMP_NUM_COLORS) { ++ printf("-%s: INFO number of pallette entries differ %d Vs. %d\n",msg, ++ im1->colorsTotal, im2->colorsTotal); ++ } ++ ++ if (cmpRes & GD_CMP_COLOR) { ++ printf("-%s: INFO actual colours of pixels differ\n",msg); ++ } ++} ++ diff --git a/graphics/gd2/files/patch-gif b/graphics/gd2/files/patch-gif deleted file mode 100644 index b7b3b44..0000000 --- a/graphics/gd2/files/patch-gif +++ /dev/null @@ -1,14 +0,0 @@ -This patch together with the old implementation (from gd-1.5) of -gd_gif_in.c restore GD's ability to read GIF images. The writing of such -images is troubled because of Unisys' zeal in patent enforcement. - ---- gd.h Tue Feb 6 14:44:01 2001 -+++ gd.h Fri Jul 27 16:10:38 2001 -@@ -184,1 +184,3 @@ -+gdImagePtr gdImageCreateFromGif(FILE *fd); -+gdImagePtr gdImageCreateFromGifCtx(gdIOCtxPtr in); - gdImagePtr gdImageCreateFromPng(FILE *fd); ---- gd_gif_in.c Fri Jul 27 16:13:45 2001 -+++ gd_gif_in.c Fri Jul 27 16:14:46 2001 -@@ -6,1 +6,0 @@ --#include "io.h" diff --git a/graphics/gd2/files/patch-index.html b/graphics/gd2/files/patch-index.html new file mode 100644 index 0000000..dfb4a4c --- /dev/null +++ b/graphics/gd2/files/patch-index.html @@ -0,0 +1,320 @@ +--- index.html.orig Thu Apr 25 14:17:36 2002 ++++ index.html Tue Nov 6 23:31:10 2001 +@@ -24,7 +24,12 @@ + more compatible with the major Web browsers than even PNG is. WBMP is + intended for wireless devices (not regular web browsers). Existing + code will need modification to call gdImagePng or gdImageJpeg instead +-of gdImageGif. <strong>Please do not ask us to send you the old GIF ++of gdImageGif. ++<p> ++Note: The version at this site also supports GIF format, for those people ++who have not yet managed to move away from GIFs. ++<p> ++<strong>Please do not ask the original author to send you the old GIF + version of GD.</strong> Unisys holds a patent on the LZW compression + algorithm, which is used in fully compressed GIF images. The best + solution is to move to legally unencumbered, well-compressed, +@@ -103,6 +108,18 @@ + <p> + Portions relating to libttf copyright 1999, 2000 John Ellson (ellson@lucent.com). + <p> ++GIF decompression code copyright 1990, 1991, 1993, by David Koblas ++(koblas@netcom.com). ++<p> ++Non-LZW-based GIF compression code copyright 1998, by Hutchison Avenue ++Software Corporation (<a href="http://www.hasc.com">http://www.hasc.com/</a>, ++info@hasc.com). ++<p> ++LZW-based GIF compression code David Rowley. ++Obtaining a license for the Unisys LZW compression patent is ++entirely between the user and Unisys. The authors of gd can provide ++NO assistance in this matter. ++<p> + Portions relating to JPEG and to color quantization copyright 2000, Doug + Becker and copyright (C) 1994-1998, Thomas G. Lane. This software is based + in part on the work of the Independent JPEG Group. See the file +@@ -193,6 +210,26 @@ + <li><a href="http://s27w007.pswfs.gov/tgd/">tgd</a>, by Bradley K. Sherman + <li><a href="http://www.unimelb.edu.au/fly/fly.html">fly</a>, by Martin Gleeson + </ul> ++ ++<P><A NAME="gifpatch"><H3>What's new in the patched version?</H3></A> ++ ++This version reinstates GIF support. Specifically, the following functions are added: ++<ul> ++<li><a href=#gdImageOpenPolygon>gdImageOpenPolygon</a>. This is basically the same as ++gdImagePolygon, but it does not join the start and end points. It is required by GD.pm. ++<li><a href=#gdImageGif>gdImageGif</a> ++<li><a href=#gdImageGifPtr>gdImageGifPtr</a> ++<li><a href=#gdImageGifCtx>gdImageGifCtx</a> ++<li><a href=#gdImageGifToSink>gdImageGifToSink</a> ++<li><a href=#gdImageCreateFromGif>gdImageCreateFromGif</a> ++<li><a href=#gdImageCreateFromGifCtx>gdImageCreateFromGifCtx</a> ++<li>Other functions added, but not documented, are: gdImageLzw, gdImageLzwPtr, ++gdImageLzwCtx, gdImageBigGif, gdImageBigGifPtr, gdImageBigGifCtx. ++</ul> ++<p> ++Note: While every effort has been made to ensure that the _WinNT_ build works, it has not ++been tested. ++ + <P><A NAME="whatsnew2.0.1"><H3>What's new in version 2.0.1?</H3></A> + <ul> + <li>Workaround for a bug in gcc, apparently found in gcc 2.7.2 and up. +@@ -311,6 +348,7 @@ + preprocessing them, this should not be a big problem. gd 2.0 should + read old .gd and .gd2 files correctly. + </ul> ++ + <P><A NAME="whatsnew1.8.4"><H3>What's new in version 1.8.4?</H3></A> + <ul> + <li>Add support for FreeType2 (John Ellson ellson@lucent.com) +@@ -343,6 +381,7 @@ + corrected + <li>Updated links to fast-moving, always dodging libpng and zlib web sites + </ul> ++ + <P><A NAME="whatsnew1.8.1"><H3>What's new in version 1.8.1?</H3></A> + <ul> + <li>Optional components no longer built by default (following the +@@ -420,6 +459,7 @@ + <a href="#gdImageCreateFromXpm"><code>gdImageCreateFromXpm</code></a> + function, if the Xpm library is available. Thanks to Caolan McNamara. + </ul> ++ + <P><A NAME="whatsnew1.6.3"><H3>What's new in version 1.6.3?</H3></A> + Version 1.6.3 corrects a memory leak in gd_png.c. This leak caused + a significant amount of memory to be allocated and not freed when +@@ -911,7 +951,8 @@ + <DT><A NAME="gdPoint">gdPoint</A> <strong>(TYPE)</strong> + <DD> + Represents a point in the coordinate space of the image; used +-by <A HREF="#gdImagePolygon">gdImagePolygon</A> and ++by <A HREF="#gdImagePolygon">gdImagePolygon</A>, ++<A HREF="#gdImageOpenPolygon">gdImageOpenPolygon</A>, and + <A HREF="#gdImageFilledPolygon">gdImageFilledPolygon</A>. + <PRE> + typedef struct { +@@ -921,7 +962,8 @@ + <DT><A NAME="gdPointPtr">gdPointPtr</A> <strong>(TYPE)</strong> + <DD> + A pointer to a <A HREF="#gdPoint">gdPoint</A> structure; passed +-as an argument to <A HREF="#gdImagePolygon">gdImagePolygon</A> ++as an argument to <A HREF="#gdImagePolygon">gdImagePolygon</A>, ++<A HREF="#gdImageOpenPolygon">gdImageOpenPolygon</A>, + and <A HREF="#gdImageFilledPolygon">gdImageFilledPolygon</A>. + </DL> + <DT><A NAME="gdSource">gdSource</A> <strong>(TYPE)</strong> +@@ -1024,6 +1066,75 @@ + /* ... Use the image ... */ + <A HREF="#gdImageDestroy">gdImageDestroy</A>(im); + </PRE> ++ ++<DT><A NAME="gdImageCreateFromGif">gdImageCreateFromGif(FILE *in)</A> ++<strong>(FUNCTION)</strong> ++<BR><A NAME="gdImageCreateFromGifCtx">gdImageCreateFromGifCtx(<a href=#gdioctx>gdIOCtx</a> *in)</A> ++<strong>(FUNCTION)</strong> ++<p> ++<DD> ++gdImageCreateFromGif is called to load images from GIF format files. ++Invoke gdImageCreateFromGif with an already opened pointer to a file ++containing the desired image. ++gdImageCreateFromGif ++returns a <A HREF="#gdImagePtr">gdImagePtr</A> to the new image, or NULL ++if unable to load the image (most often because the file is corrupt or ++does not contain a GIF image). gdImageCreateFromGif does <em>not</em> ++close the file. You can inspect the sx and sy members of the ++image to determine its size. The image must eventually be destroyed ++using <A HREF="#gdImageDestroy">gdImageDestroy()</A>. ++<PRE> ++<A HREF="#gdImagePtr">gdImagePtr</A> im; ++... inside a function ... ++FILE *in; ++in = fopen("mygif.gif", "rb"); ++im = gdImageCreateFromGif(in); ++fclose(in); ++/* ... Use the image ... */ ++<A HREF="#gdImageDestroy">gdImageDestroy</A>(im); ++</PRE> ++<DT><A NAME="gdImageCreateFromGifSource">gdImageCreateFromGifSource(gdSourcePtr in)</A> ++<strong>(FUNCTION)</strong> ++<dd> ++gdImageCreateFromGifSource is called to load a GIF from ++a data source other than a file. Usage is very similar to ++the <a href="#gdImageCreateFromGif">gdImageCreateFromGif</a> function, ++except that the programmer provides a custom data source. ++<p> ++The programmer must write an input function which accepts ++a context pointer, a buffer, and a number of bytes to be ++read as arguments. This function must read the number of ++bytes requested, unless the end of the file has been reached, ++in which case the function should return zero, or an error ++has occurred, in which case the function should return ++<code>-1</code>. The programmer then creates a ++<a href="#gdSource">gdSource</a> structure and sets ++the <code>source</code> pointer to the input function and ++the context pointer to any value which is useful to the ++programmer. ++<p> ++The example below ++implements <a href="#gdImageCreateFromGif">gdImageCreateFromGif</a> ++by creating a custom data source and invoking gdImageCreateFromGifSource. ++<pre> ++static int freadWrapper(void *context, char *buf, int len); ++ ++gdImagePtr gdImageCreateFromGif(FILE *in) ++{ ++ gdSource s; ++ s.source = freadWrapper; ++ s.context = in; ++ return gdImageCreateFromGifSource(&s); ++} ++ ++static int freadWrapper(void *context, char *buf, int len) ++{ ++ int got = fread(buf, 1, len, (FILE *) context); ++ return got; ++} ++</pre> ++ ++ + <DT><A NAME="gdImageCreateFromPng">gdImageCreateFromPng(FILE *in)</A> + <strong>(FUNCTION)</strong> + <BR><A NAME="gdImageCreateFromPngCtx">gdImageCreateFromPngCtx(<a href=#gdioctx>gdIOCtx</a> *in)</A> +@@ -1239,6 +1350,92 @@ + /* Now destroy it */ + <A HREF="#gdImageDestroy">gdImageDestroy</A>(im); + </PRE> ++ ++<DT><A NAME="gdImageGif"> ++void gdImageGif(gdImagePtr im, FILE *out)</A> ++<STRONG>(FUNCTION)</STRONG> ++<DD> ++gdImageGif outputs the specified image to the specified ++file in GIF format. The file must be open for writing. Under MSDOS ++and all versions of Windows, it is important to use "wb" as opposed ++to simply "w" as the mode when opening the file, and under Unix there ++is no penalty for doing so. gdImageGif does <em>not</em> ++close the file; your code must do so. ++<PRE> ++... inside a function ... ++<A HREF="#gdImagePtr">gdImagePtr</A> im; ++int black, white; ++FILE *out; ++/* Create the image */ ++im = <A HREF="#gdImageCreate">gdImageCreate</A>(100, 100); ++/* Allocate background */ ++white = <A HREF="#gdImageColorAllocate">gdImageColorAllocate</A>(im, 255, 255, 255); ++/* Allocate drawing color */ ++black = <A HREF="#gdImageColorAllocate">gdImageColorAllocate</A>(im, 0, 0, 0); ++/* Draw rectangle */ ++<A HREF="#gdImageRectangle">gdImageRectangle</A>(im, 0, 0, 99, 99, black); ++/* Open output file in binary mode */ ++out = fopen("rect.gif", "wb"); ++/* Write GIF */ ++gdImageGif(im, out); ++/* Close file */ ++fclose(out); ++/* Destroy image */ ++<A HREF="#gdImageDestroy">gdImageDestroy</A>(im); ++</PRE> ++ ++<DT><A NAME="gdImageGifCtx"> ++void* gdImageGifCtx(gdImagePtr im, gdIOCtxPtr out)</A> ++<STRONG>(FUNCTION)</STRONG> ++<DD>Identical to gdImageGif except that it writes the GIF to a ++<a href=#gdIOCtx>gdIOCtx</a>. ++<p> ++<DT><A NAME="gdImageGifPtr"> ++void* gdImageGifPtr(gdImagePtr im, int *size)</A> ++<STRONG>(FUNCTION)</STRONG> ++<DD>Identical to gdImageGif except that it returns a pointer to a memory ++area with the GIF data. This memory must be freed by the caller when it is ++no longer needed. The 'size' parameter received the total size of the block ++of memory. ++<p> ++ ++<DT><A NAME="gdImageGifToSink">gdImageGifToSink(gdImagePtr im, gdSinkPtr out)</A> ++<strong>(FUNCTION)</strong> ++<dd> ++gdImageGifToSink is called to write a GIF to ++a data "sink" (destination) other than a file. Usage is very similar to ++the <a href="#gdImageGif">gdImageGif</a> function, ++except that the programmer provides a custom data sink. ++<p> ++The programmer must write an output function which accepts ++a context pointer, a buffer, and a number of bytes to be ++written as arguments. This function must write the number of ++bytes requested and return that number, unless an error ++has occurred, in which case the function should return ++<code>-1</code>. The programmer then creates a ++<a href="#gdSink">gdSink</a> structure and sets ++the <code>sink</code> pointer to the output function and ++the context pointer to any value which is useful to the ++programmer. ++<p> ++The example below ++implements <a href="#gdImageGif">gdImageGif</a> ++by creating a custom data source and invoking gdImageGifFromSink. ++<pre> ++static int stdioSink(void *context, char *buffer, int len) ++{ ++ return fwrite(buffer, 1, len, (FILE *) context); ++} ++ ++void gdImageGif(gdImagePtr im, FILE *out) ++{ ++ gdSink mySink; ++ mySink.context = (void *) out; ++ mySink.sink = stdioSink; ++ gdImageGifToSink(im, &mySink); ++} ++</pre> ++ + <DT><A NAME="gdImageJpeg"> + void gdImageJpeg(gdImagePtr im, FILE *out, int quality)</A> + <STRONG>(FUNCTION)</STRONG><BR> +@@ -1642,6 +1839,15 @@ + /* Destroy it */ + <A HREF="#gdImageDestroy">gdImageDestroy</A>(im); + </PRE> ++ ++<DT><A NAME="gdImageOpenPolygon">void gdImageOpenPolygon(gdImagePtr im, gdPointPtr points, int pointsTotal, int color)</A> ++<STRONG>(FUNCTION)</STRONG> ++<DD> ++gdImageOpenPolygon is used to draw an open polygon (ie. series of line segments). It is almost identical ++to <A HREF="#gdImagePolygon">gdImagePolygon</A>, except that it does not join the last point to the ++first point. ++<P> ++ + <DT><A NAME="gdImageRectangle">void gdImageRectangle(gdImagePtr im, int x1, int y1, int x2, int y2, int color)</A> + <STRONG>(FUNCTION)</STRONG> + <DD> +@@ -3552,6 +3758,9 @@ + <A HREF="#gdImageCreateFromGd">gdImageCreateFromGd</A> | + <A HREF="#gdImageCreateFromGd2">gdImageCreateFromGd2</A> | + <A HREF="#gdImageCreateFromGd2Part">gdImageCreateFromGd2Part</A> | ++<A HREF="#gdImageCreateFromGif">gdImageCreateFromGif</A> | ++<A HREF="#gdImageCreateFromGifCtx">gdImageCreateFromGifCtx</A> | ++<A HREF="#gdImageCreateFromGifSource">gdImageCreateFromGifSource</A> | + <A HREF="#gdImageCreateFromJpeg">gdImageCreateFromJpeg</A> | + <A HREF="#gdImageCreateFromPng">gdImageCreateFromPng</A> | + <A HREF="#gdImageCreateFromPngSource">gdImageCreateFromPngSource</A> | +@@ -3569,6 +3778,10 @@ + <A HREF="#gdImageGetInterlaced">gdImageGetInterlaced</A> | + <A HREF="#gdImageGetPixel">gdImageGetPixel</A> | + <A HREF="#gdImageGetTransparent">gdImageGetTransparent</A> | ++<A HREF="#gdImageGif">gdImageGif</A> | ++<A HREF="#gdImageGifCtx">gdImageGifCtx</A> | ++<A HREF="#gdImageGifPtr">gdImageGifPtr</A> | ++<A HREF="#gdImageGifToSink">gdImageGifToSink</A> | + <A HREF="#gdImageGreen">gdImageGreen</A> | + <A HREF="#gdImageInterlace">gdImageInterlace</A> | + <A HREF="#gdImageJpeg">gdImageJpeg</A> | +@@ -3578,6 +3791,7 @@ + <A HREF="#gdImagePng">gdImagePng</A> | + <A HREF="#gdImagePngToSink">gdImagePngToSink</A> | + <A HREF="#gdImagePolygon">gdImagePolygon</A> | ++<A HREF="#gdImageOpenPolygon">gdImageOpenPolygon</A> | + <A HREF="#gdImagePtr">gdImagePtr</A> | + <A HREF="#gdImageWBMP">gdImageWBMP</A> | + <A HREF="#gdImageRectangle">gdImageRectangle</A> | diff --git a/graphics/gd2/files/patch-malloc b/graphics/gd2/files/patch-malloc deleted file mode 100644 index fa33bbc..0000000 --- a/graphics/gd2/files/patch-malloc +++ /dev/null @@ -1,5 +0,0 @@ ---- gdcache.h Tue Feb 6 14:44:02 2001 -+++ gdcache.h Fri Aug 24 08:10:41 2001 -@@ -43 +43 @@ --#include <malloc.h> -+#include <stdlib.h> diff --git a/graphics/gd2/files/patch-webpng.c b/graphics/gd2/files/patch-webpng.c new file mode 100644 index 0000000..fef8b31 --- /dev/null +++ b/graphics/gd2/files/patch-webpng.c @@ -0,0 +1,66 @@ +--- webpng.c.orig Thu Apr 25 14:19:03 2002 ++++ webpng.c Thu Apr 25 12:43:55 2002 +@@ -168,12 +168,12 @@ + t = gdImageGetTransparent (im); + if (t != (-1)) + { +- printf ("First 100% transparent index: %d\n", t); ++ printf ("First 100%% transparent index: %d\n", t); + } + else + { + /* -1 means the image is not transparent. */ +- printf ("First 100% transparent index: none\n"); ++ printf ("First 100%% transparent index: none\n"); + } + if (gdImageGetInterlaced (im)) + { +@@ -185,6 +185,40 @@ + } + no = 0; + } ++ else if (!strcmp(argv[i], "-a")) ++ { ++ int maxx, maxy, x, y, alpha, pix, nalpha = 0; ++ ++ maxx = gdImageSX(im); ++ maxy = gdImageSY(im); ++ ++ printf("alpha channel information:\n"); ++ ++ if (im->trueColor) { ++ for (y = 0; y < maxy; y++) { ++ for (x = 0; x < maxx; x++) { ++ pix = gdImageGetPixel(im, x, y); ++ alpha = gdTrueColorGetAlpha(pix); ++ ++ if (alpha > gdAlphaOpaque) { ++ /* Use access macros to learn colors. */ ++ printf ("%d %d %d %d\n", ++ gdTrueColorGetRed(pix), ++ gdTrueColorGetGreen(pix), ++ gdTrueColorGetBlue(pix), ++ alpha); ++ nalpha++; ++ } ++ ++ } ++ } ++ } ++ else ++ printf("NOT a true color image\n"); ++ no = 0; ++ printf("%d alpha channels\n", nalpha); ++ ++ } + else + { + fprintf (stderr, "Unknown argument: %s\n", argv[i]); +@@ -202,6 +236,7 @@ + " -l Prints the table of color indexes\n" + " -t [index] Set the transparent color to the specified index (0-255 or \"none\")\n" + " -d Reports the dimensions and other characteristics of the image.\n" ++ " -a Prints all alpha channels that are not 100%% opaque.\n" + "\n" + "If you specify '-' as the input file, stdin/stdout will be used input/output.\n" + ); diff --git a/graphics/gd2/pkg-descr b/graphics/gd2/pkg-descr index 35883e4..f7507cc 100644 --- a/graphics/gd2/pkg-descr +++ b/graphics/gd2/pkg-descr @@ -1,18 +1,16 @@ -gd is a graphics library. It allows your code to quickly draw images -complete with lines, arcs, text, multiple colors, cut and paste from -other images, and flood fills, and write out the result as a PNG or JPEG -file. This is particularly useful in World Wide Web applications, where -PNG and JPEG are two of the formats accepted for inline images by most -browsers. +gd is a graphics library. It allows your code to quickly draw images +complete with lines, arcs, text, multiple colors, cut and paste from +other images, and flood fills, and write out the result as a PNG, GIF +or JPEG file. This is particularly useful in World Wide Web applications, +where PNG, GIF and JPEG are three of the formats accepted for inline +images by most browsers. -gd does not provide for every possible desirable graphics operation. -It is not necessary or desirable for gd to become a kitchen-sink -graphics package, but version 2.0 does include most frequently requested -features, including both truecolor and palette images, resampling -(smooth resizing of truecolor images) and so forth. - -AUTHOR - gd was written by Thomas Boutell and is currently distributed by - boutell.com, Inc. +gd does not provide for every possible desirable graphics operation, +but version 2.0 does include most frequently requested features, +including both truecolor and palette images, resampling (smooth +resizing of truecolor images) and so forth. WWW: http://www.boutell.com/gd/ + +- Alex Dupre +sysadmin@alexdupre.com diff --git a/graphics/gd2/pkg-plist b/graphics/gd2/pkg-plist index 1b1b312..c26106e 100644 --- a/graphics/gd2/pkg-plist +++ b/graphics/gd2/pkg-plist @@ -1,8 +1,11 @@ bin/bdftogd bin/gd2copypal +bin/gd2togif bin/gd2topng +bin/gdcmpgif bin/gdparttopng bin/gdtopng +bin/giftogd2 bin/pngtogd bin/pngtogd2 bin/webpng @@ -16,4 +19,6 @@ include/gdfonts.h include/gdfontt.h lib/libgd.a lib/libgd.so -lib/libgd.so.3.0 +lib/libgd.so.4 +%%PORTDOCS%%share/doc/gd/index.html +%%PORTDOCS%%@dirrm share/doc/gd |