| 4879 | } |
| 4880 | |
| 4881 | static int DecodeTiledLevel(EXRImage* exr_image, const EXRHeader* exr_header, |
| 4882 | const OffsetData& offset_data, |
| 4883 | const std::vector<size_t>& channel_offset_list, |
| 4884 | int pixel_data_size, |
| 4885 | const unsigned char* head, const size_t size, |
| 4886 | std::string* err) { |
| 4887 | int num_channels = exr_header->num_channels; |
| 4888 | |
| 4889 | int level_index = LevelIndex(exr_image->level_x, exr_image->level_y, exr_header->tile_level_mode, offset_data.num_x_levels); |
| 4890 | int num_y_tiles = int(offset_data.offsets[size_t(level_index)].size()); |
| 4891 | if (num_y_tiles < 1) { |
| 4892 | return TINYEXR_ERROR_INVALID_DATA; |
| 4893 | } |
| 4894 | int num_x_tiles = int(offset_data.offsets[size_t(level_index)][0].size()); |
| 4895 | if (num_x_tiles < 1) { |
| 4896 | return TINYEXR_ERROR_INVALID_DATA; |
| 4897 | } |
| 4898 | int num_tiles = num_x_tiles * num_y_tiles; |
| 4899 | |
| 4900 | int err_code = TINYEXR_SUCCESS; |
| 4901 | |
| 4902 | enum { |
| 4903 | EF_SUCCESS = 0, |
| 4904 | EF_INVALID_DATA = 1, |
| 4905 | EF_INSUFFICIENT_DATA = 2, |
| 4906 | EF_FAILED_TO_DECODE = 4 |
| 4907 | }; |
| 4908 | #if TINYEXR_HAS_CXX11 && (TINYEXR_USE_THREAD > 0) |
| 4909 | std::atomic<unsigned> error_flag(EF_SUCCESS); |
| 4910 | #else |
| 4911 | unsigned error_flag(EF_SUCCESS); |
| 4912 | #endif |
| 4913 | |
| 4914 | // Although the spec says : "...the data window is subdivided into an array of smaller rectangles...", |
| 4915 | // the IlmImf library allows the dimensions of the tile to be larger (or equal) than the dimensions of the data window. |
| 4916 | #if 0 |
| 4917 | if ((exr_header->tile_size_x > exr_image->width || exr_header->tile_size_y > exr_image->height) && |
| 4918 | exr_image->level_x == 0 && exr_image->level_y == 0) { |
| 4919 | if (err) { |
| 4920 | (*err) += "Failed to decode tile data.\n"; |
| 4921 | } |
| 4922 | err_code = TINYEXR_ERROR_INVALID_DATA; |
| 4923 | } |
| 4924 | #endif |
| 4925 | exr_image->tiles = static_cast<EXRTile*>( |
| 4926 | calloc(static_cast<size_t>(num_tiles), sizeof(EXRTile))); |
| 4927 | |
| 4928 | #if TINYEXR_HAS_CXX11 && (TINYEXR_USE_THREAD > 0) |
| 4929 | std::vector<std::thread> workers; |
| 4930 | std::atomic<int> tile_count(0); |
| 4931 | |
| 4932 | int num_threads = std::max(1, int(std::thread::hardware_concurrency())); |
| 4933 | if (num_threads > int(num_tiles)) { |
| 4934 | num_threads = int(num_tiles); |
| 4935 | } |
| 4936 | |
| 4937 | for (int t = 0; t < num_threads; t++) { |
| 4938 | workers.emplace_back(std::thread([&]() |
no test coverage detected