- sync to 1.6.0
parent
ec7d9f2a80
commit
084ba37adc
54
src/gd.h
54
src/gd.h
|
@ -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
|
||||
|
|
|
@ -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. */
|
||||
|
|
|
@ -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. */
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
401
src/gd_gd.c
401
src/gd_gd.c
|
@ -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;
|
||||
}
|
||||
|
||||
|
||||
|
|
1455
src/gd_gd2.c
1455
src/gd_gd2.c
File diff suppressed because it is too large
Load Diff
|
@ -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"));
|
||||
}
|
||||
|
|
@ -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
|
|
@ -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;
|
||||
}
|
|
@ -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);
|
||||
}
|
||||
|
|
@ -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);
|
||||
|
||||
}
|
||||
|
||||
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
14
src/gddemo.c
14
src/gddemo.c
|
@ -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) {
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
138
src/gdtest.c
138
src/gdtest.c
|
@ -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);
|
||||
}
|
||||
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
@ -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);
|
||||
}
|
||||
|
|
@ -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);
|
||||
}
|
||||
|
|
@ -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;
|
||||
}
|
||||
|
Loading…
Reference in New Issue