vil_jpeg_decompressor.cxx
Go to the documentation of this file.
1 // This is core/vil/file_formats/vil_jpeg_decompressor.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 <iostream>
11 #include "vil_jpeg_decompressor.h"
12 #include "vil_jpeg_source_mgr.h"
13 #include <vil/vil_stream.h>
14 #ifdef _MSC_VER
15 # include <vcl_msvc_warnings.h>
16 #endif
17 #include <vxl_config.h>
18 
19 #define trace if (true) { } else std::cerr
20 
21 //: using jpeg decompressor objects :
22 // -# supply an error manager, e.g. with jpeg_std_err().
23 // this \e must be done before initializing the object.
24 // -# initialize with jpeg_create_decompress().
25 // -# supply a data stream, e.g. with jpeg_std_source().
26 // -# call jpeg_read_header() to start reading the data stream. this will read
27 // to the start of the compressed data and store various tables and parameters.
28 // if you just want the image parameters and not the data, it's ok to stop
29 // now, so long as you call jpeg_abort_decompress() or jpeg_destroy_decompress()
30 // to release resources.
31 // -# call jpeg_finish_decompress() if you read all the data. if you only read
32 // some of the data, call jpeg_abort_decompress().
33 // -# destruct the object with jpeg_destroy_decompress().
34 
36  : stream(s)
37  , ready(false)
38  , valid(false)
39  , biffer(nullptr)
40 {
41  stream->ref();
42 
43  // setup the standard error handler in the jpeg library
44  jobj.err = jpeg_std_error(&jerr);
45 
46  // construct the decompression object :
47  jpeg_create_decompress(&jobj);
48 
49  // Increase the amount of memory that can be used.
50  // Default (1Mb) was too small.
51 #if defined(VXL_ADDRESS_BITS) && VXL_ADDRESS_BITS == 32
52  jobj.mem->max_memory_to_use = 300 * 1024 * 1024;
53 #elif defined(VXL_ADDRESS_BITS) && VXL_ADDRESS_BITS == 64
54  jobj.mem->max_memory_to_use = 1024 * 1024 * 1024;
55 #else
56  /* use the default memory settings */
57 #endif
58 
59  // we need to read the header here, in order to get parameters such as size.
60  //
61  // set the data source
63 
64  // rewind the stream
66 
67  // now we may read the header.
68  jpeg_read_header(&jobj, TRUE);
69 
70  // This seems to be necessary. jpeglib.h claims that one can use
71  // jpeg_calc_output_dimensions() instead, but I never bothered to try.
72 #if 1
73  // bogus decompression to get image parameters.
74  jpeg_start_decompress(&jobj);
75 
76  // this aborts the decompression, but doesn't destroy the object.
77  jpeg_abort_decompress(&jobj);
78 #endif
79 }
80 
81 // read the given scanline, skipping/rewinding as required.
82 JSAMPLE const *vil_jpeg_decompressor::read_scanline(unsigned line)
83 {
84  // if the client tries to read the same scanline again, it should be free.
85  if (valid && line == jobj.output_scanline-1)
86  return biffer;
87 
88  if (ready && line<jobj.output_scanline) {
89  trace << "...aborting\n";
90  // bah! have to restart
91  jpeg_abort_decompress(&jobj);
92 
93  //
94  ready = false;
95  valid = false;
96  }
97 
98  if (!ready) {
99  trace << "...restarting\n";
100 
101  // rewind stream
103 
104  // read header
105  jpeg_read_header(&jobj, TRUE);
106 
107  // start decompression
108  jpeg_start_decompress(&jobj);
109 
110  //
111  ready = true;
112  valid = false;
113  }
114 
115  // allocate scanline buffer, if necessary.
116  if (!biffer) {
117  trace << "...allocate buffer\n";
118  unsigned row_size = jobj.output_width * jobj.output_components;
119  biffer = new JSAMPLE[row_size];
120  }
121 
122  // 'buffer' is a pointer to a 1-element array whose 0th element is biffer.
123 #if 0
124  JSAMPLE *buffer[1] = { biffer };
125 #else
126  JSAMPARRAY buffer = &biffer;
127 #endif
128 
129  // read till we've read the line we want :
130  while (jobj.output_scanline <= line) {
131  if (jpeg_read_scanlines(&jobj, buffer, 1) != 1) {
132  jpeg_abort_decompress(&jobj);
133  ready = false;
134  valid = false;
135  return nullptr;
136  }
137  }
138 
139  // end reached ?
140  if (jobj.output_scanline >= jobj.image_height) {
141  trace << "...reached end\n";
142  jpeg_finish_decompress(&jobj); // this will call vil_jpeg_term_source()
143  ready = false;
144  }
145 
146  // success.
147  valid = true; // even if we have reached the end.
148  return biffer;
149 }
150 
151 
153 {
154  // destroy the pool associated with jobj
155  (*jobj.mem->free_pool) ((j_common_ptr) &jobj, JPOOL_IMAGE);
156 
157  // destroy the decompression object
158  jpeg_destroy_decompress(&jobj);
159 
160  //
161  stream->unref();
162  stream = nullptr;
163 
164  //
165  if (biffer)
166  delete [] biffer;
167  biffer = nullptr;
168 }
Stream interface for VIL image loaders.
STATIC void vil_jpeg_stream_src_set(j_decompress_ptr cinfo, vil_stream *vs)
vil_jpeg_decompressor(vil_stream *s)
using jpeg decompressor objects :.
JSAMPLE const * read_scanline(unsigned line)
Do not delete the return value.
Stream interface for VIL image loaders.
Definition: vil_stream.h:21
STATIC void vil_jpeg_stream_src_rewind(j_decompress_ptr cinfo, vil_stream *vs)
void ref()
up/down the reference count.
Definition: vil_stream.h:45
void unref()
Definition: vil_stream.cxx:31
struct jpeg_decompress_struct jobj
struct jpeg_error_mgr jerr
#define trace