| 544 | using namespace imageio; |
| 545 | |
| 546 | void CommandExtract::unpackAndSave422(std::string filepath, bool appendExtension, |
| 547 | VkFormat vkFormat, const FormatDescriptor& format, uint32_t width, uint32_t height, |
| 548 | const char* data, std::size_t size) { |
| 549 | (void) vkFormat; |
| 550 | |
| 551 | assert(format.model() == KHR_DF_MODEL_YUVSDA); |
| 552 | assert(format.find(KHR_DF_CHANNEL_YUVSDA_Y)); |
| 553 | // Create a custom format with the same precision but with only 3 channels |
| 554 | // Reuse similar 4 channel VkFormats and drop the last channel (There is no RGB variant of 10X6 and 12X4) |
| 555 | const auto precision = format.find(KHR_DF_CHANNEL_YUVSDA_Y)->bitLength + 1u; |
| 556 | auto unpackedFormat = createFormatDescriptor( |
| 557 | precision == 8 ? VK_FORMAT_R8G8B8A8_UNORM : |
| 558 | precision == 10 ? VK_FORMAT_R10X6G10X6B10X6A10X6_UNORM_4PACK16 : |
| 559 | precision == 12 ? VK_FORMAT_R12X4G12X4B12X4A12X4_UNORM_4PACK16 : |
| 560 | precision == 16 ? VK_FORMAT_R16G16B16A16_UNORM : |
| 561 | VK_FORMAT_UNDEFINED, *this); |
| 562 | unpackedFormat.removeLastChannel(); |
| 563 | |
| 564 | // 1 pixel (block) with 4 channel is unpacked to 2 pixel with 3 channels: Y0,Y1,U,V -> R0,G0,B0,R1,G1,B1 |
| 565 | const auto blockYUVBytes = format.pixelByteCount(); |
| 566 | const auto blockDimensionX = format.basic.texelBlockDimension0 + 1; |
| 567 | const auto blockDimensionY = format.basic.texelBlockDimension1 + 1; |
| 568 | const auto pixelBytes = unpackedFormat.pixelByteCount(); |
| 569 | const auto channelBytes = pixelBytes / 3; |
| 570 | assert(format.sampleCount() == 4); |
| 571 | assert(format.basic.texelBlockDimension0 + 1 == 2); |
| 572 | assert(format.basic.texelBlockDimension1 + 1 == 1); |
| 573 | assert(format.basic.texelBlockDimension2 + 1 == 1); |
| 574 | assert(format.basic.texelBlockDimension3 + 1 == 1); |
| 575 | assert(size == width * height * blockYUVBytes / blockDimensionX / blockDimensionY); |
| 576 | (void) size; |
| 577 | (void) blockDimensionY; |
| 578 | |
| 579 | uint32_t y0Offset = 0; |
| 580 | uint32_t y0Bits = 0; |
| 581 | uint32_t y0PositionX = 0; |
| 582 | uint32_t y1Offset = 0; |
| 583 | uint32_t y1Bits = 0; |
| 584 | uint32_t y1PositionX = 0; |
| 585 | uint32_t uOffset = 0; |
| 586 | uint32_t uBits = 0; |
| 587 | uint32_t uPositionX = 0; |
| 588 | uint32_t vOffset = 0; |
| 589 | uint32_t vBits = 0; |
| 590 | uint32_t vPositionX = 0; |
| 591 | |
| 592 | for (const auto& sample : format.samples) { |
| 593 | switch (sample.channelType) { |
| 594 | case KHR_DF_CHANNEL_YUVSDA_Y: |
| 595 | if (y0Bits != 0) { |
| 596 | y1Offset = sample.bitOffset; |
| 597 | y1Bits = sample.bitLength + 1; |
| 598 | y1PositionX = sample.samplePosition0; |
| 599 | } else { |
| 600 | y0Offset = sample.bitOffset; |
| 601 | y0Bits = sample.bitLength + 1; |
| 602 | y0PositionX = sample.samplePosition0; |
| 603 | } |
nothing calls this directly
no test coverage detected