| 776 | } |
| 777 | |
| 778 | static bool SaveState_CompressScreenshot(SaveStateScreenshotData* data, zip_t* zf) |
| 779 | { |
| 780 | zip_error_t ze = {}; |
| 781 | zip_source_t* const zs = zip_source_buffer_create(nullptr, 0, 0, &ze); |
| 782 | if (!zs) |
| 783 | return false; |
| 784 | |
| 785 | if (zip_source_begin_write(zs) != 0) |
| 786 | { |
| 787 | zip_source_free(zs); |
| 788 | return false; |
| 789 | } |
| 790 | |
| 791 | ScopedGuard zs_free([zs]() { zip_source_free(zs); }); |
| 792 | |
| 793 | png_structp png_ptr = png_create_write_struct(PNG_LIBPNG_VER_STRING, nullptr, nullptr, nullptr); |
| 794 | png_infop info_ptr = nullptr; |
| 795 | if (!png_ptr) |
| 796 | return false; |
| 797 | |
| 798 | ScopedGuard cleanup([&png_ptr, &info_ptr]() { |
| 799 | if (png_ptr) |
| 800 | png_destroy_write_struct(&png_ptr, info_ptr ? &info_ptr : nullptr); |
| 801 | }); |
| 802 | |
| 803 | info_ptr = png_create_info_struct(png_ptr); |
| 804 | if (!info_ptr) |
| 805 | return false; |
| 806 | |
| 807 | if (setjmp(png_jmpbuf(png_ptr))) |
| 808 | return false; |
| 809 | |
| 810 | png_set_write_fn(png_ptr, zs, [](png_structp png_ptr, png_bytep data_ptr, png_size_t size) { |
| 811 | zip_source_write(static_cast<zip_source_t*>(png_get_io_ptr(png_ptr)), data_ptr, size); |
| 812 | }, [](png_structp png_ptr) {}); |
| 813 | png_set_compression_level(png_ptr, 5); |
| 814 | png_set_IHDR(png_ptr, info_ptr, data->width, data->height, 8, PNG_COLOR_TYPE_RGBA, |
| 815 | PNG_INTERLACE_NONE, PNG_COMPRESSION_TYPE_DEFAULT, PNG_FILTER_TYPE_DEFAULT); |
| 816 | png_write_info(png_ptr, info_ptr); |
| 817 | |
| 818 | for (u32 y = 0; y < data->height; ++y) |
| 819 | { |
| 820 | // ensure the alpha channel is set to opaque |
| 821 | u32* row = &data->pixels[y * data->width]; |
| 822 | for (u32 x = 0; x < data->width; x++) |
| 823 | row[x] |= 0xFF000000u; |
| 824 | |
| 825 | png_write_row(png_ptr, reinterpret_cast<png_bytep>(row)); |
| 826 | } |
| 827 | |
| 828 | png_write_end(png_ptr, nullptr); |
| 829 | |
| 830 | if (zip_source_commit_write(zs) != 0) |
| 831 | return false; |
| 832 | |
| 833 | const s64 file_index = zip_file_add(zf, EntryFilename_Screenshot, zs, 0); |
| 834 | if (file_index < 0) |
| 835 | return false; |
no test coverage detected