DVBCore  20.3.0
DVBCore Documentation
image_jpeg.c
Go to the documentation of this file.
1 /*******************************************************************************
2  * Copyright © 2014 The DTVKit Open Software Foundation Ltd (www.dtvkit.org)
3  * Copyright © 2010 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 /*#define ENABLE_DEBUG*/
26 
27 /*---includes for this file--------------------------------------------------*/
28 
29 /* compiler library header files */
30 #include <stdio.h> /* Required for JPEG library */
31 #include <string.h>
32 #include <setjmp.h>
33 
34 /* third party header files */
35 #include "jpeglib.h"
36 #include "jerror.h"
37 
38 /* DVBCore header files */
39 #include "techtype.h"
40 #include "dbgfuncs.h"
41 
42 #include "stbheap.h"
43 
44 #ifdef OSD_ST_MODE
45 /* Macro to convert 8-bit alpha values to values supported in "32" bit mode for stapi */
46 #define ST_ALPHA(x) (((x) * 128 + 127) / 255)
47 #endif
48 
49 #define INPUT_BUF_SIZE 4096 /* choose an efficiently fread'able size */
50 
51 
52 /*---constant definitions for this file--------------------------------------*/
53 #ifdef ENABLE_DEBUG
54 #define DBG(x) STB_SPDebugWrite x
55 #else
56 #define DBG(x)
57 #endif
58 
59 
60 /*---local typedef structs for this file-------------------------------------*/
61 typedef struct
62 {
63  U8BIT *data;
64  U32BIT posn;
65  U32BIT left;
67 
69 {
70  struct jpeg_error_mgr pub;
71  jmp_buf setjmp_buffer;
72 };
73 
74 
75 typedef struct
76 {
77  struct jpeg_source_mgr pub; /* public fields */
78 
79  S_PSEUDO_FILE *infile; /* source stream */
80  JOCTET *buffer; /* start of buffer */
81  BOOLEAN start_of_file; /* have we gotten any data yet? */
83 
84 
85 /*---local (static) variable declarations for this file----------------------*/
86 /* (internal variables declared static to make them local) */
87 typedef struct my_error_mgr *my_error_ptr;
88 typedef my_source_mgr *my_src_ptr;
89 
90 
91 /*---local function prototypes for this file---------------------------------*/
92 /* (internal functions declared static to make them local) */
93 static BOOLEAN JPGGetImageSize(U8BIT *image_data, U32BIT data_size, U16BIT *pixel_width,
94  U16BIT *pixel_height, U32BIT *row_bytes);
95 static BOOLEAN JPGConvertImage(U8BIT *image_data, U32BIT data_size, U8BIT *output_data);
96 
97 static void my_error_exit( j_common_ptr cinfo );
98 static void jobs_stdio_src(j_decompress_ptr cinfo, S_PSEUDO_FILE *infile);
99 static void init_source(j_decompress_ptr cinfo);
100 static boolean fill_input_buffer(j_decompress_ptr cinfo);
101 static void skip_input_data(j_decompress_ptr cinfo, long num_bytes);
102 static void term_source(j_decompress_ptr cinfo);
103 
104 
105 /*---global function definitions---------------------------------------------*/
106 
107 /*!**************************************************************************
108  * @brief Converts the given JPEG image data to a bitmap image that can be displayed on-screen,
109  * but no scaling is applied.
110  * @param image_data - PNG image data
111  * @param image_data_size - number of PNG image data bytes
112  * @param output_data - address of pointer to buffer allocated for output data
113  * @param output_data_size - pointer to number of bytes in output bitmap
114  * @param pixel_width - pointer to returned width in pixels
115  * @param pixel_height - pointer to returned height in pixels
116  * @return TRUE if image data is a valid PNG and conversion succeeds, FALSE otherwise
117  ****************************************************************************/
118 BOOLEAN STB_IMGConvertJPEG(U8BIT *image_data, U32BIT image_data_size, U8BIT **output_data,
119  U32BIT *output_data_size, U16BIT *pixel_width, U16BIT *pixel_height)
120 {
121  BOOLEAN retval;
122  U32BIT rowbytes;
123 
124  FUNCTION_START(STB_IMGConvertJPEG);
125 
126  retval = FALSE;
127  *output_data = NULL;
128  *output_data_size = 0;
129 
130  if ((image_data != NULL) && (image_data_size > 0))
131  {
132  if (JPGGetImageSize(image_data, image_data_size, pixel_width, pixel_height, &rowbytes))
133  {
134  DBG(("STB_IMGConvertJPEG: pixel_width=%u, pixel_height=%u, rowbytes=%lu",
135  *pixel_width, *pixel_height, rowbytes));
136 
137  /* Allocate memory for the decompressed image */
138  *output_data_size = rowbytes * *pixel_height;
139 
140  *output_data = (U8BIT *)STB_GetMemory(*output_data_size);
141  if (*output_data != NULL)
142  {
143  retval = JPGConvertImage(image_data, image_data_size, *output_data);
144  if (!retval)
145  {
146  DBG(("STB_IMGConvertJPEG: Failed to decompress image"));
147 
148  STB_FreeMemory(*output_data);
149  *output_data = NULL;
150  *output_data_size = 0;
151  }
152  }
153  }
154  }
155 
156  FUNCTION_FINISH(STB_IMGConvertJPEG);
157 
158  return(retval);
159 }
160 
161 /*---local function definitions---------------------------------------------*/
162 
163 /*!**************************************************************************
164  * @brief Returns the size in pixels and the number of bytes required for a single row.
165  * @param image_data - JPEG image data to be decoded
166  * @param data_size - number of bytes of image data
167  * @param pixel_width - returned width in pixels
168  * @param pixel_height - returned height in pixels
169  * @param row_bytes - returned bytes per line
170  * @return TRUE if size data is returned, FALSE otherwise
171  ****************************************************************************/
172 static BOOLEAN JPGGetImageSize(U8BIT *image_data, U32BIT data_size, U16BIT *pixel_width,
173  U16BIT *pixel_height, U32BIT *row_bytes)
174 {
175  BOOLEAN retval;
176  struct jpeg_decompress_struct cinfo;
177  struct my_error_mgr jerr;
178  S_PSEUDO_FILE pseudo_file;
179 
180  FUNCTION_START(JPGGetImageSize);
181 
182  retval = FALSE;
183 
184  if ((image_data != NULL) && (data_size > 0))
185  {
186  cinfo.err = jpeg_std_error(&jerr.pub);
187  jerr.pub.error_exit = my_error_exit;
188 
189  if (setjmp(jerr.setjmp_buffer))
190  {
191  /* If we get here, the JPEG code has signaled an error.
192  * We need to clean up the JPEG object, close the input file, and return */
193  jpeg_destroy_decompress(&cinfo);
194  }
195  else
196  {
197  pseudo_file.data = image_data;
198  pseudo_file.posn = 0;
199  pseudo_file.left = data_size;
200 
201  jpeg_create_decompress(&cinfo);
202  jobs_stdio_src( &cinfo, &pseudo_file );
203 
204  jpeg_read_header(&cinfo, TRUE);
205 
206  *pixel_width = cinfo.output_width;
207  *pixel_height = cinfo.output_height;
208 
209 #ifdef OSD_16_BIT
210  *row_bytes = cinfo.output_width * sizeof(U16BIT);
211 #else /* OSD_32_BIT */
212  *row_bytes = cinfo.output_width * sizeof(U32BIT);
213 #endif
214 
215  jpeg_destroy_decompress(&cinfo);
216  }
217  }
218 
219  FUNCTION_FINISH(JPGGetImageSize);
220 
221  return(retval);
222 }
223 
224 /*!**************************************************************************
225  * @brief Decompresses the JPEG image and converts it to image data the correct format for the OSD
226  * @param image_data - JPEG image data to be decoded
227  * @param data_size - number of bytes of image data
228  * @param output_data - preallocated buffer to take the output data
229  * @return TRUE if the image is decompressed successfully, FALSE otherwise
230  ****************************************************************************/
231 static BOOLEAN JPGConvertImage(U8BIT *image_data, U32BIT data_size, U8BIT *output_data)
232 {
233  BOOLEAN retval;
234  struct jpeg_decompress_struct cinfo;
235  struct my_error_mgr jerr;
236  S_PSEUDO_FILE pseudo_file;
237  U8BIT *row_ptr;
238  U16BIT pixel;
239  U8BIT red, green, blue;
240  U8BIT *src;
241 #ifdef OSD_16_BIT
242  U16BIT *dest_line;
243  U16BIT *dest;
244 #else /* OSD_32_BIT */
245  U8BIT alpha;
246  U32BIT *dest_line;
247  U32BIT *dest;
248 #endif
249 
250  FUNCTION_START(JPGConvertImage);
251 
252  retval = FALSE;
253 
254  if ((image_data != NULL) && (data_size > 0))
255  {
256  cinfo.err = jpeg_std_error(&jerr.pub);
257  jerr.pub.error_exit = my_error_exit;
258 
259  if (setjmp(jerr.setjmp_buffer))
260  {
261  /* If we get here, the JPEG code has signaled an error.
262  * We need to clean up the JPEG object, close the input file, and return */
263  jpeg_destroy_decompress(&cinfo);
264  }
265  else
266  {
267  pseudo_file.data = image_data;
268  pseudo_file.posn = 0;
269  pseudo_file.left = data_size;
270 
271  jpeg_create_decompress(&cinfo);
272  jobs_stdio_src( &cinfo, &pseudo_file );
273 
274  jpeg_read_header(&cinfo, TRUE);
275 
276  /* Allocate memory to decompress a single line into */
277  row_ptr = STB_GetMemory(cinfo.output_width * cinfo.output_components);
278  if (row_ptr != NULL)
279  {
280  jpeg_start_decompress(&cinfo);
281 
282 #ifdef OSD_16_BIT
283  dest_line = (U16BIT *)output_data;
284 #else /* OSD_32_BIT */
285  dest_line = (U32BIT *)output_data;
286 #endif
287 
288  /* Decompress the image a line at a time, converting each one to the required output format */
289  while (cinfo.output_scanline < cinfo.output_height)
290  {
291  if (jpeg_read_scanlines(&cinfo, &row_ptr, 1) == 1)
292  {
293  if (cinfo.output_components == 3)
294  {
295  /* RGB image */
296  for (pixel = cinfo.output_width, dest = dest_line, src = row_ptr; pixel > 0;
297  dest++, src += 3, pixel--)
298  {
299  red = *src;
300  green = *(src + 1);
301  blue = *(src + 2);
302 #ifdef OSD_16_BIT
303  *dest = 0x0f;
304  *dest = (*dest << 4) | (red >> 4);
305  *dest = (*dest << 4) | (green >> 4);
306  *dest = (*dest << 4) | (blue >> 4);
307 #else /* OSD_32_BIT */
308 #ifdef OSD_ST_MODE
309  alpha = ST_ALPHA(0xff);
310 #else
311  alpha = 0xff;
312 #endif
313  *dest = (alpha << 24) | (red << 16) | (green << 8) | blue;
314 #endif
315  }
316  }
317  }
318  }
319 
320  jpeg_finish_decompress(&cinfo);
321 
322  STB_FreeMemory(row_ptr);
323  }
324 
325  jpeg_destroy_decompress(&cinfo);
326  }
327  }
328 
329  FUNCTION_FINISH(JPGConvertImage);
330 
331  return(retval);
332 }
333 
334 static void my_error_exit( j_common_ptr cinfo )
335 {
336  /* cinfo->err really points to a my_error_mgr struct, so coerce pointer */
337  my_error_ptr myerr = (my_error_ptr) cinfo->err;
338 
339  /* Always display the message. */
340  /* We could postpone this until after returning, if we chose. */
341  (*cinfo->err->output_message)(cinfo);
342 
343  /* Return control to the setjmp point */
344  longjmp(myerr->setjmp_buffer, 1);
345 }
346 
347 static void jobs_stdio_src(j_decompress_ptr cinfo, S_PSEUDO_FILE *infile)
348 {
349  my_src_ptr src;
350 
351  /* The source object and input buffer are made permanent so that a series
352  * of JPEG images can be read from the same file by calling jpeg_stdio_src
353  * only before the first one. (If we discarded the buffer at the end of
354  * one image, we'd likely lose the start of the next one.)
355  * This makes it unsafe to use this manager and a different source
356  * manager serially with the same JPEG object. Caveat programmer.
357  */
358  if (cinfo->src == NULL)
359  {
360  /* first time for this JPEG object? */
361  cinfo->src = (struct jpeg_source_mgr *)(*cinfo->mem->alloc_small)((j_common_ptr)cinfo,
362  JPOOL_PERMANENT, sizeof(my_source_mgr));
363 
364  src = (my_src_ptr) cinfo->src;
365 
366  src->buffer = (JOCTET *)(*cinfo->mem->alloc_small)((j_common_ptr) cinfo,
367  JPOOL_PERMANENT, INPUT_BUF_SIZE * sizeof(JOCTET));
368  }
369 
370  src = (my_src_ptr) cinfo->src;
371  src->pub.init_source = init_source;
372  src->pub.fill_input_buffer = fill_input_buffer;
373  src->pub.skip_input_data = skip_input_data;
374  src->pub.resync_to_restart = jpeg_resync_to_restart; /* use default method */
375  src->pub.term_source = term_source;
376  src->infile = infile;
377  src->pub.bytes_in_buffer = 0; /* forces fill_input_buffer on first read */
378  src->pub.next_input_byte = NULL; /* until buffer loaded */
379 }
380 
381 static void init_source(j_decompress_ptr cinfo)
382 {
383  my_src_ptr src = (my_src_ptr) cinfo->src;
384 
385  /* We reset the empty-input-file flag for each image,
386  * but we don't clear the input buffer.
387  * This is correct behavior for reading a series of images from one source.
388  */
389  src->start_of_file = TRUE;
390 }
391 
392 /*
393  * Fill the input buffer --- called whenever buffer is emptied.
394  *
395  * In typical applications, this should read fresh data into the buffer
396  * (ignoring the current state of next_input_byte & bytes_in_buffer),
397  * reset the pointer & count to the start of the buffer, and return TRUE
398  * indicating that the buffer has been reloaded. It is not necessary to
399  * fill the buffer entirely, only to obtain at least one more byte.
400  *
401  * There is no such thing as an EOF return. If the end of the file has been
402  * reached, the routine has a choice of ERREXIT() or inserting fake data into
403  * the buffer. In most cases, generating a warning message and inserting a
404  * fake EOI marker is the best course of action --- this will allow the
405  * decompressor to output however much of the image is there. However,
406  * the resulting error message is misleading if the real problem is an empty
407  * input file, so we handle that case specially.
408  *
409  * In applications that need to be able to suspend compression due to input
410  * not being available yet, a FALSE return indicates that no more data can be
411  * obtained right now, but more may be forthcoming later. In this situation,
412  * the decompressor will return to its caller (with an indication of the
413  * number of scanlines it has read, if any). The application should resume
414  * decompression after it has loaded more data into the input buffer. Note
415  * that there are substantial restrictions on the use of suspension --- see
416  * the documentation.
417  *
418  * When suspending, the decompressor will back up to a convenient restart point
419  * (typically the start of the current MCU). next_input_byte & bytes_in_buffer
420  * indicate where the restart point will be if the current call returns FALSE.
421  * Data beyond this point must be rescanned after resumption, so move it to
422  * the front of the buffer rather than discarding it.
423  */
424 
425 static boolean fill_input_buffer(j_decompress_ptr cinfo)
426 {
427  my_src_ptr src = (my_src_ptr) cinfo->src;
428  S_PSEUDO_FILE *pseudo_file = src->infile;
429  U32BIT nbytes = INPUT_BUF_SIZE;
430 
431  if (pseudo_file->left < INPUT_BUF_SIZE)
432  {
433  nbytes = pseudo_file->left;
434  if (nbytes == 0)
435  {
436  if (src->start_of_file)
437  {
438  /* Treat empty input file as fatal error */
439  ERREXIT(cinfo, JERR_INPUT_EMPTY);
440  }
441  WARNMS(cinfo, JWRN_JPEG_EOF);
442  /* Insert a fake EOI marker */
443  src->buffer[0] = (JOCTET) 0xFF;
444  src->buffer[1] = (JOCTET) JPEG_EOI;
445  nbytes = 2;
446  }
447  }
448 
449  memcpy( src->buffer, pseudo_file->data + pseudo_file->posn, nbytes );
450  pseudo_file->posn += nbytes;
451  pseudo_file->left -= nbytes;
452 
453  src->pub.next_input_byte = src->buffer;
454  src->pub.bytes_in_buffer = nbytes;
455  src->start_of_file = FALSE;
456 
457  return TRUE;
458 }
459 
460 /*
461  * Skip data --- used to skip over a potentially large amount of
462  * uninteresting data (such as an APPn marker).
463  *
464  * Writers of suspendable-input applications must note that skip_input_data
465  * is not granted the right to give a suspension return. If the skip extends
466  * beyond the data currently in the buffer, the buffer can be marked empty so
467  * that the next read will cause a fill_input_buffer call that can suspend.
468  * Arranging for additional bytes to be discarded before reloading the input
469  * buffer is the application writer's problem.
470  */
471 
472 static void skip_input_data(j_decompress_ptr cinfo, long num_bytes)
473 {
474  my_src_ptr src = (my_src_ptr) cinfo->src;
475 
476  /* Just a dumb implementation for now. Could use fseek() except
477  * it doesn't work on pipes. Not clear that being smart is worth
478  * any trouble anyway --- large skips are infrequent.
479  */
480  if (num_bytes > 0)
481  {
482  while (num_bytes > (long) src->pub.bytes_in_buffer)
483  {
484  num_bytes -= (long) src->pub.bytes_in_buffer;
485  (void) fill_input_buffer(cinfo);
486  /* note we assume that fill_input_buffer will never return FALSE,
487  * so suspension need not be handled.
488  */
489  }
490  src->pub.next_input_byte += (size_t) num_bytes;
491  src->pub.bytes_in_buffer -= (size_t) num_bytes;
492  }
493 }
494 
495 /*
496  * An additional method that can be provided by data source modules is the
497  * resync_to_restart method for error recovery in the presence of RST markers.
498  * For the moment, this source module just uses the default resync method
499  * provided by the JPEG library. That method assumes that no backtracking
500  * is possible.
501  */
502 
503 
504 /*
505  * Terminate source --- called by jpeg_finish_decompress
506  * after all data has been read. Often a no-op.
507  *
508  * NB: *not* called by jpeg_abort or jpeg_destroy; surrounding
509  * application must deal with any cleanup that should happen even
510  * for error exit.
511  */
512 
513 static void term_source(j_decompress_ptr cinfo)
514 {
515  /* no work necessary here */
516  USE_UNWANTED_PARAM(cinfo);
517 }
518 
519 /****************************************************************************
520  * End of file
521  *****************************************************************************/
void * STB_GetMemory(U32BIT bytes)
Attempts to allocate memory from the heap.
Definition: stbheap.c:221
void STB_FreeMemory(void *addr)
Releases previously allocated heap memory.
Definition: stbheap.c:336
Debug functions header file.
BOOLEAN STB_IMGConvertJPEG(U8BIT *image_data, U32BIT image_data_size, U8BIT **output_data, U32BIT *output_data_size, U16BIT *pixel_width, U16BIT *pixel_height)
Converts the given JPEG image data to a bitmap image that can be displayed on-screen, but no scaling is applied.
Definition: image_jpeg.c:118
System Wide Global Technical Data Type Definitions.
Header file - Function prototypes for heap memory.