170a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine/* 270a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine * jdatadst.c 370a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine * 470a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine * Copyright (C) 1994-1996, Thomas G. Lane. 570a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine * This file is part of the Independent JPEG Group's software. 670a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine * For conditions of distribution and use, see the accompanying README file. 770a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine * 870a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine * This file contains compression data destination routines for the case of 970a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine * emitting JPEG data to a file (or any stdio stream). While these routines 1070a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine * are sufficient for most applications, some will want to use a different 1170a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine * destination manager. 1270a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine * IMPORTANT: we assume that fwrite() will correctly transcribe an array of 1370a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine * JOCTETs into 8-bit-wide elements on external storage. If char is wider 1470a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine * than 8 bits on your machine, you may need to do some tweaking. 1570a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine */ 1670a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine 1770a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine/* this is not a core library module, so it doesn't define JPEG_INTERNALS */ 1870a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine#include "jinclude.h" 1970a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine#include "jpeglib.h" 2070a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine#include "jerror.h" 2170a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine 2270a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine 2370a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine/* Expanded data destination object for stdio output */ 2470a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine 2570a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkinetypedef struct { 2670a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine struct jpeg_destination_mgr pub; /* public fields */ 2770a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine 2870a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine FILE * outfile; /* target stream */ 2970a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine JOCTET * buffer; /* start of buffer */ 3070a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine} my_destination_mgr; 3170a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine 3270a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkinetypedef my_destination_mgr * my_dest_ptr; 3370a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine 3470a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine#define OUTPUT_BUF_SIZE 4096 /* choose an efficiently fwrite'able size */ 3570a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine 3670a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine 3770a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine/* 3870a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine * Initialize destination --- called by jpeg_start_compress 3970a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine * before any data is actually written. 4070a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine */ 4170a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine 4270a18cd874a22452aca9e39e22275ed4538ed20bVladimir ChtchetkineMETHODDEF(void) 4370a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkineinit_destination (j_compress_ptr cinfo) 4470a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine{ 4570a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine my_dest_ptr dest = (my_dest_ptr) cinfo->dest; 4670a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine 4770a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine /* Allocate the output buffer --- it will be released when done with image */ 4870a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine dest->buffer = (JOCTET *) 4970a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, 5070a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine OUTPUT_BUF_SIZE * SIZEOF(JOCTET)); 5170a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine 5270a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine dest->pub.next_output_byte = dest->buffer; 5370a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine dest->pub.free_in_buffer = OUTPUT_BUF_SIZE; 5470a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine} 5570a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine 5670a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine 5770a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine/* 5870a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine * Empty the output buffer --- called whenever buffer fills up. 5970a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine * 6070a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine * In typical applications, this should write the entire output buffer 6170a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine * (ignoring the current state of next_output_byte & free_in_buffer), 6270a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine * reset the pointer & count to the start of the buffer, and return TRUE 6370a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine * indicating that the buffer has been dumped. 6470a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine * 6570a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine * In applications that need to be able to suspend compression due to output 6670a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine * overrun, a FALSE return indicates that the buffer cannot be emptied now. 6770a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine * In this situation, the compressor will return to its caller (possibly with 6870a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine * an indication that it has not accepted all the supplied scanlines). The 6970a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine * application should resume compression after it has made more room in the 7070a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine * output buffer. Note that there are substantial restrictions on the use of 7170a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine * suspension --- see the documentation. 7270a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine * 7370a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine * When suspending, the compressor will back up to a convenient restart point 7470a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine * (typically the start of the current MCU). next_output_byte & free_in_buffer 7570a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine * indicate where the restart point will be if the current call returns FALSE. 7670a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine * Data beyond this point will be regenerated after resumption, so do not 7770a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine * write it out when emptying the buffer externally. 7870a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine */ 7970a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine 8070a18cd874a22452aca9e39e22275ed4538ed20bVladimir ChtchetkineMETHODDEF(boolean) 8170a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkineempty_output_buffer (j_compress_ptr cinfo) 8270a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine{ 8370a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine my_dest_ptr dest = (my_dest_ptr) cinfo->dest; 8470a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine 8570a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine if (JFWRITE(dest->outfile, dest->buffer, OUTPUT_BUF_SIZE) != 8670a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine (size_t) OUTPUT_BUF_SIZE) 8770a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine ERREXIT(cinfo, JERR_FILE_WRITE); 8870a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine 8970a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine dest->pub.next_output_byte = dest->buffer; 9070a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine dest->pub.free_in_buffer = OUTPUT_BUF_SIZE; 9170a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine 9270a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine return TRUE; 9370a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine} 9470a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine 9570a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine 9670a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine/* 9770a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine * Terminate destination --- called by jpeg_finish_compress 9870a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine * after all data has been written. Usually needs to flush buffer. 9970a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine * 10070a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine * NB: *not* called by jpeg_abort or jpeg_destroy; surrounding 10170a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine * application must deal with any cleanup that should happen even 10270a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine * for error exit. 10370a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine */ 10470a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine 10570a18cd874a22452aca9e39e22275ed4538ed20bVladimir ChtchetkineMETHODDEF(void) 10670a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkineterm_destination (j_compress_ptr cinfo) 10770a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine{ 10870a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine my_dest_ptr dest = (my_dest_ptr) cinfo->dest; 10970a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine size_t datacount = OUTPUT_BUF_SIZE - dest->pub.free_in_buffer; 11070a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine 11170a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine /* Write any data remaining in the buffer */ 11270a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine if (datacount > 0) { 11370a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine if (JFWRITE(dest->outfile, dest->buffer, datacount) != datacount) 11470a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine ERREXIT(cinfo, JERR_FILE_WRITE); 11570a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine } 11670a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine fflush(dest->outfile); 11770a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine /* Make sure we wrote the output file OK */ 11870a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine if (ferror(dest->outfile)) 11970a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine ERREXIT(cinfo, JERR_FILE_WRITE); 12070a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine} 12170a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine 12270a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine 12370a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine/* 12470a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine * Prepare for output to a stdio stream. 12570a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine * The caller must have already opened the stream, and is responsible 12670a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine * for closing it after finishing compression. 12770a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine */ 12870a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine 12970a18cd874a22452aca9e39e22275ed4538ed20bVladimir ChtchetkineGLOBAL(void) 13070a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkinejpeg_stdio_dest (j_compress_ptr cinfo, FILE * outfile) 13170a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine{ 13270a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine my_dest_ptr dest; 13370a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine 13470a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine /* The destination object is made permanent so that multiple JPEG images 13570a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine * can be written to the same file without re-executing jpeg_stdio_dest. 13670a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine * This makes it dangerous to use this manager and a different destination 13770a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine * manager serially with the same JPEG object, because their private object 13870a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine * sizes may be different. Caveat programmer. 13970a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine */ 14070a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine if (cinfo->dest == NULL) { /* first time for this JPEG object? */ 14170a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine cinfo->dest = (struct jpeg_destination_mgr *) 14270a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_PERMANENT, 14370a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine SIZEOF(my_destination_mgr)); 14470a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine } 14570a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine 14670a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine dest = (my_dest_ptr) cinfo->dest; 14770a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine dest->pub.init_destination = init_destination; 14870a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine dest->pub.empty_output_buffer = empty_output_buffer; 14970a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine dest->pub.term_destination = term_destination; 15070a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine dest->outfile = outfile; 15170a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine} 152