Details | Last modification | View Log | RSS feed
| Rev | Author | Line No. | Line |
|---|---|---|---|
| 716 | lvd | 1 | #include "std.h" |
| 2 | |||
| 3 | #include "emul.h" |
||
| 4 | #include "vars.h" |
||
| 5 | #include "sshot_png.h" |
||
| 6 | |||
| 7 | typedef void (PNGAPI *png_write_end_ptr) PNGARG((png_structp png_ptr, |
||
| 8 | png_infop info_ptr)); |
||
| 9 | typedef void (PNGAPI *png_write_image_ptr) PNGARG((png_structp png_ptr, |
||
| 10 | png_bytepp image)); |
||
| 11 | typedef void (PNGAPI *png_set_bgr_ptr) PNGARG((png_structp png_ptr)); |
||
| 12 | typedef void (PNGAPI *png_write_info_ptr) PNGARG((png_structp png_ptr, |
||
| 13 | png_infop info_ptr)); |
||
| 14 | typedef void (PNGAPI *png_set_IHDR_ptr) PNGARG((png_structp png_ptr, |
||
| 15 | png_infop info_ptr, png_uint_32 width, png_uint_32 height, int bit_depth, |
||
| 16 | int color_type, int interlace_method, int compression_method, |
||
| 17 | int filter_method)); |
||
| 18 | typedef void (PNGAPI *png_set_write_fn_ptr) PNGARG((png_structp png_ptr, |
||
| 19 | png_voidp io_ptr, png_rw_ptr write_data_fn, png_flush_ptr output_flush_fn)); |
||
| 20 | typedef void (PNGAPI *png_destroy_write_struct_ptr) |
||
| 21 | PNGARG((png_structpp png_ptr_ptr, png_infopp info_ptr_ptr)); |
||
| 22 | typedef png_infop (PNGAPI *png_create_info_struct_ptr) |
||
| 23 | PNGARG((png_structp png_ptr)); |
||
| 24 | typedef void (PNGAPI *png_set_compression_level_ptr) PNGARG((png_structp png_ptr, |
||
| 25 | int level)); |
||
| 26 | typedef png_structp (PNGAPI *png_create_write_struct_ptr) |
||
| 27 | PNGARG((png_const_charp user_png_ver, png_voidp error_ptr, |
||
| 28 | png_error_ptr error_fn, png_error_ptr warn_fn)); |
||
| 29 | typedef void (PNGAPI *png_set_filter_ptr) PNGARG((png_structp png_ptr, int method, |
||
| 30 | int filters)); |
||
| 31 | |||
| 784 | DimkaM | 32 | static png_error_ptr png_error_p = nullptr; |
| 33 | static png_write_end_ptr png_write_end_p = nullptr; |
||
| 34 | static png_write_image_ptr png_write_image_p = nullptr; |
||
| 35 | static png_set_bgr_ptr png_set_bgr_p = nullptr; |
||
| 36 | static png_write_info_ptr png_write_info_p = nullptr; |
||
| 37 | static png_set_IHDR_ptr png_set_IHDR_p = nullptr; |
||
| 38 | static png_set_write_fn_ptr png_set_write_fn_p = nullptr; |
||
| 39 | static png_destroy_write_struct_ptr png_destroy_write_struct_p = nullptr; |
||
| 40 | static png_create_info_struct_ptr png_create_info_struct_p = nullptr; |
||
| 41 | static png_set_compression_level_ptr png_set_compression_level_p = nullptr; |
||
| 42 | static png_create_write_struct_ptr png_create_write_struct_p = nullptr; |
||
| 43 | static png_set_filter_ptr png_set_filter_p = nullptr; |
||
| 716 | lvd | 44 | |
| 784 | DimkaM | 45 | static HMODULE PngDll = nullptr; |
| 716 | lvd | 46 | bool PngInit() |
| 47 | { |
||
| 1081 | fyrex | 48 | #if defined(_WIN64) || defined(AMD64) |
| 49 | PngDll = LoadLibrary("libpng64.dll"); |
||
| 50 | #else |
||
| 51 | PngDll = LoadLibrary("libpng16.dll"); |
||
| 52 | #endif |
||
| 716 | lvd | 53 | if(!PngDll) |
| 54 | return false; |
||
| 55 | png_error_p = (png_error_ptr)GetProcAddress(PngDll, "png_error"); |
||
| 56 | if(!png_error_p) |
||
| 57 | return false; |
||
| 58 | png_write_end_p = (png_write_end_ptr)GetProcAddress(PngDll, "png_write_end"); |
||
| 59 | if(!png_write_end_p) |
||
| 60 | return false; |
||
| 61 | png_write_image_p = (png_write_image_ptr)GetProcAddress(PngDll, "png_write_image"); |
||
| 62 | if(!png_write_image_p) |
||
| 63 | return false; |
||
| 64 | png_set_bgr_p = (png_set_bgr_ptr)GetProcAddress(PngDll, "png_set_bgr"); |
||
| 65 | if(!png_set_bgr_p) |
||
| 66 | return false; |
||
| 67 | png_write_info_p = (png_write_info_ptr)GetProcAddress(PngDll, "png_write_info"); |
||
| 68 | if(!png_write_info_p) |
||
| 69 | return false; |
||
| 70 | png_set_IHDR_p = (png_set_IHDR_ptr)GetProcAddress(PngDll, "png_set_IHDR"); |
||
| 71 | if(!png_set_IHDR_p) |
||
| 72 | return false; |
||
| 73 | png_set_write_fn_p = (png_set_write_fn_ptr)GetProcAddress(PngDll, "png_set_write_fn"); |
||
| 74 | if(!png_set_write_fn_p) |
||
| 75 | return false; |
||
| 76 | png_destroy_write_struct_p = (png_destroy_write_struct_ptr)GetProcAddress(PngDll, "png_destroy_write_struct"); |
||
| 77 | if(!png_destroy_write_struct_p) |
||
| 78 | return false; |
||
| 79 | png_create_info_struct_p = (png_create_info_struct_ptr)GetProcAddress(PngDll, "png_create_info_struct"); |
||
| 80 | if(!png_create_info_struct_p) |
||
| 81 | return false; |
||
| 82 | png_set_compression_level_p = (png_set_compression_level_ptr)GetProcAddress(PngDll, "png_set_compression_level"); |
||
| 83 | if(!png_set_compression_level_p) |
||
| 84 | return false; |
||
| 85 | png_create_write_struct_p = (png_create_write_struct_ptr)GetProcAddress(PngDll, "png_create_write_struct"); |
||
| 86 | if(!png_create_write_struct_p) |
||
| 87 | return false; |
||
| 88 | png_set_filter_p = (png_set_filter_ptr)GetProcAddress(PngDll, "png_set_filter"); |
||
| 89 | if(!png_set_filter_p) |
||
| 90 | return false; |
||
| 91 | return true; |
||
| 92 | } |
||
| 93 | |||
| 94 | void PngDone() |
||
| 95 | { |
||
| 96 | if(PngDll) |
||
| 97 | FreeLibrary(PngDll); |
||
| 98 | } |
||
| 99 | |||
| 784 | DimkaM | 100 | static png_structp png_ptr = nullptr; |
| 101 | static png_infop info_ptr = nullptr; |
||
| 1081 | fyrex | 102 | static FILE *io_ptr; |
| 716 | lvd | 103 | |
| 104 | static void |
||
| 105 | PNGAPI |
||
| 106 | png_write_data(png_structp png_ptr, png_bytep data, png_size_t length) |
||
| 107 | { |
||
| 784 | DimkaM | 108 | size_t check; |
| 716 | lvd | 109 | |
| 1081 | fyrex | 110 | check = fwrite(data, 1, length, (FILE *)(io_ptr)); |
| 716 | lvd | 111 | if (check != length) |
| 112 | { |
||
| 113 | png_error_p(png_ptr, "Write Error"); |
||
| 114 | } |
||
| 115 | } |
||
| 116 | |||
| 117 | static void |
||
| 118 | PNGAPI |
||
| 119 | png_flush(png_structp png_ptr) |
||
| 120 | { |
||
| 1081 | fyrex | 121 | /* |
| 716 | lvd | 122 | FILE *io_ptr; |
| 123 | io_ptr = (FILE *)CVT_PTR((png_ptr->io_ptr)); |
||
| 1081 | fyrex | 124 | */ |
| 125 | if (io_ptr != nullptr) |
||
| 716 | lvd | 126 | fflush(io_ptr); |
| 1081 | fyrex | 127 | |
| 716 | lvd | 128 | } |
| 129 | |||
| 130 | BOOL PngSaveImage (FILE *pfFile, png_byte *pDiData, |
||
| 131 | int iWidth, int iHeight, png_color bkgColor) |
||
| 132 | { |
||
| 784 | DimkaM | 133 | (void)bkgColor; |
| 134 | |||
| 716 | lvd | 135 | const int ciBitDepth = 8; |
| 136 | const int ciChannels = 3; |
||
| 137 | |||
| 138 | png_uint_32 ulRowBytes; |
||
| 784 | DimkaM | 139 | static png_byte **ppbRowPointers = nullptr; |
| 716 | lvd | 140 | int i; |
| 141 | |||
| 142 | // prepare the standard PNG structures |
||
| 784 | DimkaM | 143 | png_ptr = png_create_write_struct_p(PNG_LIBPNG_VER_STRING, nullptr, nullptr, nullptr); |
| 716 | lvd | 144 | if (!png_ptr) |
| 145 | { |
||
| 146 | return FALSE; |
||
| 147 | } |
||
| 148 | |||
| 149 | png_set_filter_p(png_ptr, 0, PNG_NO_FILTERS); |
||
| 150 | |||
| 151 | png_set_compression_level_p(png_ptr, 4/*Z_BEST_COMPRESSION*/); |
||
| 152 | |||
| 153 | info_ptr = png_create_info_struct_p(png_ptr); |
||
| 154 | if (!info_ptr) |
||
| 155 | { |
||
| 784 | DimkaM | 156 | png_destroy_write_struct_p(&png_ptr, (png_infopp) nullptr); |
| 716 | lvd | 157 | return FALSE; |
| 158 | } |
||
| 159 | |||
| 160 | // initialize the png structure |
||
| 1081 | fyrex | 161 | io_ptr = pfFile; |
| 162 | png_set_write_fn_p(png_ptr, (png_voidp)pfFile, (png_rw_ptr)png_write_data, png_flush); |
||
| 716 | lvd | 163 | |
| 164 | // we're going to write a very simple 3x8 bit RGB image |
||
| 784 | DimkaM | 165 | png_set_IHDR_p(png_ptr, info_ptr, png_uint_32(iWidth), png_uint_32(iHeight), ciBitDepth, |
| 716 | lvd | 166 | PNG_COLOR_TYPE_RGB, PNG_INTERLACE_NONE, PNG_COMPRESSION_TYPE_BASE, |
| 167 | PNG_FILTER_TYPE_BASE); |
||
| 168 | |||
| 169 | // write the file header information |
||
| 170 | png_write_info_p(png_ptr, info_ptr); |
||
| 171 | |||
| 172 | // swap the BGR pixels in the DiData structure to RGB |
||
| 173 | png_set_bgr_p(png_ptr); |
||
| 174 | |||
| 175 | // row_bytes is the width x number of channels |
||
| 784 | DimkaM | 176 | ulRowBytes = png_uint_32(iWidth * ciChannels); |
| 716 | lvd | 177 | |
| 178 | // we can allocate memory for an array of row-pointers |
||
| 784 | DimkaM | 179 | ppbRowPointers = (png_bytepp) malloc(unsigned(iHeight) * sizeof(png_bytep)); |
| 716 | lvd | 180 | |
| 181 | // set the individual row-pointers to point at the correct offsets |
||
| 182 | for (i = 0; i < iHeight; i++) |
||
| 784 | DimkaM | 183 | ppbRowPointers[i] = pDiData + unsigned(i) * (((ulRowBytes + 3) >> 2) << 2); |
| 716 | lvd | 184 | |
| 185 | // write out the entire image data in one call |
||
| 186 | png_write_image_p(png_ptr, ppbRowPointers); |
||
| 187 | |||
| 188 | // write the additional chunks to the PNG file (not really needed) |
||
| 189 | png_write_end_p(png_ptr, info_ptr); |
||
| 190 | |||
| 191 | // and we're done |
||
| 192 | free (ppbRowPointers); |
||
| 784 | DimkaM | 193 | ppbRowPointers = nullptr; |
| 1081 | fyrex | 194 | |
| 195 | |||
| 716 | lvd | 196 | |
| 197 | // clean up after the write, and free any memory allocated |
||
| 784 | DimkaM | 198 | png_destroy_write_struct_p(&png_ptr, (png_infopp) nullptr); |
| 716 | lvd | 199 | |
| 200 | return TRUE; |
||
| 201 | } |