44 #define DBG(x) STB_SPDebugWrite x 49 #define PNG_HEADER_SIZE 8 51 #define ST_ALPHA(x) (((x) * 128 + 127) / 255) 77 static BOOLEAN ReadPNGHeader(U8BIT *image_data, U32BIT num_bytes, U16BIT *pixel_width,
78 U16BIT *pixel_height, U32BIT *bytes_per_row, BOOLEAN keep_open,
S_PNG_READER *reader);
80 static png_voidp PNG_Malloc(png_structp png_ptr, png_size_t size);
81 static void PNG_Free(png_structp png_ptr, png_voidp addr);
82 static void PNG_ReadData(png_structp png_ptr, png_bytep data, png_size_t length);
99 U32BIT *output_data_size, U16BIT *pixel_width, U16BIT *pixel_height)
104 U8BIT **row_pointers;
108 U32BIT bytes_per_line;
117 U8BIT alpha, red, green, blue;
123 *output_data_size = 0;
125 if ((image_data != NULL) && (image_data_size >= PNG_HEADER_SIZE))
127 if (ReadPNGHeader(image_data, image_data_size, pixel_width, pixel_height, &rowbytes, TRUE, &reader))
131 bytes_per_line = *pixel_width * 2;
133 bytes_per_line = *pixel_width * 4;
135 *output_data_size = *pixel_height * bytes_per_line;
138 if (*output_data != NULL)
140 memset(*output_data, 0, *output_data_size);
143 source_data = (U8BIT *)
STB_GetMemory(rowbytes * *pixel_height);
144 if (source_data != NULL)
147 row_pointers = (U8BIT **)
STB_GetMemory(*pixel_height *
sizeof(U8BIT *));
148 if (row_pointers != NULL)
150 for (row = 0; row < *pixel_height; row++)
152 row_pointers[row] = source_data + (row * rowbytes);
155 png_read_image(reader.png_ptr, row_pointers);
157 channels = png_get_channels(reader.png_ptr, reader.info_ptr);
161 dest_line = (U16BIT *)*output_data;
163 dest_line = (U32BIT *)*output_data;
166 for (row = 0; row < *pixel_height; dest_line += *pixel_width, row++)
168 src = row_pointers[row];
173 for (pixel = *pixel_width, dest = dest_line; pixel > 0;
174 dest++, src += 3, pixel--)
181 *dest = (*dest << 4) | (red >> 4);
182 *dest = (*dest << 4) | (green >> 4);
183 *dest = (*dest << 4) | (blue >> 4);
186 alpha = ST_ALPHA(0xff);
190 *dest = (alpha << 24) | (red << 16) | (green << 8) | blue;
197 for (pixel = *pixel_width, dest = dest_line; pixel > 0;
198 dest++, src += 4, pixel--)
205 *dest = (alpha >> 4);
206 *dest = (*dest << 4) | (red >> 4);
207 *dest = (*dest << 4) | (green >> 4);
208 *dest = (*dest << 4) | (blue >> 4);
211 alpha = ST_ALPHA(alpha);
213 *dest = (alpha << 24) | (red << 16) | (green << 8) | blue;
233 png_destroy_read_struct(&reader.png_ptr, &reader.info_ptr, &reader.end_info);
253 static BOOLEAN ReadPNGHeader(U8BIT *image_data, U32BIT num_bytes, U16BIT *pixel_width,
254 U16BIT *pixel_height, U32BIT *bytes_per_row, BOOLEAN keep_open,
S_PNG_READER *reader)
257 U32BIT num_header_bytes;
262 #if (PNG_LIBPNG_VER != 10202) || defined (ENABLE_DEBUG) 266 U32BIT resx, resy, res_unit;
269 FUNCTION_START(ReadPNGHeader);
273 if ((image_data != NULL) && (num_bytes > 0))
275 if (num_bytes < PNG_HEADER_SIZE)
277 num_header_bytes = num_bytes;
281 num_header_bytes = PNG_HEADER_SIZE;
285 if (png_sig_cmp(image_data, 0, num_header_bytes) == 0)
287 png_ptr = png_create_read_struct_2(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL, NULL,
288 PNG_Malloc, PNG_Free);
291 info_ptr = png_create_info_struct(png_ptr);
292 if (info_ptr != NULL)
294 end_info = png_create_info_struct(png_ptr);
295 if (end_info != NULL)
300 reader->buffer.data = image_data;
301 reader->buffer.length = num_bytes;
302 reader->buffer.offset = 0;
305 png_set_read_fn(png_ptr, &reader->buffer, PNG_ReadData);
309 buffer.data = image_data;
310 buffer.length = num_bytes;
314 png_set_read_fn(png_ptr, &buffer, PNG_ReadData);
318 png_read_info(png_ptr, info_ptr);
321 DBG((
"Original PNG image:"));
322 DBG((
" width=%d", png_get_image_width(png_ptr, info_ptr)));
323 DBG((
" height=%d", png_get_image_height(png_ptr, info_ptr)));
324 DBG((
" bitdepth=%d", png_get_bit_depth(png_ptr, info_ptr)));
325 DBG((
" colortype=%d", png_get_color_type(png_ptr, info_ptr)));
326 DBG((
" rowbytes=%d", png_get_rowbytes(png_ptr, info_ptr)));
327 DBG((
" channels=%d", png_get_channels(png_ptr, info_ptr)));
328 DBG((
" compression=%d", png_get_compression_type(png_ptr, info_ptr)));
329 if (png_get_pHYs(png_ptr, info_ptr, &resx, &resy, &res_unit) != 0)
331 DBG((
" resx=%lu, resy=%lu, unit=%lu", resx, resy, res_unit));
336 png_set_strip_16(png_ptr);
340 #if (PNG_LIBPNG_VER != 10202) || defined (ENABLE_DEBUG) 341 bitdepth = png_get_bit_depth(png_ptr, info_ptr);
344 switch (png_get_color_type(png_ptr, info_ptr))
346 case PNG_COLOR_TYPE_GRAY:
347 #if (PNG_LIBPNG_VER != 10202) 350 png_set_expand_gray_1_2_4_to_8(png_ptr);
353 png_set_gray_to_rgb(png_ptr);
356 case PNG_COLOR_TYPE_PALETTE:
357 png_set_palette_to_rgb(png_ptr);
358 if (png_get_valid(png_ptr, info_ptr, PNG_INFO_tRNS))
360 png_set_tRNS_to_alpha(png_ptr);
364 case PNG_COLOR_TYPE_RGB:
367 case PNG_COLOR_TYPE_RGB_ALPHA:
368 png_set_swap_alpha(png_ptr);
372 DBG((
"PNG: unhandled PNG colour type %lu", png_get_color_type(png_ptr, info_ptr)));
377 png_read_update_info(png_ptr, info_ptr);
380 DBG((
"Output PNG image:"));
381 DBG((
" width=%d", png_get_image_width(png_ptr, info_ptr)));
382 DBG((
" height=%d", png_get_image_height(png_ptr, info_ptr)));
383 DBG((
" bitdepth=%d", png_get_bit_depth(png_ptr, info_ptr)));
384 DBG((
" colortype=%d", png_get_color_type(png_ptr, info_ptr)));
385 DBG((
" rowbytes=%d", png_get_rowbytes(png_ptr, info_ptr)));
386 DBG((
" channels=%d", png_get_channels(png_ptr, info_ptr)));
387 DBG((
" compression=%d", png_get_compression_type(png_ptr, info_ptr)));
388 if (png_get_pHYs(png_ptr, info_ptr, &resx, &resy, &res_unit) != 0)
390 DBG((
" resx=%lu, resy=%lu, unit=%lu", resx, resy, res_unit));
394 *pixel_width = (U16BIT)png_get_image_width(png_ptr, info_ptr);
395 *pixel_height = (U16BIT)png_get_image_height(png_ptr, info_ptr);
396 *bytes_per_row = png_get_rowbytes(png_ptr, info_ptr);
398 if (keep_open && (reader != NULL))
401 reader->png_ptr = png_ptr;
402 reader->info_ptr = info_ptr;
403 reader->end_info = end_info;
407 png_destroy_read_struct(&png_ptr, &info_ptr, &end_info);
414 png_destroy_read_struct(&png_ptr, &info_ptr, NULL);
419 png_destroy_read_struct(&png_ptr, NULL, NULL);
425 FUNCTION_FINISH(ReadPNGHeader);
436 static png_voidp PNG_Malloc(png_structp png_ptr, png_size_t size)
440 FUNCTION_START(PNG_Malloc);
441 USE_UNWANTED_PARAM(png_ptr);
445 FUNCTION_FINISH(PNG_Malloc);
455 static void PNG_Free(png_structp png_ptr, png_voidp addr)
457 FUNCTION_START(PNG_Free);
458 USE_UNWANTED_PARAM(png_ptr);
462 FUNCTION_FINISH(PNG_Free);
471 static void PNG_ReadData(png_structp png_ptr, png_bytep data, png_size_t length)
475 FUNCTION_START(PNG_ReadData);
477 if (length > buffer->length - buffer->offset)
479 length = buffer->length - buffer->offset;
484 memcpy(data, buffer->data + buffer->offset, length);
485 buffer->offset += length;
488 FUNCTION_FINISH(PNG_ReadData);
void * STB_GetMemory(U32BIT bytes)
Attempts to allocate memory from the heap.
BOOLEAN STB_IMGConvertPNG(U8BIT *image_data, U32BIT image_data_size, U8BIT **output_data, U32BIT *output_data_size, U16BIT *pixel_width, U16BIT *pixel_height)
Converts the given PNG image data to a bitmap image that can be displayed on-screen with the given bi...
void STB_FreeMemory(void *addr)
Releases previously allocated heap memory.
Debug functions header file.
System Wide Global Technical Data Type Definitions.
Header file - Function prototypes for heap memory.