| 843 | } |
| 844 | |
| 845 | static bool SaveState_ReadScreenshot(zip_t* zf, u32* out_width, u32* out_height, std::vector<u32>* out_pixels) |
| 846 | { |
| 847 | auto zff = zip_fopen_managed(zf, EntryFilename_Screenshot, 0); |
| 848 | if (!zff) |
| 849 | return false; |
| 850 | |
| 851 | png_structp png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING, nullptr, nullptr, nullptr); |
| 852 | if (!png_ptr) |
| 853 | return false; |
| 854 | |
| 855 | png_infop info_ptr = png_create_info_struct(png_ptr); |
| 856 | if (!info_ptr) |
| 857 | { |
| 858 | png_destroy_read_struct(&png_ptr, nullptr, nullptr); |
| 859 | return false; |
| 860 | } |
| 861 | |
| 862 | ScopedGuard cleanup([&png_ptr, &info_ptr]() { |
| 863 | png_destroy_read_struct(&png_ptr, &info_ptr, nullptr); |
| 864 | }); |
| 865 | |
| 866 | if (setjmp(png_jmpbuf(png_ptr))) |
| 867 | return false; |
| 868 | |
| 869 | png_set_read_fn(png_ptr, zff.get(), [](png_structp png_ptr, png_bytep data_ptr, png_size_t size) { |
| 870 | zip_fread(static_cast<zip_file_t*>(png_get_io_ptr(png_ptr)), data_ptr, size); |
| 871 | }); |
| 872 | |
| 873 | png_read_info(png_ptr, info_ptr); |
| 874 | |
| 875 | png_uint_32 width = 0; |
| 876 | png_uint_32 height = 0; |
| 877 | int bitDepth = 0; |
| 878 | int colorType = -1; |
| 879 | if (png_get_IHDR(png_ptr, info_ptr, &width, &height, &bitDepth, &colorType, nullptr, nullptr, nullptr) != 1 || |
| 880 | width == 0 || height == 0) |
| 881 | { |
| 882 | return false; |
| 883 | } |
| 884 | |
| 885 | const png_uint_32 bytesPerRow = png_get_rowbytes(png_ptr, info_ptr); |
| 886 | std::vector<u8> rowData(bytesPerRow); |
| 887 | |
| 888 | *out_width = width; |
| 889 | *out_height = height; |
| 890 | out_pixels->resize(width * height); |
| 891 | |
| 892 | for (u32 y = 0; y < height; y++) |
| 893 | { |
| 894 | png_read_row(png_ptr, static_cast<png_bytep>(rowData.data()), nullptr); |
| 895 | |
| 896 | const u8* row_ptr = rowData.data(); |
| 897 | u32* out_ptr = &out_pixels->at(y * width); |
| 898 | if (colorType == PNG_COLOR_TYPE_RGB) |
| 899 | { |
| 900 | for (u32 x = 0; x < width; x++) |
| 901 | { |
| 902 | u32 pixel = static_cast<u32>(*(row_ptr)++); |
no test coverage detected