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