MHEG5  18.9.0
MHEG5 Documentation
mg_jpg.c
Go to the documentation of this file.
1 /*******************************************************************************
2  * Copyright © 2014 The DTVKit Open Software Foundation Ltd (www.dtvkit.org)
3  * Copyright © 2008 Ocean Blue Software Ltd
4  *
5  * This file is part of a DTVKit Software Component
6  * You are permitted to copy, modify or distribute this file subject to the terms
7  * of the DTVKit 1.0 Licence which can be found in licence.txt or at www.dtvkit.org
8  *
9  * THIS CODE AND INFORMATION ARE PROVIDED "AS IS" WITHOUT WARRANTY OF ANY KIND,
10  * EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE IMPLIED WARRANTIES
11  * OF MERCHANTABILITY AND/OR FITNESS FOR A PARTICULAR PURPOSE.
12  *
13  * If you or your organisation is not a member of DTVKit then you have access
14  * to this source code outside of the terms of the licence agreement
15  * and you are expected to delete this and any associated files immediately.
16  * Further information on DTVKit, membership and terms can be found at www.dtvkit.org
17  *******************************************************************************/
25 /*---includes for this file--------------------------------------------------*/
26 #include "decoder.h"
27 
28 /* compiler library header files */
29 #include <stdlib.h>
30 #include <string.h> /* memset */
31 #include <stdio.h>
32 #include <setjmp.h> /* setjmp OPTIONAL? */
33 
34 /* this contains modified source from third party file: jdatasrc.c
35  * The reason we have this here is because we want "different source manager"
36  * in case customer has their own jpeg library.
37  *
38  * The following copyright was in that file:
39  *
40  * Copyright (C) 1994-1996, Thomas G. Lane.
41  * This file is part of the Independent JPEG Group's software.
42  * For conditions of distribution and use, see the accompanying README file.
43  *
44  * This file contains decompression data source routines for the case of
45  * reading JPEG data from a file (or any stdio stream). While these routines
46  * are sufficient for most applications, some will want to use a different
47  * source manager.
48  * IMPORTANT: we assume that fread() will correctly transcribe an array of
49  * UINT8s from 8-bit-wide elements on external storage. If char is wider
50  * than 8 bits on your machine, you may need to do some tweaking.
51  */
52 #include <jpeglib.h>
53 #include <jerror.h>
54 
55 /* OBS header files */
56 #include "glue_memory.h"
57 #include "mg_ctxt.h"
58 #include "osd_utils.h"
59 #include "glue_assert.h"
60 
61 /*---constant definitions for this file--------------------------------------*/
62 
63 #define INPUT_BUF_SIZE 4096 /* choose an efficiently fread'able size */
64 
65 #define GetColourIndex(r, g, b, a) \
66  OSD_FindNearestColourIndex((a << 24) | (r << 16) | (g << 8) | b )
67 
68 /*---local typedef structs for this file-------------------------------------*/
69 
70 typedef struct smyfile
71 {
72  unsigned char *data;
73  unsigned int posn;
74  unsigned int left;
75 } myfile_t;
76 
78 {
79  struct jpeg_error_mgr pub;
80  jmp_buf setjmp_buffer;
81 };
82 
83 typedef struct my_error_mgr *my_error_ptr;
84 
85 /* Expanded data source object for stdio input */
86 
87 typedef struct
88 {
89  struct jpeg_source_mgr pub; /* public fields */
90 
91  myfile_t *infile; /* source stream */
92  UINT8 *buffer; /* start of buffer */
93  boolean start_of_file; /* have we gotten any data yet? */
95 
97 
98 /*---local function definitions----------------------------------------------*/
99 
100 
101 static void my_error_exit( j_common_ptr cinfo )
102 {
103  /* cinfo->err really points to a my_error_mgr struct, so coerce pointer */
104  my_error_ptr myerr = (my_error_ptr) cinfo->err;
105 
106  /* Always display the message. */
107  /* We could postpone this until after returning, if we chose. */
108  (*cinfo->err->output_message)(cinfo);
109 
110  /* Return control to the setjmp point */
111  longjmp(myerr->setjmp_buffer, 1);
112 }
113 
114 #if JPEG_LIB_VERSION == 62
115 /* pseudo_fread is called from the jpeg lib - see file "jinclude.h" line 87 */
116 size_t pseudo_fread( void *buf, size_t size, size_t count, FILE *file )
117 {
118  assert(0);
119  return 0;
120 }
121 
122 #endif
123 
124 /*
125  * Initialize source --- called by jpeg_read_header
126  * before any data is actually read.
127  */
128 
129 METHODDEF(void)
130 init_source(j_decompress_ptr cinfo)
131 {
132  my_src_ptr src = (my_src_ptr) cinfo->src;
133 
134  /* We reset the empty-input-file flag for each image,
135  * but we don't clear the input buffer.
136  * This is correct behavior for reading a series of images from one source.
137  */
138  src->start_of_file = TRUE;
139 }
140 
141 /*
142  * Fill the input buffer --- called whenever buffer is emptied.
143  *
144  * In typical applications, this should read fresh data into the buffer
145  * (ignoring the current state of next_input_byte & bytes_in_buffer),
146  * reset the pointer & count to the start of the buffer, and return TRUE
147  * indicating that the buffer has been reloaded. It is not necessary to
148  * fill the buffer entirely, only to obtain at least one more byte.
149  *
150  * There is no such thing as an EOF return. If the end of the file has been
151  * reached, the routine has a choice of ERREXIT() or inserting fake data into
152  * the buffer. In most cases, generating a warning message and inserting a
153  * fake EOI marker is the best course of action --- this will allow the
154  * decompressor to output however much of the image is there. However,
155  * the resulting error message is misleading if the real problem is an empty
156  * input file, so we handle that case specially.
157  *
158  * In applications that need to be able to suspend compression due to input
159  * not being available yet, a FALSE return indicates that no more data can be
160  * obtained right now, but more may be forthcoming later. In this situation,
161  * the decompressor will return to its caller (with an indication of the
162  * number of scanlines it has read, if any). The application should resume
163  * decompression after it has loaded more data into the input buffer. Note
164  * that there are substantial restrictions on the use of suspension --- see
165  * the documentation.
166  *
167  * When suspending, the decompressor will back up to a convenient restart point
168  * (typically the start of the current MCU). next_input_byte & bytes_in_buffer
169  * indicate where the restart point will be if the current call returns FALSE.
170  * Data beyond this point must be rescanned after resumption, so move it to
171  * the front of the buffer rather than discarding it.
172  */
173 
174 METHODDEF(boolean)
175 fill_input_buffer(j_decompress_ptr cinfo)
176 {
177  my_src_ptr src = (my_src_ptr) cinfo->src;
178  myfile_t *pseudo_file = src->infile;
179  size_t nbytes = INPUT_BUF_SIZE;
180 
181  if (pseudo_file->left < INPUT_BUF_SIZE)
182  {
183  nbytes = pseudo_file->left;
184  if (nbytes == 0)
185  {
186  if (src->start_of_file)
187  { /* Treat empty input file as fatal error */
188  ERREXIT(cinfo, JERR_INPUT_EMPTY);
189  }
190  WARNMS(cinfo, JWRN_JPEG_EOF);
191  /* Insert a fake EOI marker */
192  src->buffer[0] = (UINT8) 0xFF;
193  src->buffer[1] = (UINT8) JPEG_EOI;
194  nbytes = 2;
195  }
196  }
197  memcpy( src->buffer, pseudo_file->data + pseudo_file->posn, nbytes );
198  pseudo_file->posn += nbytes;
199  pseudo_file->left -= nbytes;
200 
201  src->pub.next_input_byte = src->buffer;
202  src->pub.bytes_in_buffer = nbytes;
203  src->start_of_file = FALSE;
204 
205  return TRUE;
206 }
207 
208 
209 /*
210  * Skip data --- used to skip over a potentially large amount of
211  * uninteresting data (such as an APPn marker).
212  *
213  * Writers of suspendable-input applications must note that skip_input_data
214  * is not granted the right to give a suspension return. If the skip extends
215  * beyond the data currently in the buffer, the buffer can be marked empty so
216  * that the next read will cause a fill_input_buffer call that can suspend.
217  * Arranging for additional bytes to be discarded before reloading the input
218  * buffer is the application writer's problem.
219  */
220 
221 METHODDEF(void)
222 skip_input_data(j_decompress_ptr cinfo, long num_bytes)
223 {
224  my_src_ptr src = (my_src_ptr) cinfo->src;
225 
226  /* Just a dumb implementation for now. Could use fseek() except
227  * it doesn't work on pipes. Not clear that being smart is worth
228  * any trouble anyway --- large skips are infrequent.
229  */
230  if (num_bytes > 0)
231  {
232  while (num_bytes > (long) src->pub.bytes_in_buffer)
233  {
234  num_bytes -= (long) src->pub.bytes_in_buffer;
235  (void) fill_input_buffer(cinfo);
236  /* note we assume that fill_input_buffer will never return FALSE,
237  * so suspension need not be handled.
238  */
239  }
240  src->pub.next_input_byte += (size_t) num_bytes;
241  src->pub.bytes_in_buffer -= (size_t) num_bytes;
242  }
243 }
244 
245 
246 /*
247  * An additional method that can be provided by data source modules is the
248  * resync_to_restart method for error recovery in the presence of RST markers.
249  * For the moment, this source module just uses the default resync method
250  * provided by the JPEG library. That method assumes that no backtracking
251  * is possible.
252  */
253 
254 
255 /*
256  * Terminate source --- called by jpeg_finish_decompress
257  * after all data has been read. Often a no-op.
258  *
259  * NB: *not* called by jpeg_abort or jpeg_destroy; surrounding
260  * application must deal with any cleanup that should happen even
261  * for error exit.
262  */
263 
264 METHODDEF(void)
265 term_source(j_decompress_ptr cinfo)
266 {
267  /* no work necessary here */
268 }
269 
270 
271 /*
272  * Prepare for input from a stdio stream.
273  * The caller must have already opened the stream, and is responsible
274  * for closing it after finishing decompression.
275  */
276 
277 METHODDEF(void)
278 jobs_stdio_src(j_decompress_ptr cinfo, myfile_t * infile)
279 {
280  my_src_ptr src;
281 
282  /* The source object and input buffer are made permanent so that a series
283  * of JPEG images can be read from the same file by calling jpeg_stdio_src
284  * only before the first one. (If we discarded the buffer at the end of
285  * one image, we'd likely lose the start of the next one.)
286  * This makes it unsafe to use this manager and a different source
287  * manager serially with the same JPEG object. Caveat programmer.
288  */
289  if (cinfo->src == NULL) /* first time for this JPEG object? */
290  {
291  cinfo->src = (struct jpeg_source_mgr *)
292  (*cinfo->mem->alloc_small)((j_common_ptr) cinfo, JPOOL_PERMANENT,
293  sizeof(my_source_mgr));
294  src = (my_src_ptr) cinfo->src;
295  src->buffer = (UINT8 *)
296  (*cinfo->mem->alloc_small)((j_common_ptr) cinfo, JPOOL_PERMANENT,
297  INPUT_BUF_SIZE * sizeof(UINT8));
298  }
299 
300  src = (my_src_ptr) cinfo->src;
301  src->pub.init_source = init_source;
302  src->pub.fill_input_buffer = fill_input_buffer;
303  src->pub.skip_input_data = skip_input_data;
304  src->pub.resync_to_restart = jpeg_resync_to_restart; /* use default method */
305  src->pub.term_source = term_source;
306  src->infile = infile;
307  src->pub.bytes_in_buffer = 0; /* forces fill_input_buffer on first read */
308  src->pub.next_input_byte = NULL; /* until buffer loaded */
309 }
310 
311 /*---global function definitions---------------------------------------------*/
312 
325 {
326  S_IMAGE *j_bmp = 0;
327  myfile_t pseudo_file;
328  struct jpeg_decompress_struct cinfo;
329  struct my_error_mgr jerr;
330  U8BIT density_unit;
331  U8BIT *row_ptr;
332  U16BIT r_bytes;
333 
334  if (len > 0)
335  {
336  pseudo_file.data = data;
337  pseudo_file.posn = 0;
338  pseudo_file.left = len;
339  cinfo.err = jpeg_std_error(&jerr.pub);
340  jerr.pub.error_exit = my_error_exit;
341  if (setjmp(jerr.setjmp_buffer))
342  {
343  /* If we get here, the JPEG code has signaled an error.
344  * We need to clean up the JPEG object, close the input file, and return.
345  */
346  jpeg_destroy_decompress(&cinfo);
347  OSD_MemFree(j_bmp);
348  j_bmp = 0;
349  }
350  else
351  {
352  jpeg_create_decompress(&cinfo);
353  jobs_stdio_src( &cinfo, &pseudo_file );
354  (void)jpeg_read_header(&cinfo, TRUE);
355 
356  /* jpeg_calc_output_dimensions() */
357  cinfo.out_color_space = JCS_RGB;
358 
359  (void)jpeg_start_decompress(&cinfo);
360  assert(cinfo.output_components == 3);
361 
363  {
364  #ifdef OSD_8_BIT
365  j_bmp = (S_IMAGE *) OSD_MemAlloc(sizeof(S_IMAGE));
366  if (j_bmp)
367  {
368  U8BIT *s_buff = OSD_MemAlloc( cinfo.output_width * cinfo.output_height );
369  if (s_buff)
370  {
371  r_bytes = cinfo.output_width * cinfo.output_components;
372  row_ptr = OSD_MemAlloc( r_bytes );
373  if (row_ptr)
374  {
375  U16BIT r_ndx;
376  j_bmp->col_buff = s_buff;
377  j_bmp->width = cinfo.output_width;
378  j_bmp->height = cinfo.output_height;
379 
380  /* For 8-bit, we don't support HD resolutions, so consider all to be SD */
382 
383  j_bmp->pix_bytes = 1;
384  j_bmp->opaque = COMPLETELY_OPAQUE;
385  while (cinfo.output_scanline < cinfo.output_height)
386  {
387  (void)jpeg_read_scanlines( &cinfo, &row_ptr, 1 );
388  for (r_ndx = 0; r_ndx != r_bytes; r_ndx += cinfo.output_components)
389  {
390  *s_buff++ = GetColourIndex(row_ptr[r_ndx], row_ptr[r_ndx + 1], row_ptr[r_ndx + 2], 0xff);
391  }
392  }
393  OSD_MemFree(row_ptr);
394  }
395  else
396  {
397  OSD_MemFree(s_buff);
398  OSD_MemFree(j_bmp);
399  j_bmp = 0;
400  /*using a warning so that process continues (error will abort)*/
401  WARNMS1(&cinfo, JERR_OUT_OF_MEMORY, 0);
402  }
403  }
404  else
405  {
406  OSD_MemFree(j_bmp);
407  j_bmp = 0;
408  }
409  }
410  #endif /* OSD_8_BIT */
411  }
412  ELSE
413  {
414  #if defined(OSD_16_BIT) || defined(OSD_31_BIT) || defined(OSD_32_BIT)
415  /* HD true colour */
416  r_bytes = cinfo.output_width * cinfo.output_components;
417 
418  j_bmp = (S_IMAGE *) OSD_MemAlloc(sizeof(S_IMAGE));
419  if (j_bmp)
420  {
421  U32BIT resolution;
422  if (!cinfo.saw_JFIF_marker)
423  {
424  resolution = SD_METRIC_RESOLUTION;
425  }
426  else
427  {
428  density_unit = cinfo.density_unit;
429  if ((cinfo.Y_density != cinfo.X_density) ||
430  (density_unit < 1) || (density_unit > 2))
431  {
432  /* Force this to be SD resolution */
433  density_unit = 0;
434  }
435 
436  resolution = cinfo.Y_density;
437 
438  if (density_unit == 1)
439  {
440  /* density in dots/inch */
441  resolution = (resolution * 5000 + 63) / 127;
442  }
443  else if (density_unit == 2)
444  {
445  /* density in dots/cm */
446  switch (cinfo.Y_density)
447  {
448  case 53: resolution = 5315; break;
449  case 35: resolution = 3543; break;
450  case 28: resolution = 2835; break;
451  default: resolution = resolution * 100;
452  }
453  }
454  else
455  {
456  /* SD resolution */
457  resolution = SD_METRIC_RESOLUTION;
458  }
459  }
460  if (resolution)
461  {
462  row_ptr = OSD_MemAlloc( r_bytes * cinfo.output_height );
463  if (!row_ptr)
464  {
465  OSD_MemFree(j_bmp);
466  j_bmp = 0;
467  /*using a warning so that process continues (error will abort)*/
468  WARNMS1(&cinfo, JERR_OUT_OF_MEMORY, 0);
469  }
470  else
471  {
472  j_bmp->y_resolution = (U16BIT)resolution;
473  j_bmp->width = cinfo.output_width;
474  j_bmp->height = cinfo.output_height;
475  j_bmp->col_buff = row_ptr;
476  j_bmp->pix_bytes = 3;
477  j_bmp->opaque = COMPLETELY_OPAQUE;
478  while (cinfo.output_scanline < cinfo.output_height)
479  {
480  (void)jpeg_read_scanlines( &cinfo, &row_ptr, 1 );
481  row_ptr += r_bytes;
482  }
483  }
484  }
485  }
486  #endif /* OSD_16_BIT || OSD_32_BIT */
487  }
488  (void)jpeg_finish_decompress(&cinfo);
489  jpeg_destroy_decompress(&cinfo);
490  }
491  }
492  return j_bmp;
493 }
494 
496 {
497  OSD_MemFree(data->col_buff);
498  OSD_MemFree(data);
499 }
500 
OSD utility functions.
#define IF_COL_DEPTH(cd)
Definition: mg_ctxt.h:65
#define OSD_MemAlloc
Definition: glue_memory.h:96
struct jpeg_error_mgr pub
Definition: mg_jpg.c:79
void DEC_FreeJpg(S_IMAGE *data)
Free memory allocated for JPEG bitmap.
Definition: mg_jpg.c:495
U8BIT * col_buff
Definition: decoder.h:63
unsigned int posn
Definition: mg_jpg.c:73
jobs_stdio_src(j_decompress_ptr cinfo, myfile_t *infile)
Definition: mg_jpg.c:278
jmp_buf setjmp_buffer
Definition: mg_jpg.c:80
unsigned char * data
Definition: mg_jpg.c:72
U8BIT pix_bytes
Definition: decoder.h:61
U16BIT y_resolution
Definition: decoder.h:60
uint8_t U8BIT
Definition: techtype.h:82
S_IMAGE * DEC_DecodeJpg(U8BIT *data, U32BIT len)
Allocate memory for JPG and decode bitmap.
Definition: mg_jpg.c:324
#define GetColourIndex(r, g, b, a)
Definition: mg_jpg.c:65
struct smyfile myfile_t
Memory functions.
init_source(j_decompress_ptr cinfo)
Definition: mg_jpg.c:130
U8BIT opaque
Definition: decoder.h:62
skip_input_data(j_decompress_ptr cinfo, long num_bytes)
Definition: mg_jpg.c:222
U16BIT height
Definition: decoder.h:59
#define ELSE
Definition: mg_ctxt.h:66
int len
Definition: mh5gate.c:57
my_source_mgr * my_src_ptr
Definition: mg_jpg.c:96
U16BIT width
Definition: decoder.h:58
uint16_t U16BIT
Definition: techtype.h:84
The functions in this file are OPTIONALLY provided by Receiver Platform *.
fill_input_buffer(j_decompress_ptr cinfo)
Definition: mg_jpg.c:175
myfile_t * infile
Definition: mg_jpg.c:91
struct my_error_mgr * my_error_ptr
Definition: mg_jpg.c:83
#define SD_METRIC_RESOLUTION
Definition: decoder.h:37
term_source(j_decompress_ptr cinfo)
Definition: mg_jpg.c:265
#define COLOUR_FORMAT_PALETTE
Definition: mheg5_control.h:79
boolean start_of_file
Definition: mg_jpg.c:93
define asserts
#define FALSE
Definition: techtype.h:68
unsigned int left
Definition: mg_jpg.c:74
#define TRUE
Definition: techtype.h:69
struct jpeg_source_mgr pub
Definition: mg_jpg.c:89
Interface to OSD.
UINT8 * buffer
Definition: mg_jpg.c:92
#define OSD_MemFree
Definition: glue_memory.h:97
#define INPUT_BUF_SIZE
Definition: mg_jpg.c:63
#define COMPLETELY_OPAQUE
Definition: decoder.h:31
uint32_t U32BIT
Definition: techtype.h:86
Definition: mg_jpg.c:70