| 44 | // ---------------------------------------------------------------------------------------- |
| 45 | |
| 46 | void png_loader::load(std::function<std::size_t(char*,std::size_t)> clb) |
| 47 | { |
| 48 | // Read header |
| 49 | png_byte sig[8]; |
| 50 | if (clb((char*)sig, 8) != 8) |
| 51 | throw image_load_error("png_loader: error reading file stream"); |
| 52 | if (png_sig_cmp(sig, 0, 8 ) != 0) |
| 53 | throw image_load_error("png_loader: format error"); |
| 54 | |
| 55 | // Create structs |
| 56 | png_structp png_ptr = png_create_read_struct( PNG_LIBPNG_VER_STRING, NULL, &png_loader_user_error_fn_silent, &png_loader_user_warning_fn_silent ); |
| 57 | if (png_ptr == NULL) |
| 58 | throw image_load_error("Error while reading PNG file : png_create_read_struct()"); |
| 59 | |
| 60 | png_infop info_ptr = png_create_info_struct( png_ptr ); |
| 61 | if ( info_ptr == NULL ) |
| 62 | { |
| 63 | png_destroy_read_struct(&png_ptr, ( png_infopp )NULL, ( png_infopp )NULL ); |
| 64 | throw image_load_error("Error while reading PNG file : png_create_info_struct()"); |
| 65 | } |
| 66 | |
| 67 | png_infop end_info = png_create_info_struct( png_ptr ); |
| 68 | if ( end_info == NULL ) |
| 69 | { |
| 70 | png_destroy_read_struct(&png_ptr, &info_ptr, ( png_infopp )NULL ); |
| 71 | throw image_load_error("Error while reading PNG file : png_create_info_struct()"); |
| 72 | } |
| 73 | |
| 74 | if (setjmp(png_jmpbuf(png_ptr))) |
| 75 | { |
| 76 | // If you get here, then there was an error while parsing. |
| 77 | png_destroy_read_struct(&png_ptr, &info_ptr, &end_info); |
| 78 | throw image_load_error("png_loader: parse error"); |
| 79 | } |
| 80 | |
| 81 | png_set_palette_to_rgb(png_ptr); |
| 82 | png_set_read_fn(png_ptr, &clb, png_reader_callback); |
| 83 | png_set_sig_bytes(png_ptr, 8); |
| 84 | // flags force one byte per channel output |
| 85 | byte_orderer bo; |
| 86 | int png_transforms = PNG_TRANSFORM_PACKING; |
| 87 | if (bo.host_is_little_endian()) |
| 88 | png_transforms |= PNG_TRANSFORM_SWAP_ENDIAN; |
| 89 | png_read_png(png_ptr, info_ptr, png_transforms, NULL); |
| 90 | |
| 91 | // If you get here, you are no longer affected by C's crazy longjmp |
| 92 | finalizer = std::shared_ptr<char>(new char, [=](char* ptr) mutable { |
| 93 | delete ptr; |
| 94 | png_destroy_read_struct(&png_ptr, &info_ptr, &end_info); |
| 95 | }); |
| 96 | |
| 97 | color_type = png_get_color_type( png_ptr, info_ptr ); |
| 98 | height = png_get_image_height( png_ptr, info_ptr ); |
| 99 | width = png_get_image_width( png_ptr, info_ptr ); |
| 100 | bit_depth_ = png_get_bit_depth( png_ptr, info_ptr ); |
| 101 | rows = (unsigned char**)png_get_rows( png_ptr, info_ptr ); |
| 102 | |
| 103 | if (!is_gray() && !is_graya() && !is_rgb() && !is_rgba()) |
no test coverage detected