MHEG5  18.9.0
MHEG5 Documentation
mg_png.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 <stdlib.h>
27 #include <string.h> /* memset */
28 #include <stdio.h>
29 
30 /* third party header files */
31 #include <png.h>
32 
33 /* OBS header files */
34 #include "decoder.h"
35 #include "glue_memory.h"
36 #include "glue_debug.h"
37 #include "mg_ctxt.h"
38 #include "osd_utils.h"
39 #include "glue_assert.h"
40 
41 /*---constant definitions for this file--------------------------------------*/
42 
43 #define MAX_HEADER 8
44 
45 #ifdef OSD_8_BIT
46 #define GetColourIndex(r, g, b, a) \
47  OSD_FindNearestColourIndex((a << 24) | (r << 16) | (g << 8) | b )
48 #endif
49 
50 /*---local typedef structs for this file-------------------------------------*/
51 
52 typedef struct buffer
53 {
54  void *data;
57 } S_BUFFER;
58 
59 typedef struct info
60 {
61  /* Palette info */
63  png_colorp palette;
65 
66  /* Transparency info */
68  png_bytep trans;
69  int num_trans;
70  png_color_16p trans_values;
71 } S_INFO;
72 
73 /*---local (static) variable declarations for this file----------------------*/
74 static void ErrorFunction(png_structp png_ptr,
75  png_const_charp error_msg);
76 static void WarningFunction(png_structp png_ptr,
77  png_const_charp warning_msg);
78 /*---local function definitions----------------------------------------------*/
79 
85 static void PNG_ReadDataFunc(png_structp png_ptr, png_bytep data,
86  png_size_t length)
87 {
88  S_BUFFER *buffer = png_get_io_ptr(png_ptr);
89  if (length > (png_size_t)(buffer->len - buffer->offset))
90  {
91  length = (png_size_t)(buffer->len - buffer->offset);
92  }
93  if (length > 0)
94  {
95  memcpy(data, (char *)buffer->data + buffer->offset, length);
96  buffer->offset += length;
97  }
98 }
99 
105 static png_voidp PNG_AllocFunc(png_structp png_ptr, png_size_t size)
106 {
107  return OSD_MemAlloc(size);
108 }
109 
118 static void PNG_FreeFunc(png_structp png_ptr, png_voidp ptr)
119 {
120  OSD_MemFree(ptr);
121 }
122 
123 #ifdef OSD_8_BIT
124 
131 static void ReadGrayFunc(png_structp png_ptr, png_row_infop row_info,
132  png_bytep data)
133 {
134  unsigned int i;
135 
136  FUNCTION_START(ReadGrayFunc);
137 
138  for (i = 0; i < row_info->rowbytes; ++i)
139  {
140  data[i] = GetColourIndex(data[i], data[i], data[i], 0xff);
141  }
142 
143  FUNCTION_FINISH(ReadGrayFunc);
144 }
145 
153 static void ReadPaletteFunc(png_structp png_ptr, png_row_infop row_info,
154  png_bytep data)
155 {
156  S_INFO *info = png_get_user_transform_ptr(png_ptr);
157  unsigned int i;
158 
159  FUNCTION_START(ReadPaletteFunc);
160 
161  if (info->has_trans)
162  {
163  png_colorp col;
164  png_byte idx;
165  for (i = 0; i < row_info->rowbytes; ++i)
166  {
167  idx = data[i];
168  col = &info->palette[idx];
169  if (idx >= info->num_trans)
170  {
171  data[i] = GetColourIndex(col->red, col->green, col->blue, 0xff);
172  }
173  else
174  {
175  data[i] = GetColourIndex(col->red, col->green, col->blue,
176  info->trans[idx]);
177  }
178  }
179  }
180  else
181  {
182  png_colorp col;
183  for (i = 0; i < row_info->rowbytes; ++i)
184  {
185  col = &info->palette[data[i]];
186  data[i] = GetColourIndex(col->red, col->green, col->blue, 0xff);
187  }
188  }
189 
190  FUNCTION_FINISH(ReadPaletteFunc);
191 }
192 
200 static void ReadRGBFunc(png_structp png_ptr, png_row_infop row_info,
201  png_bytep data)
202 {
203  int i, j;
204 
205  for (i = 0, j = 0; j != row_info->rowbytes; j += 3, ++i)
206  {
207  data[i] = GetColourIndex(data[j], data[j + 1], data[j + 2], 0xff);
208  }
209 }
210 
218 static void ReadRGBAlphaFunc(png_structp png_ptr, png_row_infop row_info,
219  png_bytep data)
220 {
221  unsigned int i, j;
222 
223  for (i = 0, j = 0; j < row_info->rowbytes; j += 4, ++i)
224  {
225  data[i] = GetColourIndex(data[j], data[j + 1], data[j + 2], data[j + 3]);
226  }
227 }
228 
236 static void ReadGrayAlphaFunc(png_structp png_ptr, png_row_infop row_info,
237  png_bytep data)
238 {
239  unsigned int i, j;
240 
241  for (i = 0, j = 0; j < row_info->rowbytes; j += 2, ++i)
242  {
243  data[i] = GetColourIndex(data[j], data[j], data[j], data[j + 1]);
244  }
245 }
246 
254 static void SetTransformations(png_structp png_ptr, png_infop info_ptr,
255  S_INFO *info)
256 {
257  png_byte color_type = png_get_color_type(png_ptr, info_ptr);
258  png_byte bit_depth = png_get_bit_depth(png_ptr, info_ptr);
259 
260  memset( info, 0, sizeof(S_INFO));
261  /* Read palette (if possible) */
262  if (png_get_PLTE(png_ptr, info_ptr,
263  &info->palette, &info->num_palette) == PNG_INFO_PLTE)
264  {
265  info->has_palette = TRUE;
266  }
267 
268  /* Read transparency info (if possible) */
269  if (png_get_tRNS(png_ptr, info_ptr, &info->trans,
270  &info->num_trans, &info->trans_values) == PNG_INFO_tRNS)
271  {
272  info->has_trans = TRUE;
273  }
274 
275  png_set_strip_16(png_ptr);
276  switch (color_type)
277  {
278  case PNG_COLOR_TYPE_GRAY:
279  png_set_expand(png_ptr);
280  if (info->has_trans)
281  {
282  png_set_read_user_transform_fn(png_ptr, ReadGrayAlphaFunc);
283  }
284  else
285  {
286  png_set_read_user_transform_fn(png_ptr, ReadGrayFunc);
287  }
288  break;
289  case PNG_COLOR_TYPE_PALETTE:
290  if (bit_depth < 8)
291  {
292  png_set_packing(png_ptr);
293  }
294  png_set_read_user_transform_fn(png_ptr, ReadPaletteFunc);
295  break;
296  case PNG_COLOR_TYPE_RGB:
297  if (info->has_trans)
298  {
299  png_set_expand(png_ptr);
300  png_set_read_user_transform_fn(png_ptr, ReadRGBAlphaFunc);
301  }
302  else
303  {
304  png_set_read_user_transform_fn(png_ptr, ReadRGBFunc);
305  }
306  break;
307  case PNG_COLOR_TYPE_RGB_ALPHA:
308  png_set_read_user_transform_fn(png_ptr, ReadRGBAlphaFunc);
309  break;
310  case PNG_COLOR_TYPE_GRAY_ALPHA:
311  png_set_expand(png_ptr);
312  png_set_read_user_transform_fn(png_ptr, ReadGrayAlphaFunc);
313  break;
314  }
315  png_set_user_transform_info( png_ptr, info, 8, 1 /*i.e. mg_ctxt.bytes_per_pixel*/ );
316 }
317 
318 #endif /* OSD_8_BIT */
319 
320 
333 {
334  png_structp png_ptr;
335  png_infop info_ptr;
336  png_infop end_info;
337  S_IMAGE *p_bmp = NULL;
338  S_BUFFER buffer;
339  U16BIT row, pass, num;
340  U8BIT *row_ptr;
341 #ifndef PNG_VERSION_12
342  U8BIT **row_pointers;
343 #endif
344  #ifdef OSD_8_BIT
345  S_INFO info; /* only relevant for bytes_per_pixel == 1 */
346  #endif
347  #if defined(OSD_16_BIT) || defined(OSD_31_BIT) || defined(OSD_32_BIT)
348  U8BIT opaque;
349  #endif
350 
351  TRACE(TGRAPHICS, ("data=%p len=%d", data, len))
352 
353  if (len > 0)
354  {
355  buffer.data = data;
356  buffer.len = len;
357  buffer.offset = 0;
358 
359  do
360  {
361  /* Check PNG signature */
362 #ifdef PNG_VERSION_12
363  if (!png_check_sig(data, MAX_HEADER > len ? len : MAX_HEADER))
364 #else
365  if (png_sig_cmp(data, 0, (MAX_HEADER > len ? len : MAX_HEADER)) != 0)
366 #endif
367  {
368  break;
369  }
370  /* Create read structure */
371  png_ptr = png_create_read_struct_2(PNG_LIBPNG_VER_STRING,
372  NULL, NULL, NULL, NULL,
373  PNG_AllocFunc, PNG_FreeFunc);
374  if (png_ptr == NULL)
375  {
376  break;
377  }
378  /* Create info structure */
379  info_ptr = png_create_info_struct(png_ptr);
380  if (info_ptr == NULL)
381  {
382  png_destroy_read_struct(&png_ptr, (png_infopp)NULL,
383  (png_infopp)NULL);
384  break;
385  }
386  /* Create end-info structure */
387  end_info = png_create_info_struct(png_ptr);
388  if (end_info == NULL)
389  {
390  png_destroy_read_struct(&png_ptr, &info_ptr, (png_infopp)NULL);
391  break;
392  }
393  png_set_error_fn(png_ptr, NULL, ErrorFunction, WarningFunction);
394  if (setjmp(png_jmpbuf(png_ptr)))
395  {
396  png_destroy_read_struct(&png_ptr, &info_ptr, &end_info);
397  break;
398  }
399  /* Initialise I/O */
400  png_set_read_fn(png_ptr, &buffer, PNG_ReadDataFunc);
401 
402  /* Read info */
403  png_read_info(png_ptr, info_ptr);
404 
405 #ifdef PNG_VERSION_12
406  TRACE(TGRAPHICS, ("col_typ=%d vld=%d", info_ptr->color_type, info_ptr->valid))
407 #endif
408 
410  {
411  #ifdef OSD_8_BIT
412  SetTransformations(png_ptr, info_ptr, &info);
413  pass = png_set_interlace_handling(png_ptr);
414  /* Update info */
415  png_read_update_info(png_ptr, info_ptr);
416 
417  p_bmp = (S_IMAGE *) OSD_MemAlloc( sizeof(S_IMAGE));
418  if (p_bmp != NULL)
419  {
420 #ifdef PNG_VERSION_12
421  assert((info_ptr->rowbytes % info_ptr->width) == 0 );
422 
423  row_ptr = OSD_MemAlloc( info_ptr->width * info_ptr->height );
424 #else
425  assert((png_get_rowbytes(png_ptr, info_ptr) % png_get_image_width(png_ptr, info_ptr)) == 0 );
426 
427  row_ptr = OSD_MemAlloc(png_get_image_width(png_ptr, info_ptr) *
428  png_get_image_height(png_ptr, info_ptr));
429 #endif
430  if (row_ptr == NULL)
431  {
432  OSD_MemFree( p_bmp );
433  p_bmp = NULL;
434  }
435  else
436  {
437  p_bmp->col_buff = row_ptr;
438 #ifdef PNG_VERSION_12
439  p_bmp->width = (U16BIT)info_ptr->width;
440  p_bmp->height = (U16BIT)info_ptr->height;
441 #else
442  p_bmp->width = (U16BIT)png_get_image_width(png_ptr, info_ptr);
443  p_bmp->height = (U16BIT)png_get_image_height(png_ptr, info_ptr);
444 #endif
445  p_bmp->pix_bytes = 1;
446 #ifdef PNG_VERSION_12
447  if ((info_ptr->color_type & PNG_COLOR_MASK_ALPHA) || (info.has_trans))
448 #else
449  if ((png_get_color_type(png_ptr, info_ptr) & PNG_COLOR_MASK_ALPHA) || (info.has_trans))
450 #endif
451  {
452  p_bmp->opaque = HAS_TRANSPARENCY;
453  }
454  else
455  {
456  p_bmp->opaque = COMPLETELY_OPAQUE;
457  }
458 
459  /* Read image */
460 #ifdef PNG_VERSION_12
461  png_ptr->num_rows = p_bmp->height;
462  do
463  {
464  for (row = 0; row != p_bmp->height; row++)
465  {
466  png_read_row(png_ptr, row_ptr, png_bytep_NULL);
467  row_ptr += p_bmp->width;
468  }
469  row_ptr = p_bmp->col_buff;
470  }
471  while (--pass);
472 #else
473  row_pointers = OSD_MemAlloc(p_bmp->height * sizeof(U8BIT *));
474  if (row_pointers != NULL)
475  {
476  for (row = 0; row != p_bmp->height; row++)
477  {
478  row_pointers[row] = row_ptr + (row * p_bmp->width);
479  }
480 
481  png_read_image(png_ptr, row_pointers);
482 
483  OSD_MemFree(row_pointers);
484  }
485  USE_UNWANTED_PARAM(pass);
486 #endif
487 
488  if (p_bmp->opaque == COMPLETELY_OPAQUE)
489  {
490  for (row = 0; (p_bmp->opaque == COMPLETELY_OPAQUE) && row != p_bmp->height; ++row)
491  {
492  for (num = 0; num != p_bmp->width; ++num)
493  {
494  if (!OSD_IsColourOpaque(*row_ptr))
495  {
496  p_bmp->opaque = HAS_TRANSPARENCY;
497  break;
498  }
499  row_ptr++;
500  }
501  }
502  }
503  TRACE(TGRAPHICS, ("w=%d h=%d", p_bmp->width, p_bmp->height))
504  /*TRACE_BUFF(TGRAPHICS,p_bmp->col_buff,p_bmp->width*2)*/
505  }
506  }
507  #endif /*OSD_8_BIT*/
508  }
509  ELSE
510  {
511  #if defined(OSD_16_BIT) || defined(OSD_31_BIT) || defined(OSD_32_BIT)
512  png_set_strip_16(png_ptr);
513 #ifdef PNG_VERSION_12
514  switch (info_ptr->color_type)
515 #else
516  switch (png_get_color_type(png_ptr, info_ptr))
517 #endif
518  {
519  case PNG_COLOR_TYPE_GRAY_ALPHA:
520  case PNG_COLOR_TYPE_GRAY:
521  png_set_expand(png_ptr);
522  png_set_gray_to_rgb(png_ptr);
523  break;
524  case PNG_COLOR_TYPE_PALETTE:
525  /* for this case, could do "png_set_palette_to_rgb(png_ptr)"
526  * but that is the same as "png_set_expand(png_ptr)"
527  */
528  png_set_expand(png_ptr);
529  break;
530 
531  case PNG_COLOR_TYPE_RGB:
532 #ifdef PNG_VERSION_12
533  if (info_ptr->valid & PNG_INFO_tRNS)
534 #else
535  if (png_get_valid(png_ptr, info_ptr, PNG_INFO_tRNS) != 0)
536 #endif
537  {
538  png_set_expand(png_ptr);
539  }
540  case PNG_COLOR_TYPE_RGB_ALPHA:
541  default:;
542  }
543  pass = png_set_interlace_handling(png_ptr);
544 
545  png_read_update_info(png_ptr, info_ptr);
546 
547  num = 3;
548  opaque = COMPLETELY_OPAQUE;
549 #ifdef PNG_VERSION_12
550  if (info_ptr->color_type & PNG_COLOR_MASK_ALPHA)
551 #else
552  if (png_get_color_type(png_ptr, info_ptr) & PNG_COLOR_MASK_ALPHA)
553 #endif
554  {
555  png_set_swap_alpha(png_ptr);
556  opaque = HAS_TRANSPARENCY;
557  num++;
558  }
559  p_bmp = (S_IMAGE *) OSD_MemAlloc( sizeof(S_IMAGE));
560  if (p_bmp != NULL)
561  {
562 #ifdef PNG_VERSION_12
563  row_ptr = OSD_MemAlloc((info_ptr->width * info_ptr->height * num));
564 #else
565  row_ptr = OSD_MemAlloc( png_get_image_width(png_ptr, info_ptr) *
566  png_get_image_height(png_ptr, info_ptr) * num );
567 #endif
568  if (row_ptr)
569  {
570  p_bmp->col_buff = row_ptr;
571  p_bmp->pix_bytes = (U8BIT)num;
572  p_bmp->opaque = opaque;
573 #ifdef PNG_VERSION_12
574  p_bmp->width = (U16BIT)info_ptr->width;
575  p_bmp->height = (U16BIT)info_ptr->height;
576 #else
577  p_bmp->width = (U16BIT)png_get_image_width(png_ptr, info_ptr);
578  p_bmp->height = (U16BIT)png_get_image_height(png_ptr, info_ptr);
579 #endif
580  p_bmp->y_resolution = (U16BIT)png_get_y_pixels_per_meter( png_ptr, info_ptr );
581 
582  /* Read image */
583 #ifdef PNG_VERSION_12
584  num *= p_bmp->width;
585  /* Read image */
586  png_ptr->num_rows = p_bmp->height;
587  do
588  {
589  for (row = 0; row != p_bmp->height; row++)
590  {
591  png_read_row(png_ptr, row_ptr, png_bytep_NULL);
592  row_ptr += num;
593  }
594  row_ptr = p_bmp->col_buff;
595  }
596  while (--pass);
597 #else
598  row_pointers = OSD_MemAlloc(p_bmp->height * sizeof(U8BIT *));
599  if (row_pointers != NULL)
600  {
601  num *= p_bmp->width;
602 
603  for (row = 0; row != p_bmp->height; row++)
604  {
605  row_pointers[row] = row_ptr + (row * num);
606  }
607 
608  png_read_image(png_ptr, row_pointers);
609 
610  OSD_MemFree(row_pointers);
611  }
612  USE_UNWANTED_PARAM(pass);
613 #endif
614  TRACE(TGRAPHICS, ("w=%d h=%d", p_bmp->width, p_bmp->height))
615  /*TRACE_BUFF(TGRAPHICS,p_bmp->col_buff,num*2)*/
616  }
617  else
618  {
619  OSD_MemFree( p_bmp );
620  p_bmp = NULL;
621  }
622  }
623  #endif
624  }
625 
626  /* Finish reading */
627  png_read_end(png_ptr, end_info);
628 
629  /* Clear everything */
630  png_destroy_read_struct(&png_ptr, &info_ptr, &end_info);
631  }
632  while (0);
633  }
634  return p_bmp;
635 }
636 
637 void DEC_FreePng( S_IMAGE *data )
638 {
639  OSD_MemFree(data->col_buff);
640  OSD_MemFree(data);
641 }
642 
643 static void ErrorFunction(png_structp png_ptr,
644  png_const_charp error_msg)
645 {
646  DBG_PRINTF("PNG_ERR: %s\n", error_msg);
647 }
648 
649 static void WarningFunction(png_structp png_ptr,
650  png_const_charp warning_msg)
651 {
652  DBG_PRINTF("PNG_WARN: %s\n", warning_msg);
653 }
654 
OSD utility functions.
#define MAX_HEADER
Definition: mg_png.c:43
#define IF_COL_DEPTH(cd)
Definition: mg_ctxt.h:65
void * data
Definition: mg_png.c:54
#define FUNCTION_FINISH(name)
Definition: glue_debug.h:143
S_IMAGE * DEC_DecodePng(U8BIT *data, U32BIT len)
Allocate memory for png and decode bitmap.
Definition: mg_png.c:332
#define OSD_MemAlloc
Definition: glue_memory.h:96
#define DBG_PRINTF(...)
Definition: glue_debug.h:127
png_color_16p trans_values
Definition: mg_png.c:70
Debug tracing.
U8BIT * col_buff
Definition: decoder.h:63
int num_trans
Definition: mg_png.c:69
Definition: mg_png.c:59
struct buffer S_BUFFER
U8BIT pix_bytes
Definition: decoder.h:61
U16BIT y_resolution
Definition: decoder.h:60
uint8_t U8BIT
Definition: techtype.h:82
#define GetColourIndex(r, g, b, a)
Definition: mg_jpg.c:65
void DEC_FreePng(S_IMAGE *data)
Free memory allocated for PNG bitmap.
Definition: mg_png.c:637
Memory functions.
#define HAS_TRANSPARENCY
Definition: decoder.h:30
U8BIT opaque
Definition: decoder.h:62
int num_palette
Definition: mg_png.c:64
U16BIT height
Definition: decoder.h:59
#define ELSE
Definition: mg_ctxt.h:66
png_colorp palette
Definition: mg_png.c:63
int32_t S32BIT
Definition: techtype.h:87
U16BIT width
Definition: decoder.h:58
uint16_t U16BIT
Definition: techtype.h:84
The functions in this file are OPTIONALLY provided by Receiver Platform *.
S32BIT offset
Definition: mg_png.c:56
struct info S_INFO
#define COLOUR_FORMAT_PALETTE
Definition: mheg5_control.h:79
S32BIT len
Definition: mg_png.c:55
Definition: mg_png.c:52
define asserts
BOOLEAN has_palette
Definition: mg_png.c:62
BOOLEAN has_trans
Definition: mg_png.c:67
png_bytep trans
Definition: mg_png.c:68
U8BIT BOOLEAN
Definition: techtype.h:99
#define USE_UNWANTED_PARAM(param)
Definition: techtype.h:48
#define TRUE
Definition: techtype.h:69
Interface to OSD.
#define FUNCTION_START(name)
Definition: glue_debug.h:142
#define OSD_MemFree
Definition: glue_memory.h:97
#define COMPLETELY_OPAQUE
Definition: decoder.h:31
uint32_t U32BIT
Definition: techtype.h:86
#define TRACE(t, x)
Definition: glue_debug.h:118