| 470 | } |
| 471 | |
| 472 | Task<void> ImageData::orientToTopLeft(int priority) { |
| 473 | if (orientation == EOrientation::None || orientation == EOrientation::TopLeft) { |
| 474 | orientation = EOrientation::TopLeft; |
| 475 | co_return; |
| 476 | } |
| 477 | |
| 478 | const bool swapAxes = orientation >= EOrientation::LeftTop; |
| 479 | |
| 480 | struct DataDesc { |
| 481 | shared_ptr<PixelBuffer> data; |
| 482 | Vector2i size; |
| 483 | |
| 484 | struct Hash { |
| 485 | size_t operator()(const DataDesc& interval) const { return hash<shared_ptr<PixelBuffer>>()(interval.data); } |
| 486 | }; |
| 487 | |
| 488 | bool operator==(const DataDesc& other) const { return data == other.data && size == other.size; } |
| 489 | }; |
| 490 | |
| 491 | unordered_set<DataDesc, DataDesc::Hash> channelData; |
| 492 | for (auto& c : channels) { |
| 493 | // TODO: ensure channel data is interleaved if multiple channels share the same data buffer |
| 494 | |
| 495 | channelData.insert({c.dataBuf(), c.size()}); |
| 496 | if (swapAxes) { |
| 497 | c.setSize({c.size().y(), c.size().x()}); |
| 498 | } |
| 499 | } |
| 500 | |
| 501 | vector<Task<nanogui::Vector2i>> tasks; |
| 502 | for (auto& c : channelData) { |
| 503 | tasks.emplace_back(tev::orientToTopLeft(*c.data, c.size, orientation, priority)); |
| 504 | } |
| 505 | |
| 506 | co_await awaitAll(span{tasks}); |
| 507 | |
| 508 | const auto referenceWindow = displayWindow.isValid() ? displayWindow : (dataWindow.isValid() ? dataWindow : Box2i{size()}); |
| 509 | if (dataWindow.isValid()) { |
| 510 | dataWindow = applyOrientation(orientation, dataWindow, referenceWindow); |
| 511 | } |
| 512 | |
| 513 | if (displayWindow.isValid()) { |
| 514 | displayWindow = applyOrientation(orientation, displayWindow, referenceWindow); |
| 515 | } |
| 516 | |
| 517 | orientation = EOrientation::TopLeft; |
| 518 | } |
| 519 | |
| 520 | void ImageData::updateLayers() { |
| 521 | layers.clear(); |
nothing calls this directly
no test coverage detected