- sync to 1.6.0

master
pierre 2006-04-05 15:35:53 +00:00
parent ec7d9f2a80
commit 084ba37adc
21 changed files with 3905 additions and 2378 deletions

2710
src/gd.c

File diff suppressed because it is too large Load Diff

View File

@ -1,30 +1,22 @@
#ifndef GD_H
#define GD_H 1
/* gd.h: declarations file for the gifdraw module.
Written by Tom Boutell, 5/94.
Copyright 1994, Cold Spring Harbor Labs.
Permission granted to use this code in any fashion provided
that this notice is retained and any alterations are
labeled as such. It is requested, but not required, that
you share extensions to this module with us so that we
can incorporate them into new versions. */
/* gd.h: declarations file for the graphic-draw module.
* 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." Thomas Boutell and
* Boutell.Com, Inc. disclaim 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. */
/* stdio is needed for file I/O. */
#include <stdio.h>
#include "io.h"
#include "gd_io.h"
/* Uncomment this line if you are licensed to use LZW compression.
Licensing LZW is strictly between you and the Unisys corporation.
The authors of GD can provide NO INFORMATION WHATSOEVER
regarding licensing of LZW compression.
*/
/* #define LZW_LICENCED */
/* This can't be changed, it's part of the GIF specification. */
/* This can't be changed in the current palette-only version of gd. */
#define gdMaxColors 256
@ -93,8 +85,8 @@ typedef gdFont *gdFontPtr;
/* Functions to manipulate images. */
gdImagePtr gdImageCreate(int sx, int sy);
gdImagePtr gdImageCreateFromGif(FILE *fd);
gdImagePtr gdImageCreateFromGifCtx(gdIOCtxPtr in);
gdImagePtr gdImageCreateFromPng(FILE *fd);
gdImagePtr gdImageCreateFromPngCtx(gdIOCtxPtr in);
/* A custom data source. */
/* The source function must return -1 on error, otherwise the number
@ -106,7 +98,7 @@ typedef struct {
void *context;
} gdSource, *gdSourcePtr;
gdImagePtr gdImageCreateFromGifSource(gdSourcePtr in);
gdImagePtr gdImageCreateFromPngSource(gdSourcePtr in);
gdImagePtr gdImageCreateFromGd(FILE *in);
gdImagePtr gdImageCreateFromGdCtx(gdIOCtxPtr in);
@ -154,7 +146,7 @@ int gdImageColorExact(gdImagePtr im, int r, int g, int b);
void gdImageColorDeallocate(gdImagePtr im, int color);
void gdImageColorTransparent(gdImagePtr im, int color);
void gdImagePaletteCopy(gdImagePtr dst, gdImagePtr src);
void gdImageGif(gdImagePtr im, FILE *out);
void gdImagePng(gdImagePtr im, FILE *out);
/* A custom data sink. */
/* The sink function must return -1 on error, otherwise the number
@ -165,13 +157,11 @@ typedef struct {
void *context;
} gdSink, *gdSinkPtr;
void gdImageGifToSink(gdImagePtr im, gdSinkPtr out);
void gdImagePngToSink(gdImagePtr im, gdSinkPtr out);
void gdImageGd(gdImagePtr im, FILE *out);
void gdImageGd2(gdImagePtr im, FILE *out, int cs, int fmt);
void* gdImageGifPtr(gdImagePtr im, int *size);
void gdImageLzw(gdImagePtr im, FILE *out);
void* gdImageLzwPtr(gdImagePtr im, int *size);
void* gdImagePngPtr(gdImagePtr im, int *size);
void* gdImageGdPtr(gdImagePtr im, int *size);
void* gdImageGd2Ptr(gdImagePtr im, int cs, int fmt, int *size);
void gdImageArc(gdImagePtr im, int cx, int cy, int w, int h, int s, int e, int color);
@ -202,6 +192,14 @@ void gdImageInterlace(gdImagePtr im, int interlaceArg);
#define gdImageGetTransparent(im) ((im)->transparent)
#define gdImageGetInterlaced(im) ((im)->interlace)
/* I/O Support routines. */
gdIOCtx* gdNewFileCtx(FILE*);
gdIOCtx* gdNewDynamicCtx(int, void*);
gdIOCtx* gdNewSSCtx(gdSourcePtr in, gdSinkPtr out);
void* gdDPExtractData(struct gdIOCtx* ctx, int *size);
#define GD2_CHUNKSIZE 128
#define GD2_CHUNKSIZE_MIN 64
#define GD2_CHUNKSIZE_MAX 4096

View File

@ -1,7 +1,7 @@
#include <stdio.h>
#include "gd.h"
/* A short program which converts a .gif file into a .gd file, for
/* 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. */

View File

@ -1,7 +1,7 @@
#include <stdio.h>
#include "gd.h"
/* A short program which converts a .gif file into a .gd file, for
/* 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. */

38
src/gd2topng.c Normal file
View File

@ -0,0 +1,38 @@
#include <stdio.h>
#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. */
int main(int argc, char **argv)
{
gdImagePtr im;
FILE *in, *out;
if (argc != 3) {
fprintf(stderr, "Usage: gd2topng filename.gd2 filename.png\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 GD2 format!\n");
exit(1);
}
out = fopen(argv[2], "wb");
if (!out) {
fprintf(stderr, "Output file cannot be written to!\n");
gdImageDestroy(im);
exit(1);
}
gdImagePng(im, out);
fclose(out);
gdImageDestroy(im);
}

View File

@ -1,201 +1,200 @@
#include <stdio.h>
#include <math.h>
#include <string.h>
#include <stdlib.h>
#include "gd.h"
#include "io.h"
#define TRUE 1
#define FALSE 0
/* Exported functions: */
extern void gdImageGd(gdImagePtr im, FILE *out);
/* Use this for commenting out debug-print statements. */
/* Just use the first '#define' to allow all the prints... */
/*#define GD2_DBG(s) (s) */
#define GD2_DBG(s)
/* */
/* Shared code to read color tables from gd file. */
/* */
int _gdGetColors(gdIOCtx *in, gdImagePtr im)
{
int i;
if (!gdGetByte(&im->colorsTotal, in)) {
goto fail1;
}
if (!gdGetWord(&im->transparent, in)) {
goto fail1;
}
if (im->transparent == 257) {
im->transparent = (-1);
}
GD2_DBG(printf("Pallette had %d colours (T=%d)\n",im->colorsTotal, im->transparent));
for (i=0; (i<gdMaxColors); i++) {
if (!gdGetByte(&im->red[i], in)) {
goto fail1;
}
if (!gdGetByte(&im->green[i], in)) {
goto fail1;
}
if (!gdGetByte(&im->blue[i], in)) {
goto fail1;
}
}
for (i=0; (i < im->colorsTotal); i++) {
im->open[i] = 0;
};
return TRUE;
fail1:
return FALSE;
}
/* */
/* Use the common basic header info to make the image object. */
/* This is also called from _gd2CreateFromFile */
/* */
static
gdImagePtr _gdCreateFromFile(gdIOCtx *in, int *sx, int *sy)
{
int x, y;
int i;
gdImagePtr im;
if (!gdGetWord(sx, in)) {
goto fail1;
}
if (!gdGetWord(sy, in)) {
goto fail1;
}
GD2_DBG(printf("Image is %dx%d\n", *sx, *sy));
im = gdImageCreate(*sx, *sy);
if (!_gdGetColors(in, im)) {
goto fail2;
}
return im;
fail2:
gdImageDestroy(im);
fail1:
return 0;
}
gdImagePtr gdImageCreateFromGd(FILE *inFile)
{
gdImagePtr im;
gdIOCtx *in;
in = gdNewFileCtx(inFile);
im = gdImageCreateFromGdCtx(in);
in->free(in);
return im;
}
gdImagePtr gdImageCreateFromGdCtx(gdIOCtxPtr in)
{
int sx, sy;
int x, y;
int i;
gdImagePtr im;
/* Read the header */
im = _gdCreateFromFile(in, &sx, &sy);
if (im == NULL) {
goto fail1;
};
/* Then the data... */
for (y=0; (y<sy); y++) {
for (x=0; (x<sx); x++) {
int ch;
ch = gdGetC(in);
if (ch == EOF) {
goto fail2;
}
/* ROW-MAJOR IN GD 1.3 */
im->pixels[y][x] = ch;
}
}
return im;
fail2:
gdImageDestroy(im);
fail1:
return 0;
}
void _gdPutColors(gdImagePtr im, gdIOCtx *out)
{
int x, y;
int i;
int trans;
gdPutC((unsigned char)im->colorsTotal, out);
trans = im->transparent;
if (trans == (-1)) {
trans = 257;
}
gdPutWord(trans, out);
for (i=0; (i<gdMaxColors); i++) {
gdPutC((unsigned char)im->red[i], out);
gdPutC((unsigned char)im->green[i], out);
gdPutC((unsigned char)im->blue[i], out);
}
}
static
void _gdPutHeader(gdImagePtr im, gdIOCtx *out)
{
gdPutWord(im->sx, out);
gdPutWord(im->sy, out);
_gdPutColors(im, out);
}
static void _gdImageGd(gdImagePtr im, gdIOCtx *out)
{
int x, y;
_gdPutHeader(im, out);
for (y=0; (y < im->sy); y++) {
for (x=0; (x < im->sx); x++) {
/* ROW-MAJOR IN GD 1.3 */
gdPutC((unsigned char)im->pixels[y][x], out);
}
}
}
void gdImageGd(gdImagePtr im, FILE *outFile)
{
gdIOCtx *out = gdNewFileCtx(outFile);
_gdImageGd(im, out);
out->free(out);
}
void* gdImageGdPtr(gdImagePtr im, int *size)
{
void *rv;
gdIOCtx *out = gdNewDynamicCtx(2048, NULL);
_gdImageGd(im, out);
rv = gdDPExtractData(out,size);
out->free(out);
return rv;
}
#include <stdio.h>
#include <math.h>
#include <string.h>
#include <stdlib.h>
#include "gd.h"
#define TRUE 1
#define FALSE 0
/* Exported functions: */
extern void gdImageGd(gdImagePtr im, FILE *out);
/* Use this for commenting out debug-print statements. */
/* Just use the first '#define' to allow all the prints... */
/*#define GD2_DBG(s) (s) */
#define GD2_DBG(s)
/* */
/* Shared code to read color tables from gd file. */
/* */
int _gdGetColors(gdIOCtx *in, gdImagePtr im)
{
int i;
if (!gdGetByte(&im->colorsTotal, in)) {
goto fail1;
}
if (!gdGetWord(&im->transparent, in)) {
goto fail1;
}
if (im->transparent == 257) {
im->transparent = (-1);
}
GD2_DBG(printf("Pallette had %d colours (T=%d)\n",im->colorsTotal, im->transparent));
for (i=0; (i<gdMaxColors); i++) {
if (!gdGetByte(&im->red[i], in)) {
goto fail1;
}
if (!gdGetByte(&im->green[i], in)) {
goto fail1;
}
if (!gdGetByte(&im->blue[i], in)) {
goto fail1;
}
}
for (i=0; (i < im->colorsTotal); i++) {
im->open[i] = 0;
};
return TRUE;
fail1:
return FALSE;
}
/* */
/* Use the common basic header info to make the image object. */
/* This is also called from _gd2CreateFromFile */
/* */
static
gdImagePtr _gdCreateFromFile(gdIOCtx *in, int *sx, int *sy)
{
int x, y;
int i;
gdImagePtr im;
if (!gdGetWord(sx, in)) {
goto fail1;
}
if (!gdGetWord(sy, in)) {
goto fail1;
}
GD2_DBG(printf("Image is %dx%d\n", *sx, *sy));
im = gdImageCreate(*sx, *sy);
if (!_gdGetColors(in, im)) {
goto fail2;
}
return im;
fail2:
gdImageDestroy(im);
fail1:
return 0;
}
gdImagePtr gdImageCreateFromGd(FILE *inFile)
{
gdImagePtr im;
gdIOCtx *in;
in = gdNewFileCtx(inFile);
im = gdImageCreateFromGdCtx(in);
in->free(in);
return im;
}
gdImagePtr gdImageCreateFromGdCtx(gdIOCtxPtr in)
{
int sx, sy;
int x, y;
int i;
gdImagePtr im;
/* Read the header */
im = _gdCreateFromFile(in, &sx, &sy);
if (im == NULL) {
goto fail1;
};
/* Then the data... */
for (y=0; (y<sy); y++) {
for (x=0; (x<sx); x++) {
int ch;
ch = gdGetC(in);
if (ch == EOF) {
goto fail2;
}
/* ROW-MAJOR IN GD 1.3 */
im->pixels[y][x] = ch;
}
}
return im;
fail2:
gdImageDestroy(im);
fail1:
return 0;
}
void _gdPutColors(gdImagePtr im, gdIOCtx *out)
{
int x, y;
int i;
int trans;
gdPutC((unsigned char)im->colorsTotal, out);
trans = im->transparent;
if (trans == (-1)) {
trans = 257;
}
gdPutWord(trans, out);
for (i=0; (i<gdMaxColors); i++) {
gdPutC((unsigned char)im->red[i], out);
gdPutC((unsigned char)im->green[i], out);
gdPutC((unsigned char)im->blue[i], out);
}
}
static
void _gdPutHeader(gdImagePtr im, gdIOCtx *out)
{
gdPutWord(im->sx, out);
gdPutWord(im->sy, out);
_gdPutColors(im, out);
}
static void _gdImageGd(gdImagePtr im, gdIOCtx *out)
{
int x, y;
_gdPutHeader(im, out);
for (y=0; (y < im->sy); y++) {
for (x=0; (x < im->sx); x++) {
/* ROW-MAJOR IN GD 1.3 */
gdPutC((unsigned char)im->pixels[y][x], out);
}
}
}
void gdImageGd(gdImagePtr im, FILE *outFile)
{
gdIOCtx *out = gdNewFileCtx(outFile);
_gdImageGd(im, out);
out->free(out);
}
void* gdImageGdPtr(gdImagePtr im, int *size)
{
void *rv;
gdIOCtx *out = gdNewDynamicCtx(2048, NULL);
_gdImageGd(im, out);
rv = gdDPExtractData(out,size);
out->free(out);
return rv;
}

File diff suppressed because it is too large Load Diff

157
src/gd_io.c Normal file
View File

@ -0,0 +1,157 @@
/*
* io.c
*
* Implements the imple I/O 'helper' routines.
*
* Not really essential, but these routines were used extensively in GD,
* so they were moved here. They also make IOCtx calls look better...
*
* Written (or, at least, moved) 1999, Philip Warner.
*
*/
#include <math.h>
#include <string.h>
#include <stdlib.h>
#include "gd.h"
/* Use this for commenting out debug-print statements. */
/* Just use the first '#define' to allow all the prints... */
/*#define IO_DBG(s) (s) */
#define IO_DBG(s)
/*
* Write out a word to the I/O context pointer
*/
void
Putword(int w, gdIOCtx *ctx)
{
unsigned char buf[2];
buf[0] = w & 0xff;
buf[1] = (w / 256) & 0xff;
(ctx->putBuf)( ctx, (char *) buf, 2);
}
void
Putchar(int c, gdIOCtx *ctx)
{
(ctx->putC)( ctx, c & 0xff );
}
void gdPutC(const unsigned char c, gdIOCtx *ctx)
{
(ctx->putC)(ctx, c);
}
void
gdPutWord(int w, gdIOCtx *ctx)
{
IO_DBG(printf("Putting word...\n"));
(ctx->putC)(ctx, (unsigned char)(w >> 8));
(ctx->putC)(ctx, (unsigned char)(w & 0xFF));
IO_DBG(printf("put.\n"));
}
void gdPutInt(int w, gdIOCtx *ctx)
{
IO_DBG(printf("Putting int...\n"));
(ctx->putC)(ctx, (unsigned char)(w >> 24));
(ctx->putC)(ctx, (unsigned char)((w >> 16) & 0xFF));
(ctx->putC)(ctx, (unsigned char)((w >> 8) & 0xFF));
(ctx->putC)(ctx, (unsigned char)(w & 0xFF));
IO_DBG(printf("put.\n"));
}
int gdGetC(gdIOCtx *ctx)
{
return ((ctx->getC)(ctx));
}
int gdGetByte(int *result, gdIOCtx *ctx)
{
int r;
r = (ctx->getC)(ctx);
if (r == EOF) {
return 0;
}
*result = r;
return 1;
}
int gdGetWord(int *result, gdIOCtx *ctx)
{
int r;
r = (ctx->getC)(ctx);
if (r == EOF) {
return 0;
}
*result = r << 8;
r = (ctx->getC)(ctx);
if (r == EOF) {
return 0;
}
*result += r;
return 1;
}
int gdGetInt(int *result, gdIOCtx *ctx)
{
int r;
r = (ctx->getC)(ctx);
if (r == EOF) {
return 0;
}
*result = r << 24;
r = (ctx->getC)(ctx);
if (r == EOF) {
return 0;
}
*result += r << 16;
r = (ctx->getC)(ctx);
if (r == EOF) {
return 0;
}
*result += r << 8;
r = (ctx->getC)(ctx);
if (r == EOF) {
return 0;
}
*result += r;
return 1;
}
int gdPutBuf(const void *buf, int size, gdIOCtx* ctx)
{
IO_DBG(printf("Putting buf...\n"));
return (ctx->putBuf)(ctx, buf, size);
IO_DBG(printf("put.\n"));
}
int gdGetBuf(void *buf, int size, gdIOCtx* ctx)
{
return (ctx->getBuf)(ctx, buf, size);
}
int gdSeek(gdIOCtx *ctx, int pos)
{
IO_DBG(printf("Seeking...\n"));
return ((ctx->seek)(ctx, pos));
IO_DBG(printf("Done.\n"));
}
long gdTell(gdIOCtx *ctx)
{
IO_DBG(printf("Telling...\n"));
return ((ctx->tell)(ctx));
IO_DBG(printf("told.\n"));
}

39
src/gd_io.h Normal file
View File

@ -0,0 +1,39 @@
#ifndef GD_IO_H
#define GD_IO_H 1
#include <stdio.h>
typedef struct gdIOCtx {
int (*getC)(struct gdIOCtx*);
int (*getBuf)(struct gdIOCtx*, void*, int);
void (*putC)(struct gdIOCtx*, int);
int (*putBuf)(struct gdIOCtx*, const void*, int);
int (*seek)(struct gdIOCtx*, const int);
long (*tell)(struct gdIOCtx*);
void (*free)(struct gdIOCtx*);
} gdIOCtx;
typedef struct gdIOCtx *gdIOCtxPtr;
void Putword(int w, gdIOCtx *ctx);
void Putchar(int c, gdIOCtx *ctx);
void gdPutC(const unsigned char c, gdIOCtx *ctx);
int gdPutBuf(const void *, int, gdIOCtx*);
void gdPutWord(int w, gdIOCtx *ctx);
void gdPutInt(int w, gdIOCtx *ctx);
int gdGetC(gdIOCtx *ctx);
int gdGetBuf(void *, int, gdIOCtx*);
int gdGetByte(int *result, gdIOCtx *ctx);
int gdGetWord(int *result, gdIOCtx *ctx);
int gdGetInt(int *result, gdIOCtx *ctx);
int gdSeek(gdIOCtx *ctx, const int);
long gdTell(gdIOCtx *ctx);
#endif

375
src/gd_io_dp.c Normal file
View File

@ -0,0 +1,375 @@
/*
* io_dp.c
*
* Implements the dynamic pointer interface.
*
* Based on GD.pm code by Lincoln Stein for interfacing to libgd.
* Added support for reading as well as support for 'tell' and 'seek'.
*
* As will all I/O modules, most functions are for local use only (called
* via function pointers in the I/O context).
*
* gdDPExtractData is the exception to this: it will return the pointer to
* the internal data, and reset the internal storage.
*
* Written/Modified 1999, Philip Warner.
*
*/
#include <math.h>
#include <string.h>
#include <stdlib.h>
#include "gd.h"
#define TRUE 1
#define FALSE 0
/* this is used for creating images in main memory*/
typedef struct dpStruct {
void* data;
int logicalSize;
int realSize;
int dataGood;
int pos;
} dynamicPtr;
typedef struct dpIOCtx {
gdIOCtx ctx;
dynamicPtr *dp;
} dpIOCtx;
typedef struct dpIOCtx *dpIOCtxPtr;
/* these functions operate on in-memory dynamic pointers */
static int allocDynamic (dynamicPtr* dp,int initialSize, void *data);
static int appendDynamic (dynamicPtr* dp, const void* src, int size);
static int reallocDynamic (dynamicPtr* dp, int required);
static int trimDynamic (dynamicPtr* dp);
static void freeDynamic (dynamicPtr* dp);
static void freeDynamicCtx(struct gdIOCtx* ctx);
static dynamicPtr* newDynamic(int initialSize, void *data);
static int dynamicPutbuf( struct gdIOCtx*, const void *, int );
static void dynamicPutchar( struct gdIOCtx*, int a );
static int dynamicGetbuf( gdIOCtxPtr ctx, void *buf, int len);
static int dynamicGetchar( gdIOCtxPtr ctx );
static int dynamicSeek(struct gdIOCtx*, const int);
static long dynamicTell(struct gdIOCtx*);
/* return data as a dynamic pointer */
gdIOCtx* gdNewDynamicCtx (int initialSize, void *data) {
dpIOCtx *ctx;
dynamicPtr* dp;
ctx = (dpIOCtx*) malloc(sizeof(dpIOCtx));
if (ctx == NULL) {
return NULL;
}
dp = newDynamic(initialSize, data);
if (!dp) {
free(ctx);
return NULL;
};
ctx->dp = dp;
ctx->ctx.getC = dynamicGetchar;
ctx->ctx.putC = dynamicPutchar;
ctx->ctx.getBuf = dynamicGetbuf;
ctx->ctx.putBuf = dynamicPutbuf;
ctx->ctx.seek = dynamicSeek;
ctx->ctx.tell = dynamicTell;
ctx->ctx.free = freeDynamicCtx;
return (gdIOCtx*)ctx;
};
void* gdDPExtractData(struct gdIOCtx* ctx, int *size)
{
dynamicPtr *dp;
dpIOCtx *dctx;
void *data;
dctx = (dpIOCtx*) ctx;
dp = dctx->dp;
/* clean up the data block and return it */
if (dp->dataGood) {
trimDynamic(dp);
*size = dp->logicalSize;
data = dp->data;
} else {
*size = 0;
data = NULL;
if (dp->data != NULL) {
free(dp->data);
}
}
dp->data = NULL;
dp->realSize=0;
dp->logicalSize=0;
return data;
}
static
void freeDynamicCtx(struct gdIOCtx* ctx)
{
dynamicPtr *dp;
dpIOCtx *dctx;
dctx = (dpIOCtx*) ctx;
dp = dctx->dp;
free(ctx);
/* clean up the data block and return it */
if (dp->data != NULL) {
free(dp->data);
}
free(dp);
}
static long dynamicTell(struct gdIOCtx* ctx)
{
dpIOCtx *dctx;
dctx = (dpIOCtx*) ctx;
return (dctx->dp->pos);
}
static int dynamicSeek(struct gdIOCtx* ctx, const int pos)
{
int bytesNeeded;
char* tmp;
dynamicPtr *dp;
dpIOCtx *dctx;
dctx = (dpIOCtx*) ctx;
dp = dctx->dp;
if (!dp->dataGood) return FALSE;
bytesNeeded = pos;
if (bytesNeeded > dp->realSize) {
if (!reallocDynamic(dp,dp->realSize*2)) {
dp->dataGood = FALSE;
return FALSE;
}
}
/* if we get here, we can be sure that we have enough bytes
to copy safely */
/* Extend the logical size if we seek beyond EOF. */
if (pos > dp->logicalSize) {
dp->logicalSize = pos;
};
dp->pos = pos;
return TRUE;
}
/* return data as a dynamic pointer */
static dynamicPtr* newDynamic (int initialSize, void *data) {
dynamicPtr* dp;
dp = (dynamicPtr*) malloc(sizeof(dynamicPtr));
if (dp == NULL) {
return NULL;
}
if (!allocDynamic(dp,initialSize, data))
return NULL;
dp->pos = 0;
return dp;
};
static int
dynamicPutbuf( struct gdIOCtx* ctx, const void *buf, int size )
{
dpIOCtx *dctx;
dctx = (dpIOCtx*) ctx;
appendDynamic(dctx->dp,buf,size);
if (dctx->dp->dataGood) {
return size;
} else {
return -1;
};
}
static void
dynamicPutchar( struct gdIOCtx* ctx, int a )
{
unsigned char b;
dpIOCtxPtr dctx;
b = a;
dctx = (dpIOCtxPtr) ctx;
appendDynamic(dctx->dp,&b,1);
}
static int
dynamicGetbuf( gdIOCtxPtr ctx, void *buf, int len)
{
int rlen, remain;
dpIOCtxPtr dctx;
dynamicPtr* dp;
dctx = (dpIOCtxPtr) ctx;
dp = dctx->dp;
remain = dp->logicalSize - dp->pos;
if (remain >= len) {
rlen = len;
} else {
if (remain == 0) {
return EOF;
}
rlen = remain;
}
memcpy(buf, (void*)((int)dp->data + dp->pos), rlen);
dp->pos += rlen;
return rlen;
}
static int
dynamicGetchar( gdIOCtxPtr ctx )
{
unsigned char b;
int rv;
rv = dynamicGetbuf(ctx, &b, 1);
if (rv != 1) {
return EOF;
} else {
return b ;/* (b & 0xff); */
}
}
/* *********************************************************************
*
* InitDynamic - Return a dynamically resizable void*
*
* *********************************************************************
*/
static int
allocDynamic (dynamicPtr* dp,int initialSize, void *data) {
if (data == NULL) {
dp->logicalSize = 0;
dp->dataGood = FALSE;
dp->data = malloc(initialSize);
} else {
dp->logicalSize = initialSize;
dp->dataGood = TRUE;
dp->data = data;
}
if (dp->data !=NULL) {
dp->realSize = initialSize;
dp->dataGood = TRUE;
dp->pos = 0;
return TRUE;
} else {
dp->realSize = 0;
return FALSE;
}
}
/* append bytes to the end of a dynamic pointer */
static int
appendDynamic (dynamicPtr* dp, const void* src, int size) {
int bytesNeeded;
char* tmp;
if (!dp->dataGood) return FALSE;
/* bytesNeeded = dp->logicalSize + size; */
bytesNeeded = dp->pos + size;
if (bytesNeeded > dp->realSize) {
if (!reallocDynamic(dp,bytesNeeded*2)) {
dp->dataGood = FALSE;
return FALSE;
}
}
/* if we get here, we can be sure that we have enough bytes
to copy safely */
/*printf("Mem OK Size: %d, Pos: %d\n", dp->realSize, dp->pos); */
tmp = (char*)dp->data;
memcpy((void*)(tmp+(dp->pos)),src,size);
dp->pos += size;
if (dp->pos > dp->logicalSize) {
dp->logicalSize = dp->pos;
};
return TRUE;
}
/* grow (or shrink) dynamic pointer */
static int
reallocDynamic (dynamicPtr* dp, int required) {
void* newPtr;
/* First try realloc(). If that doesn't work, make a new
memory block and copy. */
if (newPtr = realloc(dp->data,required)) {
dp->realSize = required;
dp->data = newPtr;
return TRUE;
}
/* create a new pointer */
newPtr = malloc(required);
if (!newPtr) {
dp->dataGood = FALSE;
return FALSE;
}
/* copy the old data into it */
memcpy(newPtr,dp->data,dp->logicalSize);
free(dp->data);
dp->data = newPtr;
dp->realSize = required;
return TRUE;
}
/* trim pointer so that its real and logical sizes match */
static int
trimDynamic (dynamicPtr* dp) {
return reallocDynamic(dp,dp->logicalSize);
}
/* dispose of the dynamic pointer */
static void
freeDynamic (dynamicPtr* dp) {
if (dp->data != NULL) {
free(dp->data);
dp->data = NULL;
}
dp->realSize=0;
dp->logicalSize=0;
}

127
src/gd_io_file.c Normal file
View File

@ -0,0 +1,127 @@
/*
* io_file.c
*
* Implements the file interface.
*
* As will all I/O modules, most functions are for local use only (called
* via function pointers in the I/O context).
*
* Most functions are just 'wrappers' for standard file functions.
*
* Written/Modified 1999, Philip Warner.
*
*/
#include <math.h>
#include <string.h>
#include <stdlib.h>
#include "gd.h"
/* this is used for creating images in main memory*/
typedef struct fileIOCtx {
gdIOCtx ctx;
FILE *f;
} fileIOCtx;
struct fileIOCtx *fileIOCtxPtr;
gdIOCtx* newFileCtx(FILE *f);
static int fileGetbuf( gdIOCtx*, void *, int );
static int filePutbuf( gdIOCtx*, const void *, int );
static void filePutchar( gdIOCtx*, int );
static int fileGetchar( gdIOCtx* ctx);
static int fileSeek(struct gdIOCtx*, const int);
static long fileTell(struct gdIOCtx*);
static void freeFileCtx(gdIOCtx *ctx);
/* return data as a dynamic pointer */
gdIOCtx* gdNewFileCtx (FILE *f) {
fileIOCtx *ctx;
ctx = (fileIOCtx*) malloc(sizeof(fileIOCtx));
if (ctx == NULL) {
return NULL;
}
ctx->f = f;
ctx->ctx.getC = fileGetchar;
ctx->ctx.putC = filePutchar;
ctx->ctx.getBuf = fileGetbuf;
ctx->ctx.putBuf = filePutbuf;
ctx->ctx.tell = fileTell;
ctx->ctx.seek = fileSeek;
ctx->ctx.free = freeFileCtx;
return (gdIOCtx*)ctx;
};
static
void freeFileCtx(gdIOCtx *ctx)
{
free(ctx);
}
static int
filePutbuf( gdIOCtx* ctx, const void *buf, int size )
{
fileIOCtx *fctx;
fctx = (fileIOCtx*) ctx;
return fwrite(buf, 1, size, fctx->f);
}
static int
fileGetbuf( gdIOCtx* ctx, void *buf, int size )
{
fileIOCtx *fctx;
fctx = (fileIOCtx*) ctx;
return (fread(buf, 1, size, fctx->f));
}
static void
filePutchar( gdIOCtx* ctx, int a )
{
unsigned char b;
fileIOCtx *fctx;
fctx = (fileIOCtx*) ctx;
b = a;
putc(b, fctx->f);
}
static int fileGetchar( gdIOCtx* ctx)
{
fileIOCtx *fctx;
fctx = (fileIOCtx*) ctx;
return getc(fctx->f);
}
static int fileSeek(struct gdIOCtx* ctx, const int pos)
{
fileIOCtx *fctx;
fctx = (fileIOCtx*) ctx;
return (fseek(fctx->f, pos, SEEK_SET) == 0);
}
static long fileTell(struct gdIOCtx* ctx)
{
fileIOCtx *fctx;
fctx = (fileIOCtx*) ctx;
return ftell(fctx->f);
}

147
src/gd_io_ss.c Normal file
View File

@ -0,0 +1,147 @@
/*
* io_ss.c
*
* Implements the Source/Sink interface.
*
* As will all I/O modules, most functions are for local use only (called
* via function pointers in the I/O context).
*
* The Source/Sink model is the primary 'user' interface for alternate data
* sources; the IOCtx interface is intended (at least in version 1.5) to be
* used internally until it settles down a bit.
*
* This module just layers the Source/Sink interface on top of the IOCtx; no
* support is provided for tell/seek, so GD2 writing is not possible, and
* retrieving parts of GD2 files is also not possible.
*
* A new SS context does not need to be created with both a Source and a Sink.
*
* Written/Modified 1999, Philip Warner.
*
*/
#include <math.h>
#include <string.h>
#include <stdlib.h>
#include "gd.h"
/* this is used for creating images in main memory*/
typedef struct ssIOCtx {
gdIOCtx ctx;
gdSourcePtr src;
gdSinkPtr snk;
} ssIOCtx;
typedef struct ssIOCtx *ssIOCtxPtr;
gdIOCtx* gdNewSSCtx(gdSourcePtr src, gdSinkPtr snk);
static int sourceGetbuf( gdIOCtx*, void *, int );
static int sourceGetchar( gdIOCtx* ctx);
static int sinkPutbuf( gdIOCtx* ctx, const void *buf, int size );
static void sinkPutchar( gdIOCtx* ctx, int a );
static void freeSsCtx(gdIOCtx *ctx);
/* return data as a dynamic pointer */
gdIOCtx* gdNewSSCtx (gdSourcePtr src, gdSinkPtr snk) {
ssIOCtxPtr ctx;
ctx = (ssIOCtxPtr) malloc(sizeof(ssIOCtx));
if (ctx == NULL) {
return NULL;
}
ctx->src = src;
ctx->snk = snk;
ctx->ctx.getC = sourceGetchar;
ctx->ctx.getBuf = sourceGetbuf;
ctx->ctx.putC = sinkPutchar;
ctx->ctx.putBuf = sinkPutbuf;
ctx->ctx.tell = NULL;
ctx->ctx.seek = NULL;
ctx->ctx.free = freeSsCtx;
return (gdIOCtx*)ctx;
};
static
void freeSsCtx(gdIOCtx *ctx)
{
free(ctx);
}
static int
sourceGetbuf( gdIOCtx* ctx, void *buf, int size )
{
ssIOCtx *lctx;
int res;
lctx = (ssIOCtx*) ctx;
res = ((lctx->src->source)(lctx->src->context, buf, size));
/*
** Translate the return values from the Source object:
** 0 is EOF, -1 is error
*/
if (res == 0) {
return EOF;
} else if (res < 0) {
return 0;
} else {
return res;
};
}
static int sourceGetchar( gdIOCtx* ctx)
{
int res;
unsigned char buf;
res = sourceGetbuf(ctx, &buf, 1);
if (res == 1) {
return buf;
} else {
return EOF;
};
}
static int
sinkPutbuf( gdIOCtx* ctx, const void *buf, int size )
{
ssIOCtxPtr lctx;
int res;
lctx = (ssIOCtx*) ctx;
res = (lctx->snk->sink)(lctx->snk->context, buf, size);
if (res <= 0) {
return 0;
} else {
return res;
};
}
static void
sinkPutchar( gdIOCtx* ctx, int a )
{
unsigned char b;
b = a;
sinkPutbuf(ctx, &b, 1);
}

227
src/gd_png.c Normal file
View File

@ -0,0 +1,227 @@
#include <stdio.h>
#include <math.h>
#include <string.h>
#include <stdlib.h>
#include "gd.h"
#include "png.h"
#define TRUE 1
#define FALSE 0
/* Exported functions */
extern void gdImagePng(gdImagePtr im, FILE *out);
extern gdImagePtr gdImageCreateFromPng(FILE *in);
gdImagePtr gdImageCreateFromPng(FILE *inFile)
{
gdImagePtr im;
gdIOCtx *in = gdNewFileCtx(inFile);
im = gdImageCreateFromPngCtx(in);
in->free(in);
return im;
}
void png_read_data(png_structp png_ptr,
png_bytep data, png_size_t length)
{
gdGetBuf(data, length, (gdIOCtx *)
png_get_io_ptr(png_ptr));
}
gdImagePtr gdImageCreateFromPngCtx(gdIOCtxPtr in)
{
gdImagePtr im;
png_structp png_ptr;
png_infop info_ptr;
int i;
png_ptr = malloc(sizeof(png_struct));
if (!png_ptr) {
return 0;
}
info_ptr = malloc(sizeof(png_info));
if (!info_ptr) {
return 0;
}
if (setjmp(png_ptr->jmpbuf)) {
png_write_destroy(png_ptr);
free(png_ptr);
free(info_ptr);
return 0;
}
png_info_init(info_ptr);
png_read_init(png_ptr);
png_set_read_fn(png_ptr,
(void *) in,
png_read_data);
/* Turn non-palette PNGs into palette PNGs. This will
go away in a future 24-bit GD. It's not a very
good way of doing things. */
if (info_ptr->color_type & PNG_COLOR_MASK_COLOR) {
png_colorp std_color_cube;
int r, g, b;
int i = 0;
std_color_cube = malloc(sizeof(png_color) * 216);
for (r = 0; (r < 6); r++) {
for (g = 0; (g < 6); g++) {
for (b = 0; (b < 6); b++) {
std_color_cube[i].red =
r * 51;
std_color_cube[i].green =
g * 51;
std_color_cube[i].blue =
b * 51;
i++;
}
}
}
png_set_dither(png_ptr, std_color_cube,
216, 216,
NULL, 0);
}
png_read_info(png_ptr, info_ptr);
if (info_ptr->valid &PNG_INFO_gAMA) {
png_set_gamma(png_ptr, 2.0, info_ptr->gamma);
} else {
png_set_gamma(png_ptr, 2.0, 0.45);
}
im = gdImageCreate(info_ptr->width,
info_ptr->height);
if (!im) {
longjmp(png_ptr->jmpbuf, 1);
}
im->interlace = info_ptr->interlace_type ? 1 : 0;
png_set_strip_16(png_ptr);
png_set_packing(png_ptr);
png_read_update_info(png_ptr, info_ptr);
/* This works because gd's internal data structure
happens to be compatible at this time. */
png_read_image(png_ptr, (png_bytepp) im->pixels);
png_read_end(png_ptr, info_ptr);
for (i = 0; (i < info_ptr -> num_palette); i++) {
im->red[i] = info_ptr -> palette[i].red;
im->green[i] = info_ptr -> palette[i].green;
im->blue[i] = info_ptr -> palette[i].blue;
im->open[i] = 0;
}
im->colorsTotal = info_ptr -> num_palette;
png_destroy_read_struct(
&png_ptr, &info_ptr,
(png_infopp) 0);
return im;
}
void png_write_data(png_structp png_ptr,
png_bytep data, png_size_t length)
{
gdPutBuf(data, length, (gdIOCtx *)
png_get_io_ptr(png_ptr));
}
void png_flush_data(png_structp png_ptr)
{
}
static void _gdImagePng(gdImagePtr im, gdIOCtx *out)
{
int x, y;
int depth = 1;
int allocated = 2;
int i;
png_structp png_ptr;
png_infop info_ptr;
png_ptr = malloc(sizeof(png_struct));
if (!png_ptr) {
return;
}
info_ptr = malloc(sizeof(png_info));
if (!info_ptr) {
return;
}
if (setjmp(png_ptr->jmpbuf)) {
png_write_destroy(png_ptr);
free(png_ptr);
free(info_ptr);
return;
}
png_info_init(info_ptr);
png_write_init(png_ptr);
png_set_write_fn(png_ptr,
(void *) out,
png_write_data,
png_flush_data);
while (allocated < im->colorsTotal) {
allocated <<= 1;
depth++;
}
/* Legal PNG palette bit depths are 1, 2, 4, and 8. */
if (depth > 2) {
if (depth > 4) {
depth = 8;
} else {
depth = 4;
}
}
info_ptr->width = im->sx;
info_ptr->height = im->sy;
info_ptr->bit_depth = depth;
info_ptr->color_type = PNG_COLOR_TYPE_PALETTE;
if (im->interlace) {
info_ptr->interlace_type = 1;
} else {
info_ptr->interlace_type = 0;
}
info_ptr->valid |= PNG_INFO_PLTE;
info_ptr->palette = (png_colorp) malloc(sizeof(png_color) *
im->colorsTotal);
for (i = 0; (i < im->colorsTotal); i++) {
info_ptr->palette[i].red = im->red[i];
info_ptr->palette[i].green = im->green[i];
info_ptr->palette[i].blue = im->blue[i];
}
info_ptr->num_palette = im->colorsTotal;
if (im->transparent != -1) {
info_ptr->trans = (png_bytep) malloc(1);
info_ptr->trans[0] = im->transparent;
info_ptr->num_trans = 1;
}
png_write_info(png_ptr, info_ptr);
png_set_packing(png_ptr);
/* NOTE: this is dependent on the current
representation of pixels! It happens
to be compatible with libpng. */
png_write_image(png_ptr, (png_byte **) im->pixels);
png_write_end(png_ptr, info_ptr);
png_write_destroy(png_ptr);
if (info_ptr->palette) {
free(info_ptr->palette);
}
if (info_ptr->trans) {
free(info_ptr->trans);
}
free(png_ptr);
free(info_ptr);
}
void gdImagePng(gdImagePtr im, FILE *outFile)
{
gdIOCtx *out = gdNewFileCtx(outFile);
_gdImagePng(im, out);
out->free(out);
}
void gdImagePngCtx(gdImagePtr im, gdIOCtx *out)
{
_gdImagePng(im, out);
}
void* gdImagePngPtr(gdImagePtr im, int *size)
{
void *rv;
gdIOCtx *out = gdNewDynamicCtx(2048, NULL);
_gdImagePng(im, out);
rv = gdDPExtractData(out, size);
out->free(out);
return rv;
}

38
src/gd_ss.c Normal file
View File

@ -0,0 +1,38 @@
#include <stdio.h>
#include <math.h>
#include <string.h>
#include <stdlib.h>
#include "gd.h"
#define TRUE 1
#define FALSE 0
/* Exported functions: */
extern void gdImagePngToSink(gdImagePtr im, gdSinkPtr out);
extern gdImagePtr gdImageCreateFromPngSource(gdSourcePtr inSource);
/* Use this for commenting out debug-print statements. */
/* Just use the first '#define' to allow all the prints... */
/*#define GD_SS_DBG(s) (s) */
#define GD_SS_DBG(s)
void gdImagePngToSink(gdImagePtr im, gdSinkPtr outSink)
{
gdIOCtx *out = gdNewSSCtx(NULL,outSink);
gdImagePngCtx(im, out);
out->free(out);
}
gdImagePtr gdImageCreateFromPngSource(gdSourcePtr inSource)
{
gdIOCtx *in = gdNewSSCtx(inSource, NULL);
gdImagePtr im;
im = gdImageCreateFromPngCtx(in);
in->free(in);
return im;
}

View File

@ -33,17 +33,17 @@ int main(void)
/* Set transparent color. */
gdImageColorTransparent(im_out, white);
/* Try to load demoin.gif and paste part of it into the
/* Try to load demoin.png and paste part of it into the
output image. */
in = fopen("demoin.gif", "rb");
in = fopen("demoin.png", "rb");
if (!in) {
fprintf(stderr, "Can't load source image; this demo\n");
fprintf(stderr, "is much more impressive if demoin.gif\n");
fprintf(stderr, "is much more impressive if demoin.png\n");
fprintf(stderr, "is available.\n");
im_in = 0;
} else {
im_in = gdImageCreateFromGif(in);
im_in = gdImageCreateFromPng(in);
fclose(in);
/* Now copy, and magnify as we do so */
gdImageCopyResized(im_out, im_in,
@ -100,9 +100,9 @@ int main(void)
/* Make output image interlaced (allows "fade in" in some viewers,
and in the latest web browsers) */
gdImageInterlace(im_out, 1);
out = fopen("demoout.gif", "wb");
/* Write GIF */
gdImageGif(im_out, out);
out = fopen("demoout.png", "wb");
/* Write PNG */
gdImagePng(im_out, out);
fclose(out);
gdImageDestroy(im_out);
if (im_in) {

48
src/gdparttopng.c Normal file
View File

@ -0,0 +1,48 @@
#include <stdio.h>
#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. */
int main(int argc, char **argv)
{
gdImagePtr im;
FILE *in, *out;
int x, y, w, h;
if (argc != 7) {
fprintf(stderr, "Usage: gdparttopng filename.gd filename.png x y w h\n");
exit(1);
}
in = fopen(argv[1], "rb");
if (!in) {
fprintf(stderr, "Input file does not exist!\n");
exit(1);
}
x = atoi(argv[3]);
y = atoi(argv[4]);
w = atoi(argv[5]);
h = atoi(argv[6]);
printf("Extracting from (%d, %d), size is %dx%d\n", x, y, w, h);
im = gdImageCreateFromGd2Part(in, x, y, w, h);
fclose(in);
if (!im) {
fprintf(stderr, "Input is not in PNG format!\n");
exit(1);
}
out = fopen(argv[2], "wb");
if (!out) {
fprintf(stderr, "Output file cannot be written to!\n");
gdImageDestroy(im);
exit(1);
}
gdImagePng(im, out);
fclose(out);
gdImageDestroy(im);
}

View File

@ -1,13 +1,15 @@
#include <stdio.h>
#include "gd.h"
/* A short program which converts a .gif file into a .gd file, for
/* 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);
static int freadWrapper(void *context, char *buf, int len);
static int fwriteWrapper(void *context, const char *buffer, int len);
int main(int argc, char **argv)
{
@ -20,10 +22,11 @@ int main(int argc, char **argv)
char of[256];
int colRed, colBlu;
int idx;
gdSource imgsrc;
gdSink imgsnk;
if (argc != 2) {
fprintf(stderr, "Usage: gdtest filename.gif\n");
fprintf(stderr, "Usage: gdtest filename.png\n");
exit(1);
}
in = fopen(argv[1], "rb");
@ -31,10 +34,10 @@ int main(int argc, char **argv)
fprintf(stderr, "Input file does not exist!\n");
exit(1);
}
im = gdImageCreateFromGif(in);
im = gdImageCreateFromPng(in);
rewind(in);
ref = gdImageCreateFromGif(in);
ref = gdImageCreateFromPng(in);
fclose(in);
@ -44,31 +47,31 @@ int main(int argc, char **argv)
/* */
/* Send to GIF File then Ptr */
/* Send to PNG File then Ptr */
/* */
sprintf(of, "%s.gif", argv[1]);
sprintf(of, "%s.png", argv[1]);
out = fopen(of, "wb");
gdImageGif(im, out);
gdImagePng(im, out);
fclose(out);
in = fopen(of, "rb");
if (!in) {
fprintf(stderr, "GIF Output file does not exist!\n");
fprintf(stderr, "PNG Output file does not exist!\n");
exit(1);
}
im2 = gdImageCreateFromGif(in);
im2 = gdImageCreateFromPng(in);
fclose(in);
CompareImages("GD->GIF File->GD", ref, im2);
CompareImages("GD->PNG File->GD", ref, im2);
unlink(of);
gdImageDestroy(im2);
iptr = gdImageGifPtr(im,&sz);
iptr = gdImagePngPtr(im,&sz);
ctx = gdNewDynamicCtx(sz,iptr);
im2 = gdImageCreateFromGifCtx(ctx);
im2 = gdImageCreateFromPngCtx(ctx);
CompareImages("GD->GIF ptr->GD", ref, im2);
CompareImages("GD->PNG ptr->GD", ref, im2);
gdImageDestroy(im2);
ctx->free(ctx);
@ -141,50 +144,57 @@ int main(int argc, char **argv)
gdImageDestroy(im2);
ctx->free(ctx);
#ifdef LZW_LICENCED
/* */
/* Send to LZW File then Ptr */
/* */
sprintf(of, "%s.lzw", argv[1]);
out = fopen(of, "wb");
gdImageLzw(im, out);
fclose(out);
/*
** Test gdImageCreateFromPngSource'
**/
in = fopen(argv[1], "rb");
imgsrc.source = freadWrapper;
imgsrc.context = in;
im2 = gdImageCreateFromPngSource(&imgsrc);
fclose(in);
if (im2 == NULL) {
printf("GD Source: ERROR Null returned by gdImageCreateFromPngSource\n");
} else {
CompareImages("GD Source", ref, im2);
gdImageDestroy(im2);
};
/*
** Test gdImagePngToSink'
**/
sprintf(of, "%s.snk", argv[1]);
out = fopen(of, "wb");
imgsnk.sink = fwriteWrapper;
imgsnk.context = out;
gdImagePngToSink(im, &imgsnk);
fclose(out);
in = fopen(of, "rb");
if (!in) {
fprintf(stderr, "LZW Output file does not exist!\n");
exit(1);
}
im2 = gdImageCreateFromGif(in);
fclose(in);
fprintf(stderr, "GD Sink: ERROR - GD Sink Output file does not exist!\n");
} else {
im2 = gdImageCreateFromPng(in);
fclose(in);
CompareImages("GD->LZW File->GD", ref, im2);
CompareImages("GD Sink", ref, im2);
gdImageDestroy(im2);
};
unlink(of);
gdImageDestroy(im2);
iptr = gdImageLzwPtr(im,&sz);
/*printf("Got ptr %d (size %d)\n",iptr, sz); */
ctx = gdNewDynamicCtx(sz,iptr);
/*printf("Got ctx %d\n",ctx); */
im2 = gdImageCreateFromGifCtx(ctx);
/*printf("Got img2 %d\n",im2); */
CompareImages("GD->LZW ptr->GD", ref, im2);
gdImageDestroy(im2);
ctx->free(ctx);
#endif
unlink(of);
/* */
/* Test Extraction */
/* */
in = fopen("test/gdtest_200_300_150_100.gif", "rb");
in = fopen("test/gdtest_200_300_150_100.png", "rb");
if (!in) {
fprintf(stderr, "gdtest_200_300_150_100.gif does not exist!\n");
fprintf(stderr, "gdtest_200_300_150_100.png does not exist!\n");
exit(1);
}
im2 = gdImageCreateFromGif(in);
im2 = gdImageCreateFromPng(in);
fclose(in);
@ -196,7 +206,7 @@ int main(int argc, char **argv)
im3 = gdImageCreateFromGd2Part(in, 200, 300, 150, 100);
fclose(in);
CompareImages("GD2Part (gdtest.gd2, gdtest_200_300_150_100.gif)", im2, im3);
CompareImages("GD2Part (gdtest.gd2, gdtest_200_300_150_100.png)", im2, im3);
gdImageDestroy(im2);
gdImageDestroy(im3);
@ -204,12 +214,12 @@ int main(int argc, char **argv)
/* */
/* Copy Blend */
/* */
in = fopen("test/gdtest.gif", "rb");
in = fopen("test/gdtest.png", "rb");
if (!in) {
fprintf(stderr, "gdtest.gif does not exist!\n");
fprintf(stderr, "gdtest.png does not exist!\n");
exit(1);
}
im2 = gdImageCreateFromGif(in);
im2 = gdImageCreateFromPng(in);
fclose(in);
im3 = gdImageCreate(100, 60);
@ -226,18 +236,18 @@ int main(int argc, char **argv)
gdImageDestroy(im3);
in = fopen("test/gdtest_merge.gif", "rb");
in = fopen("test/gdtest_merge.png", "rb");
if (!in) {
fprintf(stderr, "gdtest.gd2 does not exist!\n");
exit(1);
}
im3 = gdImageCreateFromGif(in);
im3 = gdImageCreateFromPng(in);
fclose(in);
printf("[Merged Image has %d colours]\n",im2->colorsTotal);
CompareImages("Merged (gdtest.gif, gdtest_merge.gif)", im2, im3);
CompareImages("Merged (gdtest.png, gdtest_merge.png)", im2, im3);
/*out = fopen("gdtest_merge.gif", "wb"); */
/*out = fopen("gdtest_merge.png", "wb"); */
/*gdImageLzw(im2, out); */
/*fclose(out); */
@ -257,7 +267,7 @@ void CompareImages(char *msg, gdImagePtr im1, gdImagePtr im2)
bad = (1==0);
if (im1->sx != im2->sx) {
printf("%s: image x-size differs\n",msg);
printf("%s: ERROR image x-size differs\n",msg);
bad = (1==1);
}
@ -276,20 +286,20 @@ void CompareImages(char *msg, gdImagePtr im1, gdImagePtr im2)
p2 = im2->pixels[y][x];
if (im1->red[p1] != im2->red[p2]) {
printf("%s: image colours differ\n",msg);
printf("%s: ERROR image colours differ\n",msg);
bad = (1==1);
break;
}
if (im1->green[p1] != im2->green[p2]) {
printf("%s: image colours differ\n",msg);
printf("%s: ERROR image colours differ\n",msg);
bad = (1==1);
break;
}
if (im1->blue[p1] != im2->blue[p2]) {
printf("%s: image colours differ\n",msg);
printf("%s: ERROR image colours differ\n",msg);
bad = (1==1);
break;
}
@ -304,3 +314,15 @@ void CompareImages(char *msg, gdImagePtr im1, gdImagePtr im2)
}
}
static int freadWrapper(void *context, char *buf, int len)
{
int got = fread(buf, 1, len, (FILE *) context);
return got;
}
static int fwriteWrapper(void *context, const char *buffer, int len)
{
return fwrite(buffer, 1, len, (FILE *) context);
}

38
src/gdtopng.c Normal file
View File

@ -0,0 +1,38 @@
#include <stdio.h>
#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. */
int main(int argc, char **argv)
{
gdImagePtr im;
FILE *in, *out;
if (argc != 3) {
fprintf(stderr, "Usage: gdtopng filename.gd filename.png\n");
exit(1);
}
in = fopen(argv[1], "rb");
if (!in) {
fprintf(stderr, "Input file does not exist!\n");
exit(1);
}
im = gdImageCreateFromGd(in);
fclose(in);
if (!im) {
fprintf(stderr, "Input is not in PNG format!\n");
exit(1);
}
out = fopen(argv[2], "wb");
if (!out) {
fprintf(stderr, "Output file cannot be written to!\n");
gdImageDestroy(im);
exit(1);
}
gdImagePng(im, out);
fclose(out);
gdImageDestroy(im);
}

38
src/pngtogd.c Normal file
View File

@ -0,0 +1,38 @@
#include <stdio.h>
#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. */
int main(int argc, char **argv)
{
gdImagePtr im;
FILE *in, *out;
if (argc != 3) {
fprintf(stderr, "Usage: pngtogd filename.png filename.gd\n");
exit(1);
}
in = fopen(argv[1], "rb");
if (!in) {
fprintf(stderr, "Input file does not exist!\n");
exit(1);
}
im = gdImageCreateFromPng(in);
fclose(in);
if (!im) {
fprintf(stderr, "Input is not in PNG format!\n");
exit(1);
}
out = fopen(argv[2], "wb");
if (!out) {
fprintf(stderr, "Output file cannot be written to!\n");
gdImageDestroy(im);
exit(1);
}
gdImageGd(im, out);
fclose(out);
gdImageDestroy(im);
}

44
src/pngtogd2.c Normal file
View File

@ -0,0 +1,44 @@
#include <stdio.h>
#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. */
int main(int argc, char **argv)
{
gdImagePtr im;
FILE *in, *out;
int cs, fmt;
if (argc != 5) {
fprintf(stderr, "Usage: pngtogd2 filename.png 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 = gdImageCreateFromPng(in);
fclose(in);
if (!im) {
fprintf(stderr, "Input is not in PNG 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);
}

191
src/webpng.c Normal file
View File

@ -0,0 +1,191 @@
/* Bring in the gd library functions */
#include "gd.h"
/* Bring in standard I/O and string manipulation functions */
#include <stdio.h>
#include <string.h>
int main(int argc, char **argv)
{
FILE *in;
FILE *out;
char outFn[20];
int useStdinStdout=0;
/* Declare our image pointer */
gdImagePtr im = 0;
int i;
/* We'll clear 'no' once we know the user has made a
reasonable request. */
int no = 1;
/* We'll set 'write' once we know the user's request
requires that the image be written back to disk. */
int write = 0;
/* C programs always get at least one argument; we want at
least one more (the image), more in practice. */
if (argc < 2 || !strcmp(argv[1], "--help")) {
no = 1;
goto usage;
}
/* The last argument should be the image. Open the file. */
if (strcmp("-", argv[argc-1])==0) { /* - is synonymous with STDIN */
useStdinStdout = 1;
in = stdin;
} else {
in = fopen(argv[argc-1], "rb");
}
if (!in) {
fprintf(stderr,
"Error: can't open file %s.\n", argv[argc-1]);
exit(1);
}
/* Now load the image. */
im = gdImageCreateFromPng(in);
fclose(in);
/* If the load failed, it must not be a PNG file. */
if (!im) {
fprintf(stderr,
"Error: %s is not a valid png file.\n", argv[argc-1]);
exit(1);
}
/* Consider each argument in turn. */
for (i=1; (i < (argc-1)); i++) {
/* -i turns on and off interlacing. */
if (!strcmp(argv[i], "--help")) {
/* Every program should use this for help! :) */
no = 1;
goto usage;
} else if (!strcmp(argv[i], "-i")) {
if (i == (argc-2)) {
fprintf(stderr,
"Error: -i specified without y or n.\n");
no = 1;
goto usage;
}
if (!strcmp(argv[i+1], "y")) {
/* Set interlace. */
gdImageInterlace(im, 1);
} else if (!strcmp(argv[i+1], "n")) {
/* Clear interlace. */
gdImageInterlace(im, 0);
} else {
fprintf(stderr,
"Error: -i specified without y or n.\n");
no = 1;
goto usage;
}
i++;
no = 0;
write = 1;
} else if (!strcmp(argv[i], "-t")) {
/* Set transparent index (or none). */
int index;
if (i == (argc-2)) {
fprintf(stderr,
"Error: -t specified without a color table index.\n");
no = 1;
goto usage;
}
if (!strcmp(argv[i+1], "none")) {
/* -1 means not transparent. */
gdImageColorTransparent(im, -1);
} else {
/* OK, get an integer and set the index. */
index = atoi(argv[i+1]);
gdImageColorTransparent(im, index);
}
i++;
write = 1;
no = 0;
} else if (!strcmp(argv[i], "-l")) {
/* List the colors in the color table. */
int j;
/* Tabs used below. */
printf("Index Red Green Blue\n");
for (j=0; (j < gdImageColorsTotal(im)); j++) {
/* Use access macros to learn colors. */
printf("%d %d %d %d\n",
j,
gdImageRed(im, j),
gdImageGreen(im, j),
gdImageBlue(im, j));
}
no = 0;
} else if (!strcmp(argv[i], "-d")) {
/* Output dimensions, etc. */
int t;
printf("Width: %d Height: %d Colors: %d\n",
gdImageSX(im), gdImageSY(im),
gdImageColorsTotal(im));
t = gdImageGetTransparent(im);
if (t != (-1)) {
printf("Transparent index: %d\n", t);
} else {
/* -1 means the image is not transparent. */
printf("Transparent index: none\n");
}
if (gdImageGetInterlaced(im)) {
printf("Interlaced: yes\n");
} else {
printf("Interlaced: no\n");
}
no = 0;
} else {
fprintf(stderr, "Unknown argument: %s\n", argv[i]);
break;
}
}
usage:
if (no) {
/* If the command failed, output an explanation. */
fprintf(stderr,
"Usage: webpng [-i y|n ] [-l] [-t index|off ] [-d] pngname.png\n"
" -i [y|n] Turns on/off interlace\n"
" -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"
"\n"
"If you specify '-' as the input file, stdin/stdout will be used input/output.\n"
);
}
if (write) {
if (useStdinStdout) {
out = stdout;
} else {
/* Open a temporary file. */
/* "temp.tmp" is not good temporary filename. */
sprintf(outFn, "webpng.tmp%d", getpid());
out = fopen(outFn, "wb");
if (!out) {
fprintf(stderr,
"Unable to write to %s -- exiting\n", outFn);
exit(1);
}
}
/* Write the new png. */
gdImagePng(im, out);
if (!useStdinStdout) {
fclose(out);
/* Erase the old png. */
unlink(argv[argc-1]);
/* Rename the new to the old. */
if (rename(outFn, argv[argc-1])!=0) {
perror("rename");
exit(1);
}
}
}
/* Delete the image from memory. */
if (im) {
gdImageDestroy(im);
}
/* All's well that ends well. */
return 0;
}