| 588 | } |
| 589 | |
| 590 | void Bitmap::saveImage( |
| 591 | const std::filesystem::path& path, |
| 592 | uint32_t width, |
| 593 | uint32_t height, |
| 594 | FileFormat fileFormat, |
| 595 | ExportFlags exportFlags, |
| 596 | ResourceFormat resourceFormat, |
| 597 | bool isTopDown, |
| 598 | void* pData |
| 599 | ) |
| 600 | { |
| 601 | FALCOR_CHECK(pData, "Provided data must not be nullptr."); |
| 602 | FALCOR_CHECK(fileFormat != FileFormat::DdsFile, "Cannot save DDS files. Use ImageIO instead."); |
| 603 | if (is_set(exportFlags, ExportFlags::Uncompressed) && is_set(exportFlags, ExportFlags::Lossy)) |
| 604 | FALCOR_THROW("Incompatible flags: lossy cannot be combined with uncompressed."); |
| 605 | if (is_set(exportFlags, ExportFlags::ExrFloat16) && |
| 606 | (!is_set(exportFlags, ExportFlags::Uncompressed) || fileFormat != FileFormat::ExrFile)) |
| 607 | FALCOR_THROW("Incompatible flags: EXR float16 can only be set for uncompressed EXR files."); |
| 608 | |
| 609 | int flags = 0; |
| 610 | FIBITMAP* pImage = nullptr; |
| 611 | uint32_t bytesPerPixel = getFormatBytesPerBlock(resourceFormat); |
| 612 | |
| 613 | // Convert 8-bit RGBA to BGRA byte order. |
| 614 | // TODO: Replace this code for swapping channels. Can't use FreeImage masks b/c they only care about 16 bpp images. |
| 615 | if (resourceFormat == ResourceFormat::RGBA8Unorm || resourceFormat == ResourceFormat::RGBA8Snorm || |
| 616 | resourceFormat == ResourceFormat::RGBA8UnormSrgb) |
| 617 | { |
| 618 | for (uint32_t a = 0; a < width * height; a++) |
| 619 | { |
| 620 | uint32_t* pPixel = (uint32_t*)pData; |
| 621 | pPixel += a; |
| 622 | uint8_t* ch = (uint8_t*)pPixel; |
| 623 | std::swap(ch[0], ch[2]); |
| 624 | if (is_set(exportFlags, ExportFlags::ExportAlpha) == false) |
| 625 | { |
| 626 | ch[3] = 0xff; |
| 627 | } |
| 628 | } |
| 629 | } |
| 630 | |
| 631 | if (fileFormat == Bitmap::FileFormat::PfmFile || fileFormat == Bitmap::FileFormat::ExrFile) |
| 632 | { |
| 633 | std::vector<float> floatData; |
| 634 | if (isConvertibleToRGBA32Float(resourceFormat)) |
| 635 | { |
| 636 | floatData = convertToRGBA32Float(resourceFormat, width, height, pData); |
| 637 | pData = floatData.data(); |
| 638 | resourceFormat = ResourceFormat::RGBA32Float; |
| 639 | bytesPerPixel = 16; |
| 640 | } |
| 641 | else if (bytesPerPixel != 16 && bytesPerPixel != 12) |
| 642 | { |
| 643 | FALCOR_THROW("Only support for 32-bit/channel RGB/RGBA or 16-bit RGBA images as PFM/EXR files."); |
| 644 | } |
| 645 | |
| 646 | const bool exportAlpha = is_set(exportFlags, ExportFlags::ExportAlpha); |
| 647 |
nothing calls this directly
no test coverage detected