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 }