| 4954 | } |
| 4955 | |
| 4956 | static int DecodeTiledLevel(EXRImage* exr_image, const EXRHeader* exr_header, |
| 4957 | const OffsetData& offset_data, |
| 4958 | const std::vector<size_t>& channel_offset_list, |
| 4959 | int pixel_data_size, |
| 4960 | const unsigned char* head, const size_t size, |
| 4961 | std::string* err) { |
| 4962 | int num_channels = exr_header->num_channels; |
| 4963 | |
| 4964 | int level_index = LevelIndex(exr_image->level_x, exr_image->level_y, exr_header->tile_level_mode, offset_data.num_x_levels); |
| 4965 | int num_y_tiles = int(offset_data.offsets[size_t(level_index)].size()); |
| 4966 | if (num_y_tiles < 1) { |
| 4967 | return TINYEXR_ERROR_INVALID_DATA; |
| 4968 | } |
| 4969 | int num_x_tiles = int(offset_data.offsets[size_t(level_index)][0].size()); |
| 4970 | if (num_x_tiles < 1) { |
| 4971 | return TINYEXR_ERROR_INVALID_DATA; |
| 4972 | } |
| 4973 | int num_tiles = num_x_tiles * num_y_tiles; |
| 4974 | |
| 4975 | int err_code = TINYEXR_SUCCESS; |
| 4976 | |
| 4977 | enum { |
| 4978 | EF_SUCCESS = 0, |
| 4979 | EF_INVALID_DATA = 1, |
| 4980 | EF_INSUFFICIENT_DATA = 2, |
| 4981 | EF_FAILED_TO_DECODE = 4 |
| 4982 | }; |
| 4983 | #if TINYEXR_HAS_CXX11 && (TINYEXR_USE_THREAD > 0) |
| 4984 | std::atomic<unsigned> error_flag(EF_SUCCESS); |
| 4985 | #else |
| 4986 | unsigned error_flag(EF_SUCCESS); |
| 4987 | #endif |
| 4988 | |
| 4989 | // Although the spec says : "...the data window is subdivided into an array of smaller rectangles...", |
| 4990 | // the IlmImf library allows the dimensions of the tile to be larger (or equal) than the dimensions of the data window. |
| 4991 | #if 0 |
| 4992 | if ((exr_header->tile_size_x > exr_image->width || exr_header->tile_size_y > exr_image->height) && |
| 4993 | exr_image->level_x == 0 && exr_image->level_y == 0) { |
| 4994 | if (err) { |
| 4995 | (*err) += "Failed to decode tile data.\n"; |
| 4996 | } |
| 4997 | err_code = TINYEXR_ERROR_INVALID_DATA; |
| 4998 | } |
| 4999 | #endif |
| 5000 | exr_image->tiles = static_cast<EXRTile*>( |
| 5001 | calloc(static_cast<size_t>(num_tiles), sizeof(EXRTile))); |
| 5002 | |
| 5003 | #if TINYEXR_HAS_CXX11 && (TINYEXR_USE_THREAD > 0) |
| 5004 | std::vector<std::thread> workers; |
| 5005 | std::atomic<int> tile_count(0); |
| 5006 | |
| 5007 | int num_threads = std::max(1, int(std::thread::hardware_concurrency())); |
| 5008 | #if (TINYEXR_MAX_THREADS > 0) |
| 5009 | num_threads = std::min(num_threads,TINYEXR_MAX_THREADS); |
| 5010 | #endif |
| 5011 | if (num_threads > int(num_tiles)) { |
| 5012 | num_threads = int(num_tiles); |
| 5013 | } |
no test coverage detected