Back to index

lightning-sunbird  0.9+nobinonly
jdatadst.c
Go to the documentation of this file.
00001 /*
00002  * jdatadst.c
00003  *
00004  * Copyright (C) 1994-1996, Thomas G. Lane.
00005  * This file is part of the Independent JPEG Group's software.
00006  * For conditions of distribution and use, see the accompanying README file.
00007  *
00008  * This file contains compression data destination routines for the case of
00009  * emitting JPEG data to a file (or any stdio stream).  While these routines
00010  * are sufficient for most applications, some will want to use a different
00011  * destination manager.
00012  * IMPORTANT: we assume that fwrite() will correctly transcribe an array of
00013  * JOCTETs into 8-bit-wide elements on external storage.  If char is wider
00014  * than 8 bits on your machine, you may need to do some tweaking.
00015  */
00016 
00017 /* this is not a core library module, so it doesn't define JPEG_INTERNALS */
00018 #include "jinclude.h"
00019 #include "jpeglib.h"
00020 #include "jerror.h"
00021 
00022 
00023 /* Expanded data destination object for stdio output */
00024 
00025 typedef struct {
00026   struct jpeg_destination_mgr pub; /* public fields */
00027 
00028   FILE * outfile;           /* target stream */
00029   JOCTET * buffer;          /* start of buffer */
00030 } my_destination_mgr;
00031 
00032 typedef my_destination_mgr * my_dest_ptr;
00033 
00034 #define OUTPUT_BUF_SIZE  4096      /* choose an efficiently fwrite'able size */
00035 
00036 
00037 /*
00038  * Initialize destination --- called by jpeg_start_compress
00039  * before any data is actually written.
00040  */
00041 
00042 METHODDEF(void)
00043 init_destination (j_compress_ptr cinfo)
00044 {
00045   my_dest_ptr dest = (my_dest_ptr) cinfo->dest;
00046 
00047   /* Allocate the output buffer --- it will be released when done with image */
00048   dest->buffer = (JOCTET *)
00049       (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE,
00050                               OUTPUT_BUF_SIZE * SIZEOF(JOCTET));
00051 
00052   dest->pub.next_output_byte = dest->buffer;
00053   dest->pub.free_in_buffer = OUTPUT_BUF_SIZE;
00054 }
00055 
00056 
00057 /*
00058  * Empty the output buffer --- called whenever buffer fills up.
00059  *
00060  * In typical applications, this should write the entire output buffer
00061  * (ignoring the current state of next_output_byte & free_in_buffer),
00062  * reset the pointer & count to the start of the buffer, and return TRUE
00063  * indicating that the buffer has been dumped.
00064  *
00065  * In applications that need to be able to suspend compression due to output
00066  * overrun, a FALSE return indicates that the buffer cannot be emptied now.
00067  * In this situation, the compressor will return to its caller (possibly with
00068  * an indication that it has not accepted all the supplied scanlines).  The
00069  * application should resume compression after it has made more room in the
00070  * output buffer.  Note that there are substantial restrictions on the use of
00071  * suspension --- see the documentation.
00072  *
00073  * When suspending, the compressor will back up to a convenient restart point
00074  * (typically the start of the current MCU). next_output_byte & free_in_buffer
00075  * indicate where the restart point will be if the current call returns FALSE.
00076  * Data beyond this point will be regenerated after resumption, so do not
00077  * write it out when emptying the buffer externally.
00078  */
00079 
00080 METHODDEF(boolean)
00081 empty_output_buffer (j_compress_ptr cinfo)
00082 {
00083   my_dest_ptr dest = (my_dest_ptr) cinfo->dest;
00084 
00085   if (JFWRITE(dest->outfile, dest->buffer, OUTPUT_BUF_SIZE) !=
00086       (size_t) OUTPUT_BUF_SIZE)
00087     ERREXIT(cinfo, JERR_FILE_WRITE);
00088 
00089   dest->pub.next_output_byte = dest->buffer;
00090   dest->pub.free_in_buffer = OUTPUT_BUF_SIZE;
00091 
00092   return TRUE;
00093 }
00094 
00095 
00096 /*
00097  * Terminate destination --- called by jpeg_finish_compress
00098  * after all data has been written.  Usually needs to flush buffer.
00099  *
00100  * NB: *not* called by jpeg_abort or jpeg_destroy; surrounding
00101  * application must deal with any cleanup that should happen even
00102  * for error exit.
00103  */
00104 
00105 METHODDEF(void)
00106 term_destination (j_compress_ptr cinfo)
00107 {
00108   my_dest_ptr dest = (my_dest_ptr) cinfo->dest;
00109   size_t datacount = OUTPUT_BUF_SIZE - dest->pub.free_in_buffer;
00110 
00111   /* Write any data remaining in the buffer */
00112   if (datacount > 0) {
00113     if (JFWRITE(dest->outfile, dest->buffer, datacount) != datacount)
00114       ERREXIT(cinfo, JERR_FILE_WRITE);
00115   }
00116   fflush(dest->outfile);
00117   /* Make sure we wrote the output file OK */
00118   if (ferror(dest->outfile))
00119     ERREXIT(cinfo, JERR_FILE_WRITE);
00120 }
00121 
00122 
00123 /*
00124  * Prepare for output to a stdio stream.
00125  * The caller must have already opened the stream, and is responsible
00126  * for closing it after finishing compression.
00127  */
00128 
00129 GLOBAL(void)
00130 jpeg_stdio_dest (j_compress_ptr cinfo, FILE * outfile)
00131 {
00132   my_dest_ptr dest;
00133 
00134   /* The destination object is made permanent so that multiple JPEG images
00135    * can be written to the same file without re-executing jpeg_stdio_dest.
00136    * This makes it dangerous to use this manager and a different destination
00137    * manager serially with the same JPEG object, because their private object
00138    * sizes may be different.  Caveat programmer.
00139    */
00140   if (cinfo->dest == NULL) {       /* first time for this JPEG object? */
00141     cinfo->dest = (struct jpeg_destination_mgr *)
00142       (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_PERMANENT,
00143                               SIZEOF(my_destination_mgr));
00144   }
00145 
00146   dest = (my_dest_ptr) cinfo->dest;
00147   dest->pub.init_destination = init_destination;
00148   dest->pub.empty_output_buffer = empty_output_buffer;
00149   dest->pub.term_destination = term_destination;
00150   dest->outfile = outfile;
00151 }
00152 
00153 /*
00154  * term_destination_file_close --- called by jpeg_finish_compress
00155  * after all data has been written.  Usually needs to flush buffer.
00156  * also will need to close file
00157  * NB: *not* called by jpeg_abort or jpeg_destroy; surrounding
00158  * application must deal with any cleanup that should happen even
00159  * for error exit.
00160  */
00161 
00162 METHODDEF(void)
00163 term_destination_file_close(j_compress_ptr cinfo)
00164 {
00165   my_dest_ptr dest = (my_dest_ptr) cinfo->dest;
00166   size_t datacount = OUTPUT_BUF_SIZE - dest->pub.free_in_buffer;
00167 
00168   /* Write any data remaining in the buffer */
00169   if (datacount > 0) {
00170     if (JFWRITE(dest->outfile, dest->buffer, datacount) != datacount)
00171       ERREXIT(cinfo, JERR_FILE_WRITE);
00172   }
00173   fflush(dest->outfile);
00174   
00175   /* Make sure we wrote the output file OK */
00176   if (ferror(dest->outfile))
00177     ERREXIT(cinfo, JERR_FILE_WRITE);
00178   else
00179       fclose(dest->outfile);
00180 }
00181 
00182 
00183 
00184 
00185 
00186 /*
00187  * Prepare for output to a file from a char *
00188  * The caller is responsible
00189  * for closing it after finishing compression.
00190  */
00191 
00192 GLOBAL(void)
00193 jpeg_file_dest (j_compress_ptr cinfo, char * outfile)
00194 {
00195   my_dest_ptr dest;
00196 
00197   /* The destination object is made permanent so that multiple JPEG images
00198    * can be written to the same file without re-executing jpeg_stdio_dest.
00199    * This makes it dangerous to use this manager and a different destination
00200    * manager serially with the same JPEG object, because their private object
00201    * sizes may be different.  Caveat programmer.
00202    */
00203   if (cinfo->dest == NULL) {       /* first time for this JPEG object? */
00204     cinfo->dest = (struct jpeg_destination_mgr *)
00205       (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_PERMANENT,
00206                               SIZEOF(my_destination_mgr));
00207   }
00208 
00209   dest = (my_dest_ptr) cinfo->dest;
00210   dest->pub.init_destination = init_destination;
00211   dest->pub.empty_output_buffer = empty_output_buffer;
00212   dest->pub.term_destination = term_destination_file_close;
00213   dest->outfile = fopen(outfile,"wb");
00214 }
00215 
00216 
00217 
00218 /*
00219 API to close file in case of error. needed for win16. DLL that opens file must also close it.
00220 */
00221 
00222 GLOBAL(void)
00223 jpeg_close_file(j_compress_ptr cinfo)
00224 {
00225   my_dest_ptr dest = (my_dest_ptr) cinfo->dest;
00226   fclose(dest->outfile);
00227 }
00228 
00229 
00230