X-Git-Url: http://review.tizen.org/git/?a=blobdiff_plain;f=dali%2Finternal%2Fimaging%2Fcommon%2Floader-png.cpp;h=ae6382252f6da70b63e7909b560c7b9621eac8b6;hb=3ff3d757a67b27cd14340e6fbd1cc4035d2cde8c;hp=34050fc31f11089e47020e54f5b6dbf43fd4b371;hpb=21f9c67694945e3eea731adcacba3817a0dbf25e;p=platform%2Fcore%2Fuifw%2Fdali-adaptor.git diff --git a/dali/internal/imaging/common/loader-png.cpp b/dali/internal/imaging/common/loader-png.cpp index 34050fc..ae63822 100644 --- a/dali/internal/imaging/common/loader-png.cpp +++ b/dali/internal/imaging/common/loader-png.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2020 Samsung Electronics Co., Ltd. + * Copyright (c) 2022 Samsung Electronics Co., Ltd. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -19,21 +19,19 @@ #include -#include #include +#include +#include #include #include -#include namespace Dali { namespace TizenPlatform { - namespace { - // simple class to enforce clean-up of PNG structures struct auto_png { @@ -52,45 +50,47 @@ struct auto_png } png_structp& png; - png_infop& info; + png_infop& info; }; // struct auto_png; -bool LoadPngHeader(FILE *fp, unsigned int &width, unsigned int &height, png_structp &png, png_infop &info) +bool LoadPngHeader(FILE* fp, unsigned int& width, unsigned int& height, png_structp& png, png_infop& info) { - png_byte header[8] = { 0 }; + png_byte header[8] = {0}; // Check header to see if it is a PNG file size_t size = fread(header, 1, 8, fp); - if(size != 8) + if(DALI_UNLIKELY(size != 8)) { + DALI_LOG_ERROR("fread failed\n"); return false; } - if(png_sig_cmp(header, 0, 8)) + if(DALI_UNLIKELY(png_sig_cmp(header, 0, 8))) { + DALI_LOG_ERROR("png_sig_cmp failed\n"); return false; } png = png_create_read_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL); - if(!png) + if(DALI_UNLIKELY(!png)) { - DALI_LOG_WARNING("Can't create PNG read structure\n"); + DALI_LOG_ERROR("Can't create PNG read structure\n"); return false; } info = png_create_info_struct(png); - if(!info) + if(DALI_UNLIKELY(!info)) { - DALI_LOG_WARNING("png_create_info_struct failed\n"); + DALI_LOG_ERROR("png_create_info_struct failed\n"); return false; } png_set_expand(png); - if(setjmp(png_jmpbuf(png))) + if(DALI_UNLIKELY(setjmp(png_jmpbuf(png)))) { - DALI_LOG_WARNING("error during png_init_io\n"); + DALI_LOG_ERROR("error during png_init_io\n"); return false; } @@ -101,40 +101,40 @@ bool LoadPngHeader(FILE *fp, unsigned int &width, unsigned int &height, png_stru png_read_info(png, info); // dimensions - width = png_get_image_width(png, info); + width = png_get_image_width(png, info); height = png_get_image_height(png, info); return true; } -} // namespace - anonymous +} // namespace -bool LoadPngHeader( const Dali::ImageLoader::Input& input, unsigned int& width, unsigned int& height ) +bool LoadPngHeader(const Dali::ImageLoader::Input& input, unsigned int& width, unsigned int& height) { - png_structp png = NULL; - png_infop info = NULL; - auto_png autoPng(png, info); + png_structp png = NULL; + png_infop info = NULL; + auto_png autoPng(png, info); - bool success = LoadPngHeader( input.file, width, height, png, info ); + bool success = LoadPngHeader(input.file, width, height, png, info); return success; } -bool LoadBitmapFromPng( const Dali::ImageLoader::Input& input, Dali::Devel::PixelBuffer& bitmap ) +bool LoadBitmapFromPng(const Dali::ImageLoader::Input& input, Dali::Devel::PixelBuffer& bitmap) { - png_structp png = NULL; - png_infop info = NULL; - auto_png autoPng(png, info); + png_structp png = NULL; + png_infop info = NULL; + auto_png autoPng(png, info); /// @todo: consider parameters unsigned int y; unsigned int width, height; - png_bytep *rows; - unsigned int bpp = 0; // bytes per pixel - bool valid = false; + png_bytep* rows; + unsigned int bpp = 0; // bytes per pixel + bool valid = false; // Load info from the header - if( !LoadPngHeader( input.file, width, height, png, info ) ) + if(DALI_UNLIKELY(!LoadPngHeader(input.file, width, height, png, info))) { return false; } @@ -145,7 +145,7 @@ bool LoadBitmapFromPng( const Dali::ImageLoader::Input& input, Dali::Devel::Pixe unsigned int colordepth = png_get_bit_depth(png, info); // Ask PNGLib to convert high precision images into something we can use: - if (colordepth == 16) + if(colordepth == 16) { png_set_strip_16(png); colordepth = 8; @@ -153,13 +153,13 @@ bool LoadBitmapFromPng( const Dali::ImageLoader::Input& input, Dali::Devel::Pixe png_byte colortype = png_get_color_type(png, info); - if( colortype == PNG_COLOR_TYPE_GRAY || - colortype == PNG_COLOR_TYPE_GRAY_ALPHA ) + if(colortype == PNG_COLOR_TYPE_GRAY || + colortype == PNG_COLOR_TYPE_GRAY_ALPHA) { - if( colortype == PNG_COLOR_TYPE_GRAY ) + if(colortype == PNG_COLOR_TYPE_GRAY) { pixelFormat = Pixel::L8; - if( png_get_valid(png, info, PNG_INFO_tRNS) ) + if(png_get_valid(png, info, PNG_INFO_tRNS)) { colortype = PNG_COLOR_TYPE_GRAY_ALPHA; /* expand transparency entry -> alpha channel if present */ @@ -172,7 +172,7 @@ bool LoadBitmapFromPng( const Dali::ImageLoader::Input& input, Dali::Devel::Pixe pixelFormat = Pixel::LA88; } - if( colordepth < 8 ) + if(colordepth < 8) { /* expand gray (w/reduced bits) -> 8-bit RGB if necessary */ png_set_expand_gray_1_2_4_to_8(png); @@ -181,20 +181,20 @@ bool LoadBitmapFromPng( const Dali::ImageLoader::Input& input, Dali::Devel::Pixe } valid = true; } - else if(colortype == PNG_COLOR_TYPE_RGB ) + else if(colortype == PNG_COLOR_TYPE_RGB) { switch(colordepth) { case 8: { pixelFormat = Pixel::RGB888; - valid = true; + valid = true; break; } - case 5: /// @todo is this correct for RGB16 5-6-5 ? + case 5: /// @todo is this correct for RGB16 5-6-5 ? { pixelFormat = Pixel::RGB565; - valid = true; + valid = true; break; } default: @@ -210,7 +210,7 @@ bool LoadBitmapFromPng( const Dali::ImageLoader::Input& input, Dali::Devel::Pixe case 8: { pixelFormat = Pixel::RGBA8888; - valid = true; + valid = true; break; } default: @@ -226,7 +226,7 @@ bool LoadBitmapFromPng( const Dali::ImageLoader::Input& input, Dali::Devel::Pixe case 1: { pixelFormat = Pixel::LA88; - valid = true; + valid = true; break; } @@ -240,7 +240,7 @@ bool LoadBitmapFromPng( const Dali::ImageLoader::Input& input, Dali::Devel::Pixe if(png_get_valid(png, info, PNG_INFO_tRNS) == 0x10) { pixelFormat = Pixel::RGBA8888; - valid = true; + valid = true; } else { @@ -259,9 +259,9 @@ bool LoadBitmapFromPng( const Dali::ImageLoader::Input& input, Dali::Devel::Pixe } } - if( !valid ) + if(DALI_UNLIKELY(!valid)) { - DALI_LOG_WARNING( "Unsupported png format\n" ); + DALI_LOG_ERROR("Unsupported png format\n"); return false; } @@ -270,20 +270,20 @@ bool LoadBitmapFromPng( const Dali::ImageLoader::Input& input, Dali::Devel::Pixe png_read_update_info(png, info); - if(setjmp(png_jmpbuf(png))) + if(DALI_UNLIKELY(setjmp(png_jmpbuf(png)))) { - DALI_LOG_WARNING("error during png_read_image\n"); + DALI_LOG_ERROR("error during png_read_image\n"); return false; } unsigned int rowBytes = png_get_rowbytes(png, info); - unsigned int bufferWidth = GetTextureDimension(width); - unsigned int bufferHeight = GetTextureDimension(height); - unsigned int stride = bufferWidth*bpp; + unsigned int bufferWidth = GetTextureDimension(width); + unsigned int bufferHeight = GetTextureDimension(height); + unsigned int stride = bufferWidth * bpp; // not sure if this ever happens - if( rowBytes > stride ) + if(rowBytes > stride) { stride = GetTextureDimension(rowBytes); @@ -299,15 +299,20 @@ bool LoadBitmapFromPng( const Dali::ImageLoader::Input& input, Dali::Devel::Pixe default: break; } - + } + rows = reinterpret_cast(malloc(sizeof(png_bytep) * height)); + if(DALI_UNLIKELY(!rows)) + { + DALI_LOG_ERROR("malloc is failed\n"); + return false; } // decode the whole image into bitmap buffer auto pixels = (bitmap = Dali::Devel::PixelBuffer::New(bufferWidth, bufferHeight, pixelFormat)).GetBuffer(); DALI_ASSERT_DEBUG(pixels); - rows = reinterpret_cast< png_bytep* >( malloc(sizeof(png_bytep) * height) ); - for(y=0; y* const encoded_img = static_cast*>(png_get_io_ptr(png_ptr)); + if(encoded_img) { - // Recover our buffer for writing into: - Vector* const encoded_img = static_cast< Vector* >( png_get_io_ptr(png_ptr) ); - if(encoded_img) - { - const Vector::SizeType bufferSize = encoded_img->Count(); - encoded_img->Resize( bufferSize + length ); //< Can throw OOM. - unsigned char* const bufferBack = encoded_img->Begin() + bufferSize; - memcpy(bufferBack, data, length); - } - else - { - DALI_LOG_ERROR("PNG buffer for write to memory was passed from libpng as null.\n"); - } + const Vector::SizeType bufferSize = encoded_img->Count(); + encoded_img->Resize(bufferSize + length); //< Can throw OOM. + unsigned char* const bufferBack = encoded_img->Begin() + bufferSize; + memcpy(bufferBack, data, length); } - catch(...) + else { - DALI_LOG_ERROR("C++ Exception caught\n"); + DALI_LOG_ERROR("PNG buffer for write to memory was passed from libpng as null.\n"); } } - - /** Override the flush with a NOP to prevent libpng trying cstdlib file io. */ - extern "C" void FlushData(png_structp png_ptr) + catch(...) { + DALI_LOG_ERROR("C++ Exception caught\n"); + } +} + +/** Override the flush with a NOP to prevent libpng trying cstdlib file io. */ +extern "C" void FlushData(png_structp png_ptr) +{ #ifdef DEBUG_ENABLED - Debug::LogMessage(Debug::DebugInfo, "PNG Flush"); + Debug::LogMessageWithFunctionLine(Debug::DebugInfo, "PNG Flush"); #endif // DEBUG_ENABLED - } } +} // namespace /** * Potential improvements: @@ -402,20 +407,20 @@ namespace * 7. If caller asks for no compression, bypass libpng and blat raw data to * disk, topped and tailed with header/tail blocks. */ -bool EncodeToPng( const unsigned char* const pixelBuffer, Vector& encodedPixels, std::size_t width, std::size_t height, Pixel::Format pixelFormat ) +bool EncodeToPng(const unsigned char* const pixelBuffer, Vector& encodedPixels, std::size_t width, std::size_t height, Pixel::Format pixelFormat) { // Translate pixel format enum: - int pngPixelFormat = -1; - unsigned pixelBytes = 0; - bool rgbaOrder = true; + int pngPixelFormat = -1; + unsigned pixelBytes = 0; + bool rgbaOrder = true; // Account for RGB versus BGR and presence of alpha in input pixels: - switch( pixelFormat ) + switch(pixelFormat) { case Pixel::RGB888: { pngPixelFormat = PNG_COLOR_TYPE_RGB; - pixelBytes = 3; + pixelBytes = 3; break; } case Pixel::BGRA8888: @@ -426,12 +431,12 @@ bool EncodeToPng( const unsigned char* const pixelBuffer, Vector& case Pixel::RGBA8888: { pngPixelFormat = PNG_COLOR_TYPE_RGB_ALPHA; - pixelBytes = 4; + pixelBytes = 4; break; } default: { - DALI_LOG_ERROR( "Unsupported pixel format for encoding to PNG.\n" ); + DALI_LOG_ERROR("Unsupported pixel format for encoding to PNG.\n"); return false; } } @@ -444,7 +449,7 @@ bool EncodeToPng( const unsigned char* const pixelBuffer, Vector& return false; } /* Allocate/initialize the image information data. REQUIRED */ - png_infop info_ptr = png_create_info_struct( png_ptr ); + png_infop info_ptr = png_create_info_struct(png_ptr); if(!info_ptr) { png_destroy_write_struct(&png_ptr, NULL); @@ -471,37 +476,35 @@ bool EncodeToPng( const unsigned char* const pixelBuffer, Vector& // Explicitly limit the number of filters used per scanline to speed us up: // png_set_filter(png_ptr, 0, PNG_FILTER_NONE); ///!ToDo: Try this once baseline profile is in place. - // PNG_FILTER_SUB | - // PNG_FILTER_UP | - // PNG_FILTER_AVE | - // PNG_FILTER_PAETH | - // PNG_ALL_FILTERS); + // PNG_FILTER_SUB | + // PNG_FILTER_UP | + // PNG_FILTER_AVE | + // PNG_FILTER_PAETH | + // PNG_ALL_FILTERS); // Play with Zlib parameters in optimisation phase: - // png_set_compression_mem_level(png_ptr, 8); - // png_set_compression_strategy(png_ptr, - // Z_DEFAULT_STRATEGY); - // png_set_compression_window_bits(png_ptr, 15); - // png_set_compression_method(png_ptr, 8); - // png_set_compression_buffer_size(png_ptr, 8192) + // png_set_compression_mem_level(png_ptr, 8); + // png_set_compression_strategy(png_ptr, + // Z_DEFAULT_STRATEGY); + // png_set_compression_window_bits(png_ptr, 15); + // png_set_compression_method(png_ptr, 8); + // png_set_compression_buffer_size(png_ptr, 8192) // Let lib_png know if the pixel bytes are in BGR(A) order: if(!rgbaOrder) { - png_set_bgr( png_ptr ); + png_set_bgr(png_ptr); } // Set the image information: - png_set_IHDR(png_ptr, info_ptr, width, height, 8, - pngPixelFormat, interlace, - PNG_COMPRESSION_TYPE_BASE, PNG_FILTER_TYPE_BASE); + png_set_IHDR(png_ptr, info_ptr, width, height, 8, pngPixelFormat, interlace, PNG_COMPRESSION_TYPE_BASE, PNG_FILTER_TYPE_BASE); // Start to output the PNG data to our buffer: png_write_info(png_ptr, info_ptr); // Walk the rows: - const unsigned row_step = width * pixelBytes; - png_bytep row_ptr = const_cast(pixelBuffer); - const png_bytep row_end = row_ptr + height * row_step; + const unsigned row_step = width * pixelBytes; + png_bytep row_ptr = const_cast(pixelBuffer); + const png_bytep row_end = row_ptr + height * row_step; for(; row_ptr < row_end; row_ptr += row_step) { png_write_row(png_ptr, row_ptr);