Pyrogenesis  13997
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
tex_jpg.cpp
Go to the documentation of this file.
1 /* Copyright (c) 2010 Wildfire Games
2  *
3  * Permission is hereby granted, free of charge, to any person obtaining
4  * a copy of this software and associated documentation files (the
5  * "Software"), to deal in the Software without restriction, including
6  * without limitation the rights to use, copy, modify, merge, publish,
7  * distribute, sublicense, and/or sell copies of the Software, and to
8  * permit persons to whom the Software is furnished to do so, subject to
9  * the following conditions:
10  *
11  * The above copyright notice and this permission notice shall be included
12  * in all copies or substantial portions of the Software.
13  *
14  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
15  * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
17  * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
18  * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
19  * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
20  * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
21  */
22 
23 /*
24  * JPEG codec using IJG jpeglib.
25  */
26 
27 #include "precompiled.h"
28 
29 #include <setjmp.h>
30 
33 
34 #include "tex_codec.h"
35 
36 
37 // squelch "dtor / setjmp interaction" warnings.
38 // all attempts to resolve the underlying problem failed; apparently
39 // the warning is generated if setjmp is used at all in C++ mode.
40 // (jpg_*code have no code that would trigger ctors/dtors, nor are any
41 // called in their prolog/epilog code).
42 #if MSC_VERSION
43 # pragma warning(disable: 4611)
44 #endif
45 
46 
47 /* IMPORTANT: we assume that JOCTET is 8 bits. */
48 cassert(sizeof(JOCTET) == 1 && CHAR_BIT == 8);
49 
50 //-----------------------------------------------------------------------------
51 // mem source manager
52 //-----------------------------------------------------------------------------
53 
54 
55 /* Expanded data source object for memory input */
56 typedef struct
57 {
58  struct jpeg_source_mgr pub; /* public fields */
60 }
61 SrcMgr;
62 typedef SrcMgr* SrcPtr;
63 
64 
65 /*
66 * Initialize source --- called by jpeg_read_header
67 * before any data is actually read.
68 */
69 
70 METHODDEF(void) src_init(j_decompress_ptr UNUSED(cinfo))
71 {
72 }
73 
74 
75 /*
76 * Fill the input buffer --- called whenever buffer is emptied.
77 *
78 * In typical applications, this should read fresh data into the buffer
79 * (ignoring the current state of next_input_byte & bytes_in_buffer),
80 * reset the pointer & count to the start of the buffer, and return TRUE
81 * indicating that the buffer has been reloaded. It is not necessary to
82 * fill the buffer entirely, only to obtain at least one more byte.
83 *
84 * There is no such thing as an EOF return. If the end of the file has been
85 * reached, the routine has a choice of ERREXIT() or inserting fake data into
86 * the buffer. In most cases, generating a warning message and inserting a
87 * fake EOI marker is the best course of action --- this will allow the
88 * decompressor to output however much of the image is there. However,
89 * the resulting error message is misleading if the real problem is an empty
90 * input file, so we handle that case specially.
91 */
92 
93 METHODDEF(boolean) src_fill_buffer(j_decompress_ptr cinfo)
94 {
95  SrcPtr src = (SrcPtr)cinfo->src;
96  static const JOCTET eoi[2] = { 0xFF, JPEG_EOI };
97 
98  /*
99  * since jpeg_mem_src fills the buffer with everything we've got,
100  * jpeg is trying to read beyond end of buffer. return a fake EOI marker.
101  * note: don't modify input buffer: it might be read-only.
102  */
103 
104  WARNMS(cinfo, JWRN_JPEG_EOF);
105 
106  src->pub.next_input_byte = eoi;
107  src->pub.bytes_in_buffer = 2;
108  return TRUE;
109 }
110 
111 
112 /*
113 * Skip data --- used to skip over a potentially large amount of
114 * uninteresting data (such as an APPn marker).
115 */
116 
117 METHODDEF(void) src_skip_data(j_decompress_ptr cinfo, long num_bytes)
118 {
119  SrcPtr src = (SrcPtr)cinfo->src;
120  size_t skip_count = (size_t)num_bytes;
121 
122  /* docs say non-positive num_byte skips should be ignored */
123  if(num_bytes <= 0)
124  return;
125 
126  /*
127  * just subtract bytes available in buffer,
128  * making sure we don't underflow the size_t.
129  * note: if we skip to or beyond end of buffer,
130  * bytes_in_buffer = 0 => fill_input_buffer called => abort.
131  */
132  if(skip_count > src->pub.bytes_in_buffer)
133  skip_count = src->pub.bytes_in_buffer;
134 
135  src->pub.bytes_in_buffer -= skip_count;
136  src->pub.next_input_byte += skip_count;
137 }
138 
139 
140 /*
141 * An additional method that can be provided by data source modules is the
142 * resync_to_restart method for error recovery in the presence of RST markers.
143 * For the moment, this source module just uses the default resync method
144 * provided by the JPEG library. That method assumes that no backtracking
145 * is possible.
146 */
147 
148 
149 /*
150 * Terminate source --- called by jpeg_finish_decompress
151 * after all data has been read. Often a no-op.
152 *
153 * NB: *not* called by jpeg_abort or jpeg_destroy; surrounding
154 * application must deal with any cleanup that should happen even
155 * for error exit.
156 */
157 
158 METHODDEF(void) src_term(j_decompress_ptr UNUSED(cinfo))
159 {
160  /*
161  * no-op (we don't own the buffer and shouldn't,
162  * to make possible multiple images in a source).
163  */
164 }
165 
166 
167 /*
168 * Prepare for input from a buffer.
169 * The caller is responsible for freeing it after finishing decompression.
170 */
171 
172 GLOBAL(void) src_prepare(j_decompress_ptr cinfo, rpU8 data, size_t size)
173 {
174  SrcPtr src;
175 
176  /* Treat 0-length buffer as fatal error */
177  if(size == 0)
178  ERREXIT(cinfo, JERR_INPUT_EMPTY);
179 
180  /*
181  * The source object is made permanent so that
182  * a series of JPEG images can be read from the same file
183  * by calling jpeg_mem_src only before the first one.
184  * This makes it unsafe to use this manager and a different source
185  * manager serially with the same JPEG object. Caveat programmer.
186  */
187 
188  /* first time for this JPEG object? */
189  if(!cinfo->src)
190  cinfo->src = (struct jpeg_source_mgr*)
191  (*cinfo->mem->alloc_small) ((j_common_ptr)cinfo, JPOOL_PERMANENT,
192  sizeof(SrcMgr));
193  /* (takes care of raising error if out of memory) */
194 
195  src = (SrcPtr)cinfo->src;
196  src->pub.init_source = src_init;
197  src->pub.fill_input_buffer = src_fill_buffer;
198  src->pub.skip_input_data = src_skip_data;
199  src->pub.resync_to_restart = jpeg_resync_to_restart; /* default */
200  src->pub.term_source = src_term;
201 
202  /*
203  * fill buffer with everything we have.
204  * if fill_input_buffer is called, the buffer was overrun.
205  */
206  src->pub.bytes_in_buffer = size;
207  src->pub.next_input_byte = (JOCTET*)data;
208 }
209 
210 
211 //-----------------------------------------------------------------------------
212 // mem destination manager
213 //-----------------------------------------------------------------------------
214 
215 /* Expanded data destination object for memory output */
216 typedef struct {
217  struct jpeg_destination_mgr pub; /* public fields */
219 } DstMgr;
220 
221 typedef DstMgr* DstPtr;
222 
223 // this affects how often dst_empty_output_buffer is called (which
224 // efficiently expands the DynArray) and how much tail memory we waste
225 // (not an issue because it is freed immediately after compression).
226 #define OUTPUT_BUF_SIZE 64*KiB /* choose an efficiently writeable size */
227 
228 // note: can't call dst_empty_output_buffer from dst_init or vice versa
229 // because only the former must advance da->pos.
230 static void make_room_in_buffer(j_compress_ptr cinfo)
231 {
232  DstPtr dst = (DstPtr)cinfo->dest;
233  DynArray* da = dst->da;
234 
235  void* start = da->base + da->cur_size;
236 
237  if(da_set_size(da, da->cur_size+OUTPUT_BUF_SIZE) != 0)
238  ERREXIT(cinfo, JERR_FILE_WRITE);
239 
240  dst->pub.next_output_byte = (JOCTET*)start;
241  dst->pub.free_in_buffer = OUTPUT_BUF_SIZE;
242 }
243 
244 
245 /*
246 * Initialize destination --- called by jpeg_start_compress
247 * before any data is actually written.
248 */
249 METHODDEF(void) dst_init(j_compress_ptr cinfo)
250 {
251  make_room_in_buffer(cinfo);
252 }
253 
254 
255 /*
256 * Empty the output buffer --- called whenever buffer fills up.
257 *
258 * In typical applications, this should write the entire output buffer
259 * (ignoring the current state of next_output_byte & free_in_buffer),
260 * reset the pointer & count to the start of the buffer, and return TRUE
261 * indicating that the buffer has been dumped.
262 *
263 * <snip comments on suspended IO>
264 */
265 METHODDEF(boolean) dst_empty_output_buffer(j_compress_ptr cinfo)
266 {
267  DstPtr dst = (DstPtr)cinfo->dest;
268  DynArray* da = dst->da;
269 
270  // writing out OUTPUT_BUF_SIZE-dst->pub.free_in_buffer bytes
271  // sounds reasonable, but makes for broken output.
272  da->pos += OUTPUT_BUF_SIZE;
273 
274  make_room_in_buffer(cinfo);
275 
276  return TRUE; // not suspended
277 }
278 
279 
280 /*
281 * Terminate destination --- called by jpeg_finish_compress
282 * after all data has been written. Usually needs to flush buffer.
283 *
284 * NB: *not* called by jpeg_abort or jpeg_destroy; surrounding
285 * application must deal with any cleanup that should happen even
286 * for error exit.
287 */
288 METHODDEF(void) dst_term(j_compress_ptr cinfo)
289 {
290  DstPtr dst = (DstPtr)cinfo->dest;
291  DynArray* da = dst->da;
292 
293  // account for nbytes left in buffer
294  da->pos += OUTPUT_BUF_SIZE - dst->pub.free_in_buffer;
295 }
296 
297 
298 /*
299 * Prepare for output to a buffer.
300 * The caller is responsible for allocating and writing out to disk after
301 * compression is complete.
302 */
303 
304 GLOBAL(void) dst_prepare(j_compress_ptr cinfo, DynArray* da)
305 {
306  /* The destination object is made permanent so that multiple JPEG images
307  * can be written to the same file without re-executing dst_prepare.
308  * This makes it dangerous to use this manager and a different destination
309  * manager serially with the same JPEG object, because their private object
310  * sizes may be different. Caveat programmer.
311  */
312  if (cinfo->dest == NULL) { /* first time for this JPEG object? */
313  cinfo->dest = (struct jpeg_destination_mgr*)(*cinfo->mem->alloc_small)
314  ((j_common_ptr)cinfo, JPOOL_PERMANENT, sizeof(DstMgr));
315  }
316 
317  DstPtr dst = (DstPtr)cinfo->dest;
318  dst->pub.init_destination = dst_init;
319  dst->pub.empty_output_buffer = dst_empty_output_buffer;
320  dst->pub.term_destination = dst_term;
321  dst->da = da;
322 }
323 
324 
325 //-----------------------------------------------------------------------------
326 // error handler, shared by jpg_(en|de)code
327 //-----------------------------------------------------------------------------
328 
329 // the JPEG library's standard error handler (jerror.c) is divided into
330 // several "methods" which we can override individually. This allows
331 // adjusting the behavior without duplicating a lot of code, which may
332 // have to be updated with each future release.
333 //
334 // we here override error_exit to return control to the library's caller
335 // (i.e. jpg_(de|en)code) when a fatal error occurs, rather than calling exit.
336 //
337 // the replacement error_exit does a longjmp back to the caller's
338 // setjmp return point. it needs access to the jmp_buf,
339 // so we store it in a "subclass" of jpeg_error_mgr.
340 
342 {
343  struct jpeg_error_mgr pub; // "public" fields
344 
345  // jump here (back to JPEG lib caller) on error
346  jmp_buf call_site;
347 
348  // description of first error encountered; must store in JPEG context
349  // for thread safety. initialized in setup_err_mgr.
350  char msg[JMSG_LENGTH_MAX];
351 
352  JpgErrorMgr(jpeg_compress_struct& cinfo);
353  JpgErrorMgr(jpeg_decompress_struct& cinfo);
354 private:
355  void init();
356 };
357 
358 
359 METHODDEF(void) err_error_exit(j_common_ptr cinfo)
360 {
361  // get subclass
362  JpgErrorMgr* err_mgr = (JpgErrorMgr*)cinfo->err;
363 
364  // "output" error message (i.e. store in JpgErrorMgr;
365  // call_site is responsible for displaying it via debug_printf)
366  (*cinfo->err->output_message)(cinfo);
367 
368  // jump back to call site, i.e. jpg_(de|en)code
369  longjmp(err_mgr->call_site, 1);
370 }
371 
372 
373 // stores message in JpgErrorMgr for later output by jpg_(de|en)code.
374 // note: don't display message here, so the caller can
375 // add some context (whether encoding or decoding, and filename).
376 METHODDEF(void) err_output_message(j_common_ptr cinfo)
377 {
378  // get subclass
379  JpgErrorMgr* err_mgr = (JpgErrorMgr*)cinfo->err;
380 
381  // this context already had an error message; don't overwrite it.
382  // (subsequent errors probably aren't related to the real problem).
383  // note: was set to '\0' by ctor.
384  if(err_mgr->msg[0] != '\0')
385  return;
386 
387  // generate the message and store it
388  (*cinfo->err->format_message)(cinfo, err_mgr->msg);
389 }
390 
391 
393 {
394  // fill in pub fields
395  jpeg_std_error(&pub);
396  // .. and override some methods:
397  pub.error_exit = err_error_exit;
398  pub.output_message = err_output_message;
399 
400  // required for "already have message" check in err_output_message
401  msg[0] = '\0';
402 }
403 
404 JpgErrorMgr::JpgErrorMgr(jpeg_compress_struct& cinfo)
405 {
406  init();
407  // hack: register this error manager with cinfo.
408  // must be done before jpeg_create_* in case that fails
409  // (unlikely, but possible if out of memory).
410  cinfo.err = &pub;
411 }
412 
413 JpgErrorMgr::JpgErrorMgr(jpeg_decompress_struct& cinfo)
414 {
415  init();
416  // hack: register this error manager with cinfo.
417  // must be done before jpeg_create_* in case that fails
418  // (unlikely, but possible if out of memory).
419  cinfo.err = &pub;
420 }
421 
422 
423 //-----------------------------------------------------------------------------
424 
425 
426 static Status jpg_transform(Tex* UNUSED(t), size_t UNUSED(transforms))
427 {
429 }
430 
431 
432 // note: jpg_encode and jpg_decode cannot be combined due to
433 // libjpg interface differences.
434 // we do split them up into interface and impl to simplify
435 // resource cleanup and avoid "dtor / setjmp interaction" warnings.
436 //
437 // rationale for row array: jpeg won't output more than a few
438 // scanlines at a time, so we need an output loop anyway. however,
439 // passing at least 2..4 rows is more efficient in low-quality modes
440 // due to less copying.
441 
442 
443 static Status jpg_decode_impl(rpU8 data, size_t size, jpeg_decompress_struct* cinfo, Tex* t)
444 {
445  src_prepare(cinfo, data, size);
446 
447  // ignore return value since:
448  // - suspension is not possible with the mem data source
449  // - we passed TRUE to raise an error if table-only JPEG file
450  (void)jpeg_read_header(cinfo, TRUE);
451 
452  // set libjpg output format. we cannot go with the default because
453  // Photoshop writes non-standard CMYK files that must be converted to RGB.
454  size_t flags = 0;
455  cinfo->out_color_space = JCS_RGB;
456  if(cinfo->num_components == 1)
457  {
458  flags |= TEX_GREY;
459  cinfo->out_color_space = JCS_GRAYSCALE;
460  }
461 
462  // lower quality, but faster
463  cinfo->dct_method = JDCT_IFAST;
464  cinfo->do_fancy_upsampling = FALSE;
465 
466  // ignore return value since suspension is not possible with the
467  // mem data source.
468  // note: since we've set out_color_space, JPEG will always
469  // return an acceptable image format; no need to check.
470  (void)jpeg_start_decompress(cinfo);
471 
472  // scaled output image dimensions and final bpp are now available.
473  int w = cinfo->output_width;
474  int h = cinfo->output_height;
475  int bpp = cinfo->output_components * 8;
476 
477  // alloc destination buffer
478  const size_t pitch = w * bpp / 8;
479  const size_t imgSize = pitch * h; // for allow_rows
480  shared_ptr<u8> img;
481  AllocateAligned(img, imgSize, pageSize);
482 
483  // read rows
484  std::vector<RowPtr> rows = tex_codec_alloc_rows(img.get(), h, pitch, TEX_TOP_DOWN, 0);
485  // could use cinfo->output_scanline to keep track of progress,
486  // but we need to count lines_left anyway (paranoia).
487  JSAMPARRAY row = (JSAMPARRAY)&rows[0];
488  JDIMENSION lines_left = h;
489  while(lines_left != 0)
490  {
491  JDIMENSION lines_read = jpeg_read_scanlines(cinfo, row, lines_left);
492  row += lines_read;
493  lines_left -= lines_read;
494 
495  // we've decoded in-place; no need to further process
496  }
497 
498  // ignore return value since suspension is not possible with the
499  // mem data source.
500  (void)jpeg_finish_decompress(cinfo);
501 
502  Status ret = INFO::OK;
503  if(cinfo->err->num_warnings != 0)
505 
506  // store image info
507  t->data = img;
508  t->dataSize = imgSize;
509  t->ofs = 0;
510  t->w = w;
511  t->h = h;
512  t->bpp = bpp;
513  t->flags = flags;
514 
515  return ret;
516 }
517 
518 
519 static Status jpg_encode_impl(Tex* t, jpeg_compress_struct* cinfo, DynArray* da)
520 {
521  dst_prepare(cinfo, da);
522 
523  // describe image format
524  // required:
525  cinfo->image_width = (JDIMENSION)t->w;
526  cinfo->image_height = (JDIMENSION)t->h;
527  cinfo->input_components = (int)t->bpp / 8;
528  cinfo->in_color_space = (t->bpp == 8)? JCS_GRAYSCALE : JCS_RGB;
529  // defaults depend on cinfo->in_color_space already having been set!
530  jpeg_set_defaults(cinfo);
531  // (add optional settings, e.g. quality, here)
532 
533  // TRUE ensures that we will write a complete interchange-JPEG file.
534  // don't change unless you are very sure of what you're doing.
535  jpeg_start_compress(cinfo, TRUE);
536 
537  // if BGR, convert to RGB.
539 
540  const size_t pitch = t->w * t->bpp / 8;
541  u8* data = tex_get_data(t);
542  std::vector<RowPtr> rows = tex_codec_alloc_rows(data, t->h, pitch, t->flags, TEX_TOP_DOWN);
543 
544  // could use cinfo->output_scanline to keep track of progress,
545  // but we need to count lines_left anyway (paranoia).
546  JSAMPARRAY row = (JSAMPARRAY)&rows[0];
547  JDIMENSION lines_left = (JDIMENSION)t->h;
548  while(lines_left != 0)
549  {
550  JDIMENSION lines_read = jpeg_write_scanlines(cinfo, row, lines_left);
551  row += lines_read;
552  lines_left -= lines_read;
553 
554  // we've decoded in-place; no need to further process
555  }
556 
557  jpeg_finish_compress(cinfo);
558 
559  Status ret = INFO::OK;
560  if(cinfo->err->num_warnings != 0)
562 
563  return ret;
564 }
565 
566 
567 
568 static bool jpg_is_hdr(const u8* file)
569 {
570  // JFIF requires SOI marker at start of stream.
571  // we compare single bytes to be endian-safe.
572  return (file[0] == 0xff && file[1] == 0xd8);
573 }
574 
575 
576 static bool jpg_is_ext(const OsPath& extension)
577 {
578  return extension == L".jpg" || extension == L".jpeg";
579 }
580 
581 
582 static size_t jpg_hdr_size(const u8* UNUSED(file))
583 {
584  return 0; // libjpg returns decoded image data; no header
585 }
586 
587 
588 static Status jpg_decode(rpU8 data, size_t size, Tex* RESTRICT t)
589 {
590  // contains the JPEG decompression parameters and pointers to
591  // working space (allocated as needed by the JPEG library).
592  struct jpeg_decompress_struct cinfo;
593 
594  JpgErrorMgr jerr(cinfo);
595  if(setjmp(jerr.call_site))
596  return ERR::FAIL;
597 
598  jpeg_create_decompress(&cinfo);
599 
600  Status ret = jpg_decode_impl(data, size, &cinfo, t);
601 
602  jpeg_destroy_decompress(&cinfo); // releases a "good deal" of memory
603 
604  return ret;
605 }
606 
607 
608 // limitation: palette images aren't supported
610 {
611  // contains the JPEG compression parameters and pointers to
612  // working space (allocated as needed by the JPEG library).
613  struct jpeg_compress_struct cinfo;
614 
615  JpgErrorMgr jerr(cinfo);
616  if(setjmp(jerr.call_site))
618 
619  jpeg_create_compress(&cinfo);
620 
621  Status ret = jpg_encode_impl(t, &cinfo, da);
622 
623  jpeg_destroy_compress(&cinfo); // releases a "good deal" of memory
624 
625  return ret;
626 }
627 
628 TEX_CODEC_REGISTER(jpg);
#define u8
Definition: types.h:39
DynArray * da
Definition: tex_jpg.cpp:218
SrcMgr * SrcPtr
Definition: tex_jpg.cpp:62
struct jpeg_error_mgr pub
Definition: tex_jpg.cpp:343
size_t ofs
offset to image data in file.
Definition: tex.h:227
static const size_t pageSize
Definition: alignment.h:61
#define UNUSED(param)
mark a function parameter as unused and avoid the corresponding compiler warning. ...
#define WARN_IF_ERR(expression)
Definition: status.h:265
const Status TEX_CODEC_CANNOT_HANDLE
Definition: tex.h:132
static boolean dst_empty_output_buffer(j_compress_ptr cinfo)
Definition: tex_jpg.cpp:265
const Status OK
Definition: status.h:386
Status tex_transform_to(Tex *t, size_t new_flags)
Change &lt;t&gt;&#39;s pixel format (2nd version) (note: this is equivalent to tex_transform(t, t-&gt;flags^new_flags).
Definition: tex.cpp:494
static bool jpg_is_hdr(const u8 *file)
Definition: tex_jpg.cpp:568
provides a memory range that can be expanded but doesn&#39;t waste physical memory or relocate itself...
Definition: dynarray.h:39
shared_ptr< u8 > data
file buffer or image data.
Definition: tex.h:217
indicates the image is 8bpp greyscale.
Definition: tex.h:178
static Status jpg_encode_impl(Tex *t, jpeg_compress_struct *cinfo, DynArray *da)
Definition: tex_jpg.cpp:519
size_t h
Definition: tex.h:230
DynArray * da
Definition: tex_jpg.cpp:59
static bool jpg_is_ext(const OsPath &extension)
Definition: tex_jpg.cpp:576
static boolean src_fill_buffer(j_decompress_ptr cinfo)
Definition: tex_jpg.cpp:93
indicates B and R pixel components are exchanged.
Definition: tex.h:163
struct jpeg_source_mgr pub
Definition: tex_jpg.cpp:58
JpgErrorMgr(jpeg_compress_struct &cinfo)
Definition: tex_jpg.cpp:404
uint8_t *__restrict rpU8
static void dst_term(j_compress_ptr cinfo)
Definition: tex_jpg.cpp:288
char msg[JMSG_LENGTH_MAX]
Definition: tex_jpg.cpp:350
size_t bpp
Definition: tex.h:231
std::vector< RowPtr > tex_codec_alloc_rows(const u8 *data, size_t h, size_t pitch, size_t src_flags, size_t dst_orientation)
Definition: tex_codec.cpp:154
void dst_prepare(j_compress_ptr cinfo, DynArray *da)
Definition: tex_jpg.cpp:304
static Status jpg_decode(rpU8 data, size_t size, Tex *RESTRICT t)
Definition: tex_jpg.cpp:588
u8 * base
Definition: dynarray.h:41
Definition: path.h:75
#define OUTPUT_BUF_SIZE
Definition: tex_jpg.cpp:226
void src_prepare(j_decompress_ptr cinfo, rpU8 data, size_t size)
Definition: tex_jpg.cpp:172
Status da_set_size(DynArray *da, size_t new_size)
expand or shrink the array: changes the amount of currently committed (i.e.
Definition: dynarray.cpp:93
u8 * tex_get_data(const Tex *t)
rationale: since Tex is a struct, its fields are accessible to callers.
Definition: tex.cpp:629
static size_t jpg_hdr_size(const u8 *file)
Definition: tex_jpg.cpp:582
struct jpeg_destination_mgr pub
Definition: tex_jpg.cpp:217
DstMgr * DstPtr
Definition: tex_jpg.cpp:221
static void err_error_exit(j_common_ptr cinfo)
Definition: tex_jpg.cpp:359
i64 Status
Error handling system.
Definition: status.h:171
size_t dataSize
Definition: tex.h:219
jmp_buf call_site
Definition: tex_jpg.cpp:346
stores all data describing an image.
Definition: tex.h:210
size_t pos
Definition: dynarray.h:46
static Status jpg_decode_impl(rpU8 data, size_t size, jpeg_decompress_struct *cinfo, Tex *t)
Definition: tex_jpg.cpp:443
const Status TEX_INVALID_DATA
Definition: tex.h:127
const char * extension
Definition: mongoose.cpp:1736
static Status AllocateAligned(shared_ptr< T > &p, size_t size, size_t alignment=cacheLineSize)
Definition: shared_ptr.h:66
size_t w
Definition: tex.h:229
#define RESTRICT
static void src_term(j_decompress_ptr cinfo)
Definition: tex_jpg.cpp:158
void init()
Definition: tex_jpg.cpp:392
static void make_room_in_buffer(j_compress_ptr cinfo)
Definition: tex_jpg.cpp:230
#define TEX_CODEC_REGISTER(name)
build codec vtbl and register it.
Definition: tex_codec.h:137
#define WARN_RETURN(status)
Definition: status.h:255
static void src_init(j_decompress_ptr cinfo)
Definition: tex_jpg.cpp:70
const Status FAIL
Definition: status.h:406
static Status jpg_transform(Tex *t, size_t transforms)
Definition: tex_jpg.cpp:426
#define cassert(expr)
Compile-time assertion.
static void src_skip_data(j_decompress_ptr cinfo, long num_bytes)
Definition: tex_jpg.cpp:117
static void dst_init(j_compress_ptr cinfo)
Definition: tex_jpg.cpp:249
static void err_output_message(j_common_ptr cinfo)
Definition: tex_jpg.cpp:376
size_t flags
see TexFlags and &quot;Format Conversion&quot; in docs.
Definition: tex.h:234
static Status jpg_encode(Tex *RESTRICT t, DynArray *RESTRICT da)
Definition: tex_jpg.cpp:609