void term_destination(j_compress_ptr cinfo) { my_dest_ptr dest = (my_dest_ptr) cinfo->dest; size_t datacount = OUTPUT_BUF_SIZE - dest->pub.free_in_buffer; /* Write any data remaining in the buffer */ if(datacount > 0) { if(gdPutBuf(dest->buffer, datacount, dest->outfile) != datacount) { ERREXIT(cinfo, JERR_FILE_WRITE); } } }
safeboolean empty_output_buffer(j_compress_ptr cinfo) { my_dest_ptr dest = (my_dest_ptr)cinfo->dest; if(gdPutBuf(dest->buffer, OUTPUT_BUF_SIZE, dest->outfile) != (size_t)OUTPUT_BUF_SIZE) { ERREXIT(cinfo, JERR_FILE_WRITE); } dest->pub.next_output_byte = dest->buffer; dest->pub.free_in_buffer = OUTPUT_BUF_SIZE; return TRUE; }
static void _gdImageGd2 (gdImagePtr im, gdIOCtx * out, int cs, int fmt) { int ncx, ncy, cx, cy; int x, y, ylo, yhi, xlo, xhi; int chunkLen; int chunkNum = 0; char *chunkData = NULL; /* So we can gdFree it with impunity. */ char *compData = NULL; /* So we can gdFree it with impunity. */ uLongf compLen; int idxPos = 0; int idxSize; t_chunk_info *chunkIdx = NULL; int posSave; int bytesPerPixel = im->trueColor ? 4 : 1; int compMax = 0; /*printf("Trying to write GD2 file\n"); */ /* */ /* Force fmt to a valid value since we don't return anything. */ /* */ if ((fmt != GD2_FMT_RAW) && (fmt != GD2_FMT_COMPRESSED)) { fmt = im->trueColor ? GD2_FMT_TRUECOLOR_COMPRESSED : GD2_FMT_COMPRESSED; }; if (im->trueColor) { fmt += 2; } /* */ /* Make sure chunk size is valid. These are arbitrary values; 64 because it seems */ /* a little silly to expect performance improvements on a 64x64 bit scale, and */ /* 4096 because we buffer one chunk, and a 16MB buffer seems a little large - it may be */ /* OK for one user, but for another to read it, they require the buffer. */ /* */ if (cs == 0) { cs = GD2_CHUNKSIZE; } else if (cs < GD2_CHUNKSIZE_MIN) { cs = GD2_CHUNKSIZE_MIN; } else if (cs > GD2_CHUNKSIZE_MAX) { cs = GD2_CHUNKSIZE_MAX; }; /* Work out number of chunks. */ ncx = im->sx / cs + 1; ncy = im->sy / cs + 1; /* Write the standard header. */ _gd2PutHeader (im, out, cs, fmt, ncx, ncy); if (gd2_compressed (fmt)) { /* */ /* Work out size of buffer for compressed data, If CHUNKSIZE is large, */ /* then these will be large! */ /* */ /* The zlib notes say output buffer size should be (input size) * 1.01 * 12 */ /* - we'll use 1.02 to be paranoid. */ /* */ compMax = cs * bytesPerPixel * cs * 1.02 + 12; /* */ /* Allocate the buffers. */ /* */ chunkData = gdCalloc (cs * bytesPerPixel * cs, 1); if (!chunkData) { goto fail; } compData = gdCalloc (compMax, 1); if (!compData) { goto fail; } /* */ /* Save the file position of chunk index, and allocate enough space for */ /* each chunk_info block . */ /* */ idxPos = gdTell (out); idxSize = ncx * ncy * sizeof (t_chunk_info); GD2_DBG (printf ("Index size is %d\n", idxSize)); gdSeek (out, idxPos + idxSize); chunkIdx = gdCalloc (idxSize * sizeof (t_chunk_info), 1); if (!chunkIdx) { goto fail; } }; _gdPutColors (im, out); GD2_DBG (printf ("Size: %dx%d\n", im->sx, im->sy)); GD2_DBG (printf ("Chunks: %dx%d\n", ncx, ncy)); for (cy = 0; (cy < ncy); cy++) { for (cx = 0; (cx < ncx); cx++) { ylo = cy * cs; yhi = ylo + cs; if (yhi > im->sy) { yhi = im->sy; }; GD2_DBG (printf ("Processing Chunk (%dx%d), y from %d to %d\n", cx, cy, ylo, yhi)); chunkLen = 0; for (y = ylo; (y < yhi); y++) { /*GD2_DBG(printf("y=%d: ",y)); */ xlo = cx * cs; xhi = xlo + cs; if (xhi > im->sx) { xhi = im->sx; }; if (gd2_compressed (fmt)) { for (x = xlo; x < xhi; x++) { /* 2.0.11: use truecolor pixel array. TBB */ /*GD2_DBG(printf("%d...",x)); */ if (im->trueColor) { int p = im->tpixels[y][x]; chunkData[chunkLen++] = gdTrueColorGetAlpha (p); chunkData[chunkLen++] = gdTrueColorGetRed (p); chunkData[chunkLen++] = gdTrueColorGetGreen (p); chunkData[chunkLen++] = gdTrueColorGetBlue (p); } else { int p = im->pixels[y][x]; chunkData[chunkLen++] = p; } }; } else { for (x = xlo; x < xhi; x++) { /*GD2_DBG(printf("%d, ",x)); */ if (im->trueColor) { gdPutInt (im->tpixels[y][x], out); } else { gdPutC ((unsigned char) im->pixels[y][x], out); } }; }; /*GD2_DBG(printf("y=%d done.\n",y)); */ }; if (gd2_compressed (fmt)) { compLen = compMax; if (compress ((unsigned char *) &compData[0], &compLen, (unsigned char *) &chunkData[0], chunkLen) != Z_OK) { printf ("Error from compressing\n"); } else { chunkIdx[chunkNum].offset = gdTell (out); chunkIdx[chunkNum++].size = compLen; GD2_DBG (printf ("Chunk %d size %d offset %d\n", chunkNum, chunkIdx[chunkNum - 1].size, chunkIdx[chunkNum - 1].offset)); if (gdPutBuf (compData, compLen, out) <= 0) { fprintf(stderr, "gd write error\n"); }; }; }; }; }; if (gd2_compressed (fmt)) { /* Save the position, write the index, restore position (paranoia). */ GD2_DBG (printf ("Seeking %d to write index\n", idxPos)); posSave = gdTell (out); gdSeek (out, idxPos); GD2_DBG (printf ("Writing index\n")); for (x = 0; x < chunkNum; x++) { GD2_DBG (printf ("Chunk %d size %d offset %d\n", x, chunkIdx[x].size, chunkIdx[x].offset)); gdPutInt (chunkIdx[x].offset, out); gdPutInt (chunkIdx[x].size, out); }; /* We don't use fwrite for *endian reasons. */ /*fwrite(chunkIdx, sizeof(int)*2, chunkNum, out); */ gdSeek (out, posSave); }; /*printf("Memory block size is %d\n",gdTell(out)); */ fail: GD2_DBG (printf ("Freeing memory\n")); if (chunkData) { gdFree (chunkData); } if (compData) { gdFree (compData); } if (chunkIdx) { gdFree (chunkIdx); } GD2_DBG (printf ("Done\n")); }
static void gdPngWriteData(png_structp png_ptr, png_bytep data, png_size_t length) { gdPutBuf(data, length, (gdIOCtx *) png_get_io_ptr(png_ptr)); }
static void GIFEncode(gdIOCtxPtr fp, int GWidth, int GHeight, int GInterlace, int Background, int Transparent, int BitsPerPixel, int *Red, int *Green, int *Blue, gdImagePtr im) { int B; int RWidth, RHeight; int LeftOfs, TopOfs; int Resolution; int ColorMapSize; int InitCodeSize; int i; GifCtx ctx; memset(&ctx, 0, sizeof(ctx)); ctx.Interlace = GInterlace; ctx.in_count = 1; ColorMapSize = 1 << BitsPerPixel; RWidth = ctx.Width = GWidth; RHeight = ctx.Height = GHeight; LeftOfs = TopOfs = 0; Resolution = BitsPerPixel; /* * Calculate number of bits we are expecting */ ctx.CountDown = (long)ctx.Width * (long)ctx.Height; /* * Indicate which pass we are on (if interlace) */ ctx.Pass = 0; /* * The initial code size */ if( BitsPerPixel <= 1 ) InitCodeSize = 2; else InitCodeSize = BitsPerPixel; /* * Set up the current x and y position */ ctx.curx = ctx.cury = 0; /* * Write the Magic header */ gdPutBuf(Transparent < 0 ? "GIF87a" : "GIF89a", 6, fp ); /* * Write out the screen width and height */ gifPutWord( RWidth, fp ); gifPutWord( RHeight, fp ); /* * Indicate that there is a global colour map */ B = 0x80; /* Yes, there is a color map */ /* * OR in the resolution */ B |= (Resolution - 1) << 5; /* * OR in the Bits per Pixel */ B |= (BitsPerPixel - 1); /* * Write it out */ gdPutC( B, fp ); /* * Write out the Background colour */ gdPutC( Background, fp ); /* * Byte of 0's (future expansion) */ gdPutC( 0, fp ); /* * Write out the Global Colour Map */ for( i=0; i<ColorMapSize; ++i ) { gdPutC( Red[i], fp ); gdPutC( Green[i], fp ); gdPutC( Blue[i], fp ); } /* * Write out extension for transparent colour index, if necessary. */ if ( Transparent >= 0 ) { gdPutC( '!', fp ); gdPutC( 0xf9, fp ); gdPutC( 4, fp ); gdPutC( 1, fp ); gdPutC( 0, fp ); gdPutC( 0, fp ); gdPutC( (unsigned char) Transparent, fp ); gdPutC( 0, fp ); } /* * Write an Image separator */ gdPutC( ',', fp ); /* * Write the Image header */ gifPutWord( LeftOfs, fp ); gifPutWord( TopOfs, fp ); gifPutWord( ctx.Width, fp ); gifPutWord( ctx.Height, fp ); /* * Write out whether or not the image is interlaced */ if( ctx.Interlace ) gdPutC( 0x40, fp ); else gdPutC( 0x00, fp ); /* * Write out the initial code size */ gdPutC( InitCodeSize, fp ); /* * Go and actually compress the data */ compress( InitCodeSize+1, fp, im, &ctx ); /* * Write out a Zero-length packet (to end the series) */ gdPutC( 0, fp ); /* * Write the GIF file terminator */ gdPutC( ';', fp ); }
/* Function: gdImageGifAnimBeginCtx Like <gdImageGifAnimBegin> except that it outputs to <gdIOCtx>. See <gdImageGifAnimBegin>. Parameters: im - The reference image out - Pointer to the output <gdIOCtx>. GlobalCM - Global colormap flag: 1 -> yes, 0 -> no, -1 -> do default Loops - Loop count; 0 -> infinite, -1 means no loop Returns: Nothing. */ BGD_DECLARE(void) gdImageGifAnimBeginCtx(gdImagePtr im, gdIOCtxPtr out, int GlobalCM, int Loops) { int B; int RWidth, RHeight; int Resolution; int ColorMapSize; int BitsPerPixel; int Background = 0; int i; /* Default is to use global color map */ if (GlobalCM < 0) { GlobalCM = 1; } BitsPerPixel = colorstobpp(im->colorsTotal); ColorMapSize = 1 << BitsPerPixel; RWidth = im->sx; RHeight = im->sy; Resolution = BitsPerPixel; /* Write the Magic header */ gdPutBuf("GIF89a", 6, out); /* Write out the screen width and height */ gifPutWord(RWidth, out); gifPutWord(RHeight, out); /* Indicate that there is a global colour map */ B = GlobalCM ? 0x80 : 0; /* OR in the resolution */ B |= (Resolution - 1) << 4; /* OR in the Bits per Pixel */ B |= (BitsPerPixel - 1); /* Write it out */ gdPutC(B, out); /* Write out the Background colour */ gdPutC(Background, out); /* Byte of 0's (future expansion) */ gdPutC(0, out); /* Write out the Global Colour Map */ if(GlobalCM) { for(i = 0; i < ColorMapSize; ++i) { gdPutC(im->red[i], out); gdPutC(im->green[i], out); gdPutC(im->blue[i], out); } } if(Loops >= 0) { gdPutBuf("!\377\13NETSCAPE2.0\3\1", 16, out); gifPutWord(Loops, out); gdPutC(0, out); } }