| 6388 | } |
| 6389 | |
| 6390 | static int DecodeTiledLevel(EXRImage* exr_image, const EXRHeader* exr_header, |
| 6391 | const OffsetData& offset_data, |
| 6392 | const std::vector<size_t>& channel_offset_list, |
| 6393 | int pixel_data_size, |
| 6394 | const unsigned char* head, const size_t size, |
| 6395 | std::string* err) { |
| 6396 | int num_channels = exr_header->num_channels; |
| 6397 | |
| 6398 | int level_index = LevelIndex(exr_image->level_x, exr_image->level_y, exr_header->tile_level_mode, offset_data.num_x_levels); |
| 6399 | int num_y_tiles = int(offset_data.offsets[size_t(level_index)].size()); |
| 6400 | if (num_y_tiles < 1) { |
| 6401 | return TINYEXR_ERROR_INVALID_DATA; |
| 6402 | } |
| 6403 | int num_x_tiles = int(offset_data.offsets[size_t(level_index)][0].size()); |
| 6404 | if (num_x_tiles < 1) { |
| 6405 | return TINYEXR_ERROR_INVALID_DATA; |
| 6406 | } |
| 6407 | int num_tiles = num_x_tiles * num_y_tiles; |
| 6408 | |
| 6409 | int err_code = TINYEXR_SUCCESS; |
| 6410 | |
| 6411 | enum { |
| 6412 | EF_SUCCESS = 0, |
| 6413 | EF_INVALID_DATA = 1, |
| 6414 | EF_INSUFFICIENT_DATA = 2, |
| 6415 | EF_FAILED_TO_DECODE = 4 |
| 6416 | }; |
| 6417 | #if TINYEXR_HAS_CXX11 && (TINYEXR_USE_THREAD > 0) |
| 6418 | std::atomic<unsigned> error_flag(EF_SUCCESS); |
| 6419 | #else |
| 6420 | unsigned error_flag(EF_SUCCESS); |
| 6421 | #endif |
| 6422 | |
| 6423 | // Although the spec says : "...the data window is subdivided into an array of smaller rectangles...", |
| 6424 | // the IlmImf library allows the dimensions of the tile to be larger (or equal) than the dimensions of the data window. |
| 6425 | #if 0 |
| 6426 | if ((exr_header->tile_size_x > exr_image->width || exr_header->tile_size_y > exr_image->height) && |
| 6427 | exr_image->level_x == 0 && exr_image->level_y == 0) { |
| 6428 | if (err) { |
| 6429 | (*err) += "Failed to decode tile data.\n"; |
| 6430 | } |
| 6431 | err_code = TINYEXR_ERROR_INVALID_DATA; |
| 6432 | } |
| 6433 | #endif |
| 6434 | exr_image->tiles = static_cast<EXRTile*>( |
| 6435 | calloc(static_cast<size_t>(num_tiles), sizeof(EXRTile))); |
| 6436 | |
| 6437 | #if TINYEXR_HAS_CXX11 && (TINYEXR_USE_THREAD > 0) |
| 6438 | std::vector<std::thread> workers; |
| 6439 | std::atomic<int> tile_count(0); |
| 6440 | |
| 6441 | int num_threads = std::max(1, int(std::thread::hardware_concurrency())); |
| 6442 | #if (TINYEXR_MAX_THREADS > 0) |
| 6443 | num_threads = std::min(num_threads,TINYEXR_MAX_THREADS); |
| 6444 | #endif |
| 6445 | if (num_threads > int(num_tiles)) { |
| 6446 | num_threads = int(num_tiles); |
| 6447 | } |
no test coverage detected