vil_jpeg_destination_mgr.cxx
Go to the documentation of this file.
1 // This is core/vil/file_formats/vil_jpeg_destination_mgr.cxx
2 //:
3 // \file
4 // \author fsm
5 // \verbatim
6 // Modifications
7 // 11 Oct 2002 Ian Scott - converted to vil
8 //\endverbatim
9 
10 #include <cstddef>
12 #include <cassert>
13 #ifdef _MSC_VER
14 # include <vcl_msvc_warnings.h>
15 #endif
16 #include <vil/vil_stream.h>
17 
18 #define STATIC /*static*/
19 
20 // In ANSI C, and indeed any rational implementation, std::size_t is also the
21 // type returned by sizeof(). However, it seems there are some irrational
22 // implementations out there, in which sizeof() returns an int even though
23 // std::size_t is defined as long or unsigned long. To ensure consistent results
24 // we always use this SIZEOF() macro in place of using sizeof() directly.
25 
26 #define SIZEOF(object) ((std::size_t) sizeof(object))
27 
28 // Implement a jpeg_destination_manager for vil_stream *.
29 // Adapted by fsm from the FILE * version in jdatadst.c
30 
31 #define vil_jpeg_OUTPUT_BUF_SIZE 4096 // choose an efficiently fwrite'able size
33 
34 
35 // * Initialize destination --- called by jpeg_start_compress
36 // * before any data is actually written.
37 STATIC
38 void
39 vil_jpeg_init_destination (j_compress_ptr cinfo)
40 {
41  auto dest = (vil_jpeg_dstptr) cinfo->dest; // cast to derived class
42 
43  // Allocate the output buffer --- it will be released when done with image
44  dest->buffer = (JOCTET *)
45  (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo,
46  JPOOL_IMAGE,
48 
49  dest->base.next_output_byte = dest->buffer;
50  dest->base.free_in_buffer = vil_jpeg_OUTPUT_BUF_SIZE;
51 }
52 
53 
54 //: Empty the output buffer --- called whenever buffer fills up.
55 //
56 // In typical applications, this should write the entire output buffer
57 // (ignoring the current state of next_output_byte & free_in_buffer),
58 // reset the pointer & count to the start of the buffer, and return TRUE
59 // indicating that the buffer has been dumped.
60 //
61 // In applications that need to be able to suspend compression due to output
62 // overrun, a FALSE return indicates that the buffer cannot be emptied now.
63 // In this situation, the compressor will return to its caller (possibly with
64 // an indication that it has not accepted all the supplied scanlines). The
65 // application should resume compression after it has made more room in the
66 // output buffer. Note that there are substantial restrictions on the use of
67 // suspension --- see the documentation.
68 //
69 // When suspending, the compressor will back up to a convenient restart point
70 // (typically the start of the current MCU). next_output_byte & free_in_buffer
71 // indicate where the restart point will be if the current call returns FALSE.
72 // Data beyond this point will be regenerated after resumption, so do not
73 // write it out when emptying the buffer externally.
74 jpeg_boolean
75 vil_jpeg_empty_output_buffer (j_compress_ptr cinfo)
76 {
77  auto dest = (vil_jpeg_dstptr) cinfo->dest; // cast to derived class
78 
79  if (dest->stream->write(dest->buffer, vil_jpeg_OUTPUT_BUF_SIZE) != (std::size_t) vil_jpeg_OUTPUT_BUF_SIZE)
80  ERREXIT(cinfo, JERR_FILE_WRITE);
81 
82  dest->base.next_output_byte = dest->buffer;
83  dest->base.free_in_buffer = vil_jpeg_OUTPUT_BUF_SIZE;
84 
85  return TRUE;
86 }
87 
88 
89 //: Terminate destination --- called by jpeg_finish_compress after all data has been written. Usually needs to flush buffer.
90 //
91 // \note \e not called by jpeg_abort or jpeg_destroy; surrounding
92 // application must deal with any cleanup that should happen even
93 // for error exit.
94 void
95 vil_jpeg_term_destination (j_compress_ptr cinfo)
96 {
97  auto dest = (vil_jpeg_dstptr) cinfo->dest; // cast to derived class
98  std::size_t datacount = vil_jpeg_OUTPUT_BUF_SIZE - dest->base.free_in_buffer;
99 
100  // Write any data remaining in the buffer
101  if (datacount > 0) {
102  if (dest->stream->write(dest->buffer, datacount) != (vil_streampos)datacount)
103  ERREXIT(cinfo, JERR_FILE_WRITE);
104  }
105 }
106 
107 
108 //: Prepare for output to a vil_stream.
109 // The caller must have already opened the stream, and is responsible
110 // for closing it after finishing compression.
111 void
112 vil_jpeg_stream_dst_set (j_compress_ptr cinfo, vil_stream *vs)
113 {
114  // The destination object is made permanent so that multiple JPEG images
115  // can be written to the same file without re-executing jpeg_stdio_dest.
116  // This makes it dangerous to use this manager and a different destination
117  // manager serially with the same JPEG object, because their private object
118  // sizes may be different. Caveat programmer.
119  //
120  assert(! cinfo->dest); // call this routine only once.
121 
122  // allocate
123  auto dest = (vil_jpeg_dstptr)
124  (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo,
125  JPOOL_PERMANENT,
127  cinfo->dest = reinterpret_cast<jpeg_destination_mgr *>(dest);
128 
129  // fill in methods in base
130  dest->base.init_destination = vil_jpeg_init_destination;
131  dest->base.empty_output_buffer = vil_jpeg_empty_output_buffer;
132  dest->base.term_destination = vil_jpeg_term_destination;
133 
134  dest->stream = vs;
135 }
136 
137 void
138 vil_jpeg_stream_dst_rewind(j_compress_ptr cinfo, vil_stream *vs)
139 {
140  auto dst = ( vil_jpeg_dstptr )( cinfo->dest );
141  { // verify
142  assert(dst != nullptr);
143  assert(dst->stream == vs);
144  }
145 
146  cinfo->dest->next_output_byte = dst->buffer;
147  cinfo->dest->free_in_buffer = vil_jpeg_OUTPUT_BUF_SIZE;
148 
149  vs->seek(0L);
150 }
Stream interface for VIL image loaders.
void vil_jpeg_stream_dst_rewind(j_compress_ptr cinfo, vil_stream *vs)
jpeg_boolean vil_jpeg_empty_output_buffer(j_compress_ptr cinfo)
Empty the output buffer — called whenever buffer fills up.
void vil_jpeg_term_destination(j_compress_ptr cinfo)
Terminate destination — called by jpeg_finish_compress after all data has been written....
#define vil_jpeg_OUTPUT_BUF_SIZE
virtual void seek(vil_streampos position)=0
Goto file pointer.
vil_jpeg_stream_destination_mgr * vil_jpeg_dstptr
STATIC void vil_jpeg_init_destination(j_compress_ptr cinfo)
void vil_jpeg_stream_dst_set(j_compress_ptr cinfo, vil_stream *vs)
Prepare for output to a vil_stream.
Stream interface for VIL image loaders.
Definition: vil_stream.h:21
#define STATIC
#define SIZEOF(object)
this is the data source structure which allows JPEG to write to a vil_stream.
vxl_int_32 vil_streampos
Definition: vil_stream.h:16