Path: blob/master/3rdparty/libjpeg-turbo/src/jdatadst.c
16337 views
/*1* jdatadst.c2*3* This file was part of the Independent JPEG Group's software:4* Copyright (C) 1994-1996, Thomas G. Lane.5* Modified 2009-2012 by Guido Vollbeding.6* libjpeg-turbo Modifications:7* Copyright (C) 2013, 2016, D. R. Commander.8* For conditions of distribution and use, see the accompanying README.ijg9* file.10*11* This file contains compression data destination routines for the case of12* emitting JPEG data to memory or to a file (or any stdio stream).13* While these routines are sufficient for most applications,14* some will want to use a different destination manager.15* IMPORTANT: we assume that fwrite() will correctly transcribe an array of16* JOCTETs into 8-bit-wide elements on external storage. If char is wider17* than 8 bits on your machine, you may need to do some tweaking.18*/1920/* this is not a core library module, so it doesn't define JPEG_INTERNALS */21#include "jinclude.h"22#include "jpeglib.h"23#include "jerror.h"2425#ifndef HAVE_STDLIB_H /* <stdlib.h> should declare malloc(),free() */26extern void *malloc (size_t size);27extern void free (void *ptr);28#endif293031/* Expanded data destination object for stdio output */3233typedef struct {34struct jpeg_destination_mgr pub; /* public fields */3536FILE *outfile; /* target stream */37JOCTET *buffer; /* start of buffer */38} my_destination_mgr;3940typedef my_destination_mgr *my_dest_ptr;4142#define OUTPUT_BUF_SIZE 4096 /* choose an efficiently fwrite'able size */434445#if JPEG_LIB_VERSION >= 80 || defined(MEM_SRCDST_SUPPORTED)46/* Expanded data destination object for memory output */4748typedef struct {49struct jpeg_destination_mgr pub; /* public fields */5051unsigned char **outbuffer; /* target buffer */52unsigned long *outsize;53unsigned char *newbuffer; /* newly allocated buffer */54JOCTET *buffer; /* start of buffer */55size_t bufsize;56} my_mem_destination_mgr;5758typedef my_mem_destination_mgr *my_mem_dest_ptr;59#endif606162/*63* Initialize destination --- called by jpeg_start_compress64* before any data is actually written.65*/6667METHODDEF(void)68init_destination (j_compress_ptr cinfo)69{70my_dest_ptr dest = (my_dest_ptr) cinfo->dest;7172/* Allocate the output buffer --- it will be released when done with image */73dest->buffer = (JOCTET *)74(*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE,75OUTPUT_BUF_SIZE * sizeof(JOCTET));7677dest->pub.next_output_byte = dest->buffer;78dest->pub.free_in_buffer = OUTPUT_BUF_SIZE;79}8081#if JPEG_LIB_VERSION >= 80 || defined(MEM_SRCDST_SUPPORTED)82METHODDEF(void)83init_mem_destination (j_compress_ptr cinfo)84{85/* no work necessary here */86}87#endif888990/*91* Empty the output buffer --- called whenever buffer fills up.92*93* In typical applications, this should write the entire output buffer94* (ignoring the current state of next_output_byte & free_in_buffer),95* reset the pointer & count to the start of the buffer, and return TRUE96* indicating that the buffer has been dumped.97*98* In applications that need to be able to suspend compression due to output99* overrun, a FALSE return indicates that the buffer cannot be emptied now.100* In this situation, the compressor will return to its caller (possibly with101* an indication that it has not accepted all the supplied scanlines). The102* application should resume compression after it has made more room in the103* output buffer. Note that there are substantial restrictions on the use of104* suspension --- see the documentation.105*106* When suspending, the compressor will back up to a convenient restart point107* (typically the start of the current MCU). next_output_byte & free_in_buffer108* indicate where the restart point will be if the current call returns FALSE.109* Data beyond this point will be regenerated after resumption, so do not110* write it out when emptying the buffer externally.111*/112113METHODDEF(boolean)114empty_output_buffer (j_compress_ptr cinfo)115{116my_dest_ptr dest = (my_dest_ptr) cinfo->dest;117118if (JFWRITE(dest->outfile, dest->buffer, OUTPUT_BUF_SIZE) !=119(size_t) OUTPUT_BUF_SIZE)120ERREXIT(cinfo, JERR_FILE_WRITE);121122dest->pub.next_output_byte = dest->buffer;123dest->pub.free_in_buffer = OUTPUT_BUF_SIZE;124125return TRUE;126}127128#if JPEG_LIB_VERSION >= 80 || defined(MEM_SRCDST_SUPPORTED)129METHODDEF(boolean)130empty_mem_output_buffer (j_compress_ptr cinfo)131{132size_t nextsize;133JOCTET *nextbuffer;134my_mem_dest_ptr dest = (my_mem_dest_ptr) cinfo->dest;135136/* Try to allocate new buffer with double size */137nextsize = dest->bufsize * 2;138nextbuffer = (JOCTET *) malloc(nextsize);139140if (nextbuffer == NULL)141ERREXIT1(cinfo, JERR_OUT_OF_MEMORY, 10);142143MEMCOPY(nextbuffer, dest->buffer, dest->bufsize);144145if (dest->newbuffer != NULL)146free(dest->newbuffer);147148dest->newbuffer = nextbuffer;149150dest->pub.next_output_byte = nextbuffer + dest->bufsize;151dest->pub.free_in_buffer = dest->bufsize;152153dest->buffer = nextbuffer;154dest->bufsize = nextsize;155156return TRUE;157}158#endif159160161/*162* Terminate destination --- called by jpeg_finish_compress163* after all data has been written. Usually needs to flush buffer.164*165* NB: *not* called by jpeg_abort or jpeg_destroy; surrounding166* application must deal with any cleanup that should happen even167* for error exit.168*/169170METHODDEF(void)171term_destination (j_compress_ptr cinfo)172{173my_dest_ptr dest = (my_dest_ptr) cinfo->dest;174size_t datacount = OUTPUT_BUF_SIZE - dest->pub.free_in_buffer;175176/* Write any data remaining in the buffer */177if (datacount > 0) {178if (JFWRITE(dest->outfile, dest->buffer, datacount) != datacount)179ERREXIT(cinfo, JERR_FILE_WRITE);180}181fflush(dest->outfile);182/* Make sure we wrote the output file OK */183if (ferror(dest->outfile))184ERREXIT(cinfo, JERR_FILE_WRITE);185}186187#if JPEG_LIB_VERSION >= 80 || defined(MEM_SRCDST_SUPPORTED)188METHODDEF(void)189term_mem_destination (j_compress_ptr cinfo)190{191my_mem_dest_ptr dest = (my_mem_dest_ptr) cinfo->dest;192193*dest->outbuffer = dest->buffer;194*dest->outsize = (unsigned long)(dest->bufsize - dest->pub.free_in_buffer);195}196#endif197198199/*200* Prepare for output to a stdio stream.201* The caller must have already opened the stream, and is responsible202* for closing it after finishing compression.203*/204205GLOBAL(void)206jpeg_stdio_dest (j_compress_ptr cinfo, FILE *outfile)207{208my_dest_ptr dest;209210/* The destination object is made permanent so that multiple JPEG images211* can be written to the same file without re-executing jpeg_stdio_dest.212*/213if (cinfo->dest == NULL) { /* first time for this JPEG object? */214cinfo->dest = (struct jpeg_destination_mgr *)215(*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_PERMANENT,216sizeof(my_destination_mgr));217} else if (cinfo->dest->init_destination != init_destination) {218/* It is unsafe to reuse the existing destination manager unless it was219* created by this function. Otherwise, there is no guarantee that the220* opaque structure is the right size. Note that we could just create a221* new structure, but the old structure would not be freed until222* jpeg_destroy_compress() was called.223*/224ERREXIT(cinfo, JERR_BUFFER_SIZE);225}226227dest = (my_dest_ptr) cinfo->dest;228dest->pub.init_destination = init_destination;229dest->pub.empty_output_buffer = empty_output_buffer;230dest->pub.term_destination = term_destination;231dest->outfile = outfile;232}233234235#if JPEG_LIB_VERSION >= 80 || defined(MEM_SRCDST_SUPPORTED)236/*237* Prepare for output to a memory buffer.238* The caller may supply an own initial buffer with appropriate size.239* Otherwise, or when the actual data output exceeds the given size,240* the library adapts the buffer size as necessary.241* The standard library functions malloc/free are used for allocating242* larger memory, so the buffer is available to the application after243* finishing compression, and then the application is responsible for244* freeing the requested memory.245* Note: An initial buffer supplied by the caller is expected to be246* managed by the application. The library does not free such buffer247* when allocating a larger buffer.248*/249250GLOBAL(void)251jpeg_mem_dest (j_compress_ptr cinfo,252unsigned char **outbuffer, unsigned long *outsize)253{254my_mem_dest_ptr dest;255256if (outbuffer == NULL || outsize == NULL) /* sanity check */257ERREXIT(cinfo, JERR_BUFFER_SIZE);258259/* The destination object is made permanent so that multiple JPEG images260* can be written to the same buffer without re-executing jpeg_mem_dest.261*/262if (cinfo->dest == NULL) { /* first time for this JPEG object? */263cinfo->dest = (struct jpeg_destination_mgr *)264(*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_PERMANENT,265sizeof(my_mem_destination_mgr));266} else if (cinfo->dest->init_destination != init_mem_destination) {267/* It is unsafe to reuse the existing destination manager unless it was268* created by this function.269*/270ERREXIT(cinfo, JERR_BUFFER_SIZE);271}272273dest = (my_mem_dest_ptr) cinfo->dest;274dest->pub.init_destination = init_mem_destination;275dest->pub.empty_output_buffer = empty_mem_output_buffer;276dest->pub.term_destination = term_mem_destination;277dest->outbuffer = outbuffer;278dest->outsize = outsize;279dest->newbuffer = NULL;280281if (*outbuffer == NULL || *outsize == 0) {282/* Allocate initial buffer */283dest->newbuffer = *outbuffer = (unsigned char *) malloc(OUTPUT_BUF_SIZE);284if (dest->newbuffer == NULL)285ERREXIT1(cinfo, JERR_OUT_OF_MEMORY, 10);286*outsize = OUTPUT_BUF_SIZE;287}288289dest->pub.next_output_byte = dest->buffer = *outbuffer;290dest->pub.free_in_buffer = dest->bufsize = *outsize;291}292#endif293294295