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 | } |