1*a67afe4dSAndroid Build Coastguard Worker /*-------------------------------------
2*a67afe4dSAndroid Build Coastguard Worker * PNGFILE.C -- Image File Functions
3*a67afe4dSAndroid Build Coastguard Worker *-------------------------------------
4*a67afe4dSAndroid Build Coastguard Worker *
5*a67afe4dSAndroid Build Coastguard Worker * Copyright 2000,2017 Willem van Schaik.
6*a67afe4dSAndroid Build Coastguard Worker *
7*a67afe4dSAndroid Build Coastguard Worker * This code is released under the libpng license.
8*a67afe4dSAndroid Build Coastguard Worker * For conditions of distribution and use, see the disclaimer
9*a67afe4dSAndroid Build Coastguard Worker * and license in png.h
10*a67afe4dSAndroid Build Coastguard Worker */
11*a67afe4dSAndroid Build Coastguard Worker
12*a67afe4dSAndroid Build Coastguard Worker #include <windows.h>
13*a67afe4dSAndroid Build Coastguard Worker #include <commdlg.h>
14*a67afe4dSAndroid Build Coastguard Worker #include <stdio.h>
15*a67afe4dSAndroid Build Coastguard Worker #include <stdlib.h>
16*a67afe4dSAndroid Build Coastguard Worker #include <zlib.h>
17*a67afe4dSAndroid Build Coastguard Worker
18*a67afe4dSAndroid Build Coastguard Worker #include "png.h"
19*a67afe4dSAndroid Build Coastguard Worker #include "pngfile.h"
20*a67afe4dSAndroid Build Coastguard Worker #include "cexcept.h"
21*a67afe4dSAndroid Build Coastguard Worker
22*a67afe4dSAndroid Build Coastguard Worker define_exception_type(const char *);
23*a67afe4dSAndroid Build Coastguard Worker extern struct exception_context the_exception_context[1];
24*a67afe4dSAndroid Build Coastguard Worker struct exception_context the_exception_context[1];
25*a67afe4dSAndroid Build Coastguard Worker png_const_charp msg;
26*a67afe4dSAndroid Build Coastguard Worker
27*a67afe4dSAndroid Build Coastguard Worker static OPENFILENAME ofn;
28*a67afe4dSAndroid Build Coastguard Worker
29*a67afe4dSAndroid Build Coastguard Worker static png_structp png_ptr = NULL;
30*a67afe4dSAndroid Build Coastguard Worker static png_infop info_ptr = NULL;
31*a67afe4dSAndroid Build Coastguard Worker
32*a67afe4dSAndroid Build Coastguard Worker
33*a67afe4dSAndroid Build Coastguard Worker /* cexcept interface */
34*a67afe4dSAndroid Build Coastguard Worker
35*a67afe4dSAndroid Build Coastguard Worker static void
png_cexcept_error(png_structp png_ptr,png_const_charp msg)36*a67afe4dSAndroid Build Coastguard Worker png_cexcept_error(png_structp png_ptr, png_const_charp msg)
37*a67afe4dSAndroid Build Coastguard Worker {
38*a67afe4dSAndroid Build Coastguard Worker if(png_ptr)
39*a67afe4dSAndroid Build Coastguard Worker ;
40*a67afe4dSAndroid Build Coastguard Worker #ifdef PNG_CONSOLE_IO_SUPPORTED
41*a67afe4dSAndroid Build Coastguard Worker fprintf(stderr, "libpng error: %s\n", msg);
42*a67afe4dSAndroid Build Coastguard Worker #endif
43*a67afe4dSAndroid Build Coastguard Worker {
44*a67afe4dSAndroid Build Coastguard Worker Throw msg;
45*a67afe4dSAndroid Build Coastguard Worker }
46*a67afe4dSAndroid Build Coastguard Worker }
47*a67afe4dSAndroid Build Coastguard Worker
48*a67afe4dSAndroid Build Coastguard Worker /* Windows open-file functions */
49*a67afe4dSAndroid Build Coastguard Worker
PngFileInitialize(HWND hwnd)50*a67afe4dSAndroid Build Coastguard Worker void PngFileInitialize (HWND hwnd)
51*a67afe4dSAndroid Build Coastguard Worker {
52*a67afe4dSAndroid Build Coastguard Worker static TCHAR szFilter[] = TEXT ("PNG Files (*.PNG)\0*.png\0")
53*a67afe4dSAndroid Build Coastguard Worker TEXT ("All Files (*.*)\0*.*\0\0");
54*a67afe4dSAndroid Build Coastguard Worker
55*a67afe4dSAndroid Build Coastguard Worker ofn.lStructSize = sizeof (OPENFILENAME);
56*a67afe4dSAndroid Build Coastguard Worker ofn.hwndOwner = hwnd;
57*a67afe4dSAndroid Build Coastguard Worker ofn.hInstance = NULL;
58*a67afe4dSAndroid Build Coastguard Worker ofn.lpstrFilter = szFilter;
59*a67afe4dSAndroid Build Coastguard Worker ofn.lpstrCustomFilter = NULL;
60*a67afe4dSAndroid Build Coastguard Worker ofn.nMaxCustFilter = 0;
61*a67afe4dSAndroid Build Coastguard Worker ofn.nFilterIndex = 0;
62*a67afe4dSAndroid Build Coastguard Worker ofn.lpstrFile = NULL; /* Set in Open and Close functions */
63*a67afe4dSAndroid Build Coastguard Worker ofn.nMaxFile = MAX_PATH;
64*a67afe4dSAndroid Build Coastguard Worker ofn.lpstrFileTitle = NULL; /* Set in Open and Close functions */
65*a67afe4dSAndroid Build Coastguard Worker ofn.nMaxFileTitle = MAX_PATH;
66*a67afe4dSAndroid Build Coastguard Worker ofn.lpstrInitialDir = NULL;
67*a67afe4dSAndroid Build Coastguard Worker ofn.lpstrTitle = NULL;
68*a67afe4dSAndroid Build Coastguard Worker ofn.Flags = 0; /* Set in Open and Close functions */
69*a67afe4dSAndroid Build Coastguard Worker ofn.nFileOffset = 0;
70*a67afe4dSAndroid Build Coastguard Worker ofn.nFileExtension = 0;
71*a67afe4dSAndroid Build Coastguard Worker ofn.lpstrDefExt = TEXT ("png");
72*a67afe4dSAndroid Build Coastguard Worker ofn.lCustData = 0;
73*a67afe4dSAndroid Build Coastguard Worker ofn.lpfnHook = NULL;
74*a67afe4dSAndroid Build Coastguard Worker ofn.lpTemplateName = NULL;
75*a67afe4dSAndroid Build Coastguard Worker }
76*a67afe4dSAndroid Build Coastguard Worker
PngFileOpenDlg(HWND hwnd,PTSTR pstrFileName,PTSTR pstrTitleName)77*a67afe4dSAndroid Build Coastguard Worker BOOL PngFileOpenDlg (HWND hwnd, PTSTR pstrFileName, PTSTR pstrTitleName)
78*a67afe4dSAndroid Build Coastguard Worker {
79*a67afe4dSAndroid Build Coastguard Worker ofn.hwndOwner = hwnd;
80*a67afe4dSAndroid Build Coastguard Worker ofn.lpstrFile = pstrFileName;
81*a67afe4dSAndroid Build Coastguard Worker ofn.lpstrFileTitle = pstrTitleName;
82*a67afe4dSAndroid Build Coastguard Worker ofn.Flags = OFN_HIDEREADONLY;
83*a67afe4dSAndroid Build Coastguard Worker
84*a67afe4dSAndroid Build Coastguard Worker return GetOpenFileName (&ofn);
85*a67afe4dSAndroid Build Coastguard Worker }
86*a67afe4dSAndroid Build Coastguard Worker
PngFileSaveDlg(HWND hwnd,PTSTR pstrFileName,PTSTR pstrTitleName)87*a67afe4dSAndroid Build Coastguard Worker BOOL PngFileSaveDlg (HWND hwnd, PTSTR pstrFileName, PTSTR pstrTitleName)
88*a67afe4dSAndroid Build Coastguard Worker {
89*a67afe4dSAndroid Build Coastguard Worker ofn.hwndOwner = hwnd;
90*a67afe4dSAndroid Build Coastguard Worker ofn.lpstrFile = pstrFileName;
91*a67afe4dSAndroid Build Coastguard Worker ofn.lpstrFileTitle = pstrTitleName;
92*a67afe4dSAndroid Build Coastguard Worker ofn.Flags = OFN_HIDEREADONLY | OFN_OVERWRITEPROMPT;
93*a67afe4dSAndroid Build Coastguard Worker
94*a67afe4dSAndroid Build Coastguard Worker return GetSaveFileName (&ofn);
95*a67afe4dSAndroid Build Coastguard Worker }
96*a67afe4dSAndroid Build Coastguard Worker
97*a67afe4dSAndroid Build Coastguard Worker /* PNG image handler functions */
98*a67afe4dSAndroid Build Coastguard Worker
PngLoadImage(PTSTR pstrFileName,png_byte ** ppbImageData,int * piWidth,int * piHeight,int * piChannels,png_color * pBkgColor)99*a67afe4dSAndroid Build Coastguard Worker BOOL PngLoadImage (PTSTR pstrFileName, png_byte **ppbImageData,
100*a67afe4dSAndroid Build Coastguard Worker int *piWidth, int *piHeight, int *piChannels, png_color *pBkgColor)
101*a67afe4dSAndroid Build Coastguard Worker {
102*a67afe4dSAndroid Build Coastguard Worker static FILE *pfFile;
103*a67afe4dSAndroid Build Coastguard Worker png_byte pbSig[8];
104*a67afe4dSAndroid Build Coastguard Worker int iBitDepth;
105*a67afe4dSAndroid Build Coastguard Worker int iColorType;
106*a67afe4dSAndroid Build Coastguard Worker double dGamma;
107*a67afe4dSAndroid Build Coastguard Worker png_color_16 *pBackground;
108*a67afe4dSAndroid Build Coastguard Worker png_uint_32 ulChannels;
109*a67afe4dSAndroid Build Coastguard Worker png_uint_32 ulRowBytes;
110*a67afe4dSAndroid Build Coastguard Worker png_byte *pbImageData = *ppbImageData;
111*a67afe4dSAndroid Build Coastguard Worker static png_byte **ppbRowPointers = NULL;
112*a67afe4dSAndroid Build Coastguard Worker int i;
113*a67afe4dSAndroid Build Coastguard Worker
114*a67afe4dSAndroid Build Coastguard Worker /* open the PNG input file */
115*a67afe4dSAndroid Build Coastguard Worker
116*a67afe4dSAndroid Build Coastguard Worker if (!pstrFileName)
117*a67afe4dSAndroid Build Coastguard Worker {
118*a67afe4dSAndroid Build Coastguard Worker *ppbImageData = pbImageData = NULL;
119*a67afe4dSAndroid Build Coastguard Worker return FALSE;
120*a67afe4dSAndroid Build Coastguard Worker }
121*a67afe4dSAndroid Build Coastguard Worker
122*a67afe4dSAndroid Build Coastguard Worker if (!(pfFile = fopen(pstrFileName, "rb")))
123*a67afe4dSAndroid Build Coastguard Worker {
124*a67afe4dSAndroid Build Coastguard Worker *ppbImageData = pbImageData = NULL;
125*a67afe4dSAndroid Build Coastguard Worker return FALSE;
126*a67afe4dSAndroid Build Coastguard Worker }
127*a67afe4dSAndroid Build Coastguard Worker
128*a67afe4dSAndroid Build Coastguard Worker /* first check the eight byte PNG signature */
129*a67afe4dSAndroid Build Coastguard Worker
130*a67afe4dSAndroid Build Coastguard Worker fread(pbSig, 1, 8, pfFile);
131*a67afe4dSAndroid Build Coastguard Worker if (png_sig_cmp(pbSig, 0, 8))
132*a67afe4dSAndroid Build Coastguard Worker {
133*a67afe4dSAndroid Build Coastguard Worker *ppbImageData = pbImageData = NULL;
134*a67afe4dSAndroid Build Coastguard Worker return FALSE;
135*a67afe4dSAndroid Build Coastguard Worker }
136*a67afe4dSAndroid Build Coastguard Worker
137*a67afe4dSAndroid Build Coastguard Worker /* create the two png(-info) structures */
138*a67afe4dSAndroid Build Coastguard Worker
139*a67afe4dSAndroid Build Coastguard Worker png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING, NULL,
140*a67afe4dSAndroid Build Coastguard Worker (png_error_ptr)png_cexcept_error, (png_error_ptr)NULL);
141*a67afe4dSAndroid Build Coastguard Worker if (!png_ptr)
142*a67afe4dSAndroid Build Coastguard Worker {
143*a67afe4dSAndroid Build Coastguard Worker *ppbImageData = pbImageData = NULL;
144*a67afe4dSAndroid Build Coastguard Worker return FALSE;
145*a67afe4dSAndroid Build Coastguard Worker }
146*a67afe4dSAndroid Build Coastguard Worker
147*a67afe4dSAndroid Build Coastguard Worker info_ptr = png_create_info_struct(png_ptr);
148*a67afe4dSAndroid Build Coastguard Worker if (!info_ptr)
149*a67afe4dSAndroid Build Coastguard Worker {
150*a67afe4dSAndroid Build Coastguard Worker png_destroy_read_struct(&png_ptr, NULL, NULL);
151*a67afe4dSAndroid Build Coastguard Worker *ppbImageData = pbImageData = NULL;
152*a67afe4dSAndroid Build Coastguard Worker return FALSE;
153*a67afe4dSAndroid Build Coastguard Worker }
154*a67afe4dSAndroid Build Coastguard Worker
155*a67afe4dSAndroid Build Coastguard Worker Try
156*a67afe4dSAndroid Build Coastguard Worker {
157*a67afe4dSAndroid Build Coastguard Worker
158*a67afe4dSAndroid Build Coastguard Worker /* initialize the png structure */
159*a67afe4dSAndroid Build Coastguard Worker
160*a67afe4dSAndroid Build Coastguard Worker #ifdef PNG_STDIO_SUPPORTED
161*a67afe4dSAndroid Build Coastguard Worker png_init_io(png_ptr, pfFile);
162*a67afe4dSAndroid Build Coastguard Worker #else
163*a67afe4dSAndroid Build Coastguard Worker png_set_read_fn(png_ptr, (png_voidp)pfFile, png_read_data);
164*a67afe4dSAndroid Build Coastguard Worker #endif
165*a67afe4dSAndroid Build Coastguard Worker
166*a67afe4dSAndroid Build Coastguard Worker png_set_sig_bytes(png_ptr, 8);
167*a67afe4dSAndroid Build Coastguard Worker
168*a67afe4dSAndroid Build Coastguard Worker /* read all PNG info up to image data */
169*a67afe4dSAndroid Build Coastguard Worker
170*a67afe4dSAndroid Build Coastguard Worker png_read_info(png_ptr, info_ptr);
171*a67afe4dSAndroid Build Coastguard Worker
172*a67afe4dSAndroid Build Coastguard Worker /* get width, height, bit-depth and color-type */
173*a67afe4dSAndroid Build Coastguard Worker
174*a67afe4dSAndroid Build Coastguard Worker png_get_IHDR(png_ptr, info_ptr, piWidth, piHeight, &iBitDepth,
175*a67afe4dSAndroid Build Coastguard Worker &iColorType, NULL, NULL, NULL);
176*a67afe4dSAndroid Build Coastguard Worker
177*a67afe4dSAndroid Build Coastguard Worker /* expand images of all color-type and bit-depth to 3x8-bit RGB */
178*a67afe4dSAndroid Build Coastguard Worker /* let the library process alpha, transparency, background, etc. */
179*a67afe4dSAndroid Build Coastguard Worker
180*a67afe4dSAndroid Build Coastguard Worker #ifdef PNG_READ_16_TO_8_SUPPORTED
181*a67afe4dSAndroid Build Coastguard Worker if (iBitDepth == 16)
182*a67afe4dSAndroid Build Coastguard Worker # ifdef PNG_READ_SCALE_16_TO_8_SUPPORTED
183*a67afe4dSAndroid Build Coastguard Worker png_set_scale_16(png_ptr);
184*a67afe4dSAndroid Build Coastguard Worker # else
185*a67afe4dSAndroid Build Coastguard Worker png_set_strip_16(png_ptr);
186*a67afe4dSAndroid Build Coastguard Worker # endif
187*a67afe4dSAndroid Build Coastguard Worker #endif
188*a67afe4dSAndroid Build Coastguard Worker if (iColorType == PNG_COLOR_TYPE_PALETTE)
189*a67afe4dSAndroid Build Coastguard Worker png_set_expand(png_ptr);
190*a67afe4dSAndroid Build Coastguard Worker if (iBitDepth < 8)
191*a67afe4dSAndroid Build Coastguard Worker png_set_expand(png_ptr);
192*a67afe4dSAndroid Build Coastguard Worker if (png_get_valid(png_ptr, info_ptr, PNG_INFO_tRNS))
193*a67afe4dSAndroid Build Coastguard Worker png_set_expand(png_ptr);
194*a67afe4dSAndroid Build Coastguard Worker if (iColorType == PNG_COLOR_TYPE_GRAY ||
195*a67afe4dSAndroid Build Coastguard Worker iColorType == PNG_COLOR_TYPE_GRAY_ALPHA)
196*a67afe4dSAndroid Build Coastguard Worker png_set_gray_to_rgb(png_ptr);
197*a67afe4dSAndroid Build Coastguard Worker
198*a67afe4dSAndroid Build Coastguard Worker /* set the background color to draw transparent and alpha images over */
199*a67afe4dSAndroid Build Coastguard Worker if (png_get_bKGD(png_ptr, info_ptr, &pBackground))
200*a67afe4dSAndroid Build Coastguard Worker {
201*a67afe4dSAndroid Build Coastguard Worker png_set_background(png_ptr, pBackground, PNG_BACKGROUND_GAMMA_FILE, 1, 1.0);
202*a67afe4dSAndroid Build Coastguard Worker pBkgColor->red = (byte) pBackground->red;
203*a67afe4dSAndroid Build Coastguard Worker pBkgColor->green = (byte) pBackground->green;
204*a67afe4dSAndroid Build Coastguard Worker pBkgColor->blue = (byte) pBackground->blue;
205*a67afe4dSAndroid Build Coastguard Worker }
206*a67afe4dSAndroid Build Coastguard Worker else
207*a67afe4dSAndroid Build Coastguard Worker {
208*a67afe4dSAndroid Build Coastguard Worker pBkgColor = NULL;
209*a67afe4dSAndroid Build Coastguard Worker }
210*a67afe4dSAndroid Build Coastguard Worker
211*a67afe4dSAndroid Build Coastguard Worker /* if required set gamma conversion */
212*a67afe4dSAndroid Build Coastguard Worker if (png_get_gAMA(png_ptr, info_ptr, &dGamma))
213*a67afe4dSAndroid Build Coastguard Worker png_set_gamma(png_ptr, (double) 2.2, dGamma);
214*a67afe4dSAndroid Build Coastguard Worker
215*a67afe4dSAndroid Build Coastguard Worker /* after the transformations are registered, update info_ptr data */
216*a67afe4dSAndroid Build Coastguard Worker
217*a67afe4dSAndroid Build Coastguard Worker png_read_update_info(png_ptr, info_ptr);
218*a67afe4dSAndroid Build Coastguard Worker
219*a67afe4dSAndroid Build Coastguard Worker /* get again width, height and the new bit-depth and color-type */
220*a67afe4dSAndroid Build Coastguard Worker
221*a67afe4dSAndroid Build Coastguard Worker png_get_IHDR(png_ptr, info_ptr, piWidth, piHeight, &iBitDepth,
222*a67afe4dSAndroid Build Coastguard Worker &iColorType, NULL, NULL, NULL);
223*a67afe4dSAndroid Build Coastguard Worker
224*a67afe4dSAndroid Build Coastguard Worker
225*a67afe4dSAndroid Build Coastguard Worker /* row_bytes is the width x number of channels */
226*a67afe4dSAndroid Build Coastguard Worker
227*a67afe4dSAndroid Build Coastguard Worker ulRowBytes = png_get_rowbytes(png_ptr, info_ptr);
228*a67afe4dSAndroid Build Coastguard Worker ulChannels = png_get_channels(png_ptr, info_ptr);
229*a67afe4dSAndroid Build Coastguard Worker
230*a67afe4dSAndroid Build Coastguard Worker *piChannels = ulChannels;
231*a67afe4dSAndroid Build Coastguard Worker
232*a67afe4dSAndroid Build Coastguard Worker /* now we can allocate memory to store the image */
233*a67afe4dSAndroid Build Coastguard Worker
234*a67afe4dSAndroid Build Coastguard Worker if (pbImageData)
235*a67afe4dSAndroid Build Coastguard Worker {
236*a67afe4dSAndroid Build Coastguard Worker free (pbImageData);
237*a67afe4dSAndroid Build Coastguard Worker pbImageData = NULL;
238*a67afe4dSAndroid Build Coastguard Worker }
239*a67afe4dSAndroid Build Coastguard Worker if ((*piHeight) > ((size_t)(-1))/ulRowBytes) {
240*a67afe4dSAndroid Build Coastguard Worker {
241*a67afe4dSAndroid Build Coastguard Worker png_error(png_ptr, "Visual PNG: image is too big");
242*a67afe4dSAndroid Build Coastguard Worker }
243*a67afe4dSAndroid Build Coastguard Worker if ((pbImageData = (png_byte *) malloc(ulRowBytes * (*piHeight)
244*a67afe4dSAndroid Build Coastguard Worker * sizeof(png_byte))) == NULL)
245*a67afe4dSAndroid Build Coastguard Worker {
246*a67afe4dSAndroid Build Coastguard Worker png_error(png_ptr, "Visual PNG: out of memory");
247*a67afe4dSAndroid Build Coastguard Worker }
248*a67afe4dSAndroid Build Coastguard Worker *ppbImageData = pbImageData;
249*a67afe4dSAndroid Build Coastguard Worker
250*a67afe4dSAndroid Build Coastguard Worker /* and allocate memory for an array of row-pointers */
251*a67afe4dSAndroid Build Coastguard Worker
252*a67afe4dSAndroid Build Coastguard Worker if ((ppbRowPointers = (png_bytepp) malloc((*piHeight)
253*a67afe4dSAndroid Build Coastguard Worker * sizeof(png_bytep))) == NULL)
254*a67afe4dSAndroid Build Coastguard Worker {
255*a67afe4dSAndroid Build Coastguard Worker png_error(png_ptr, "Visual PNG: out of memory");
256*a67afe4dSAndroid Build Coastguard Worker }
257*a67afe4dSAndroid Build Coastguard Worker
258*a67afe4dSAndroid Build Coastguard Worker /* set the individual row-pointers to point at the correct offsets */
259*a67afe4dSAndroid Build Coastguard Worker
260*a67afe4dSAndroid Build Coastguard Worker for (i = 0; i < (*piHeight); i++)
261*a67afe4dSAndroid Build Coastguard Worker ppbRowPointers[i] = pbImageData + i * ulRowBytes;
262*a67afe4dSAndroid Build Coastguard Worker
263*a67afe4dSAndroid Build Coastguard Worker /* now we can go ahead and just read the whole image */
264*a67afe4dSAndroid Build Coastguard Worker
265*a67afe4dSAndroid Build Coastguard Worker png_read_image(png_ptr, ppbRowPointers);
266*a67afe4dSAndroid Build Coastguard Worker
267*a67afe4dSAndroid Build Coastguard Worker /* read the additional chunks in the PNG file (not really needed) */
268*a67afe4dSAndroid Build Coastguard Worker
269*a67afe4dSAndroid Build Coastguard Worker png_read_end(png_ptr, NULL);
270*a67afe4dSAndroid Build Coastguard Worker
271*a67afe4dSAndroid Build Coastguard Worker /* and we're done */
272*a67afe4dSAndroid Build Coastguard Worker
273*a67afe4dSAndroid Build Coastguard Worker free (ppbRowPointers);
274*a67afe4dSAndroid Build Coastguard Worker ppbRowPointers = NULL;
275*a67afe4dSAndroid Build Coastguard Worker
276*a67afe4dSAndroid Build Coastguard Worker /* yepp, done */
277*a67afe4dSAndroid Build Coastguard Worker }
278*a67afe4dSAndroid Build Coastguard Worker
279*a67afe4dSAndroid Build Coastguard Worker Catch (msg)
280*a67afe4dSAndroid Build Coastguard Worker {
281*a67afe4dSAndroid Build Coastguard Worker png_destroy_read_struct(&png_ptr, &info_ptr, NULL);
282*a67afe4dSAndroid Build Coastguard Worker
283*a67afe4dSAndroid Build Coastguard Worker *ppbImageData = pbImageData = NULL;
284*a67afe4dSAndroid Build Coastguard Worker
285*a67afe4dSAndroid Build Coastguard Worker if(ppbRowPointers)
286*a67afe4dSAndroid Build Coastguard Worker free (ppbRowPointers);
287*a67afe4dSAndroid Build Coastguard Worker
288*a67afe4dSAndroid Build Coastguard Worker fclose(pfFile);
289*a67afe4dSAndroid Build Coastguard Worker
290*a67afe4dSAndroid Build Coastguard Worker return FALSE;
291*a67afe4dSAndroid Build Coastguard Worker }
292*a67afe4dSAndroid Build Coastguard Worker
293*a67afe4dSAndroid Build Coastguard Worker fclose (pfFile);
294*a67afe4dSAndroid Build Coastguard Worker
295*a67afe4dSAndroid Build Coastguard Worker return TRUE;
296*a67afe4dSAndroid Build Coastguard Worker }
297*a67afe4dSAndroid Build Coastguard Worker
298*a67afe4dSAndroid Build Coastguard Worker
299*a67afe4dSAndroid Build Coastguard Worker BOOL PngSaveImage (PTSTR pstrFileName, png_byte *pDiData,
300*a67afe4dSAndroid Build Coastguard Worker int iWidth, int iHeight, png_color bkgColor)
301*a67afe4dSAndroid Build Coastguard Worker {
302*a67afe4dSAndroid Build Coastguard Worker const int ciBitDepth = 8;
303*a67afe4dSAndroid Build Coastguard Worker const int ciChannels = 3;
304*a67afe4dSAndroid Build Coastguard Worker
305*a67afe4dSAndroid Build Coastguard Worker static FILE *pfFile;
306*a67afe4dSAndroid Build Coastguard Worker png_uint_32 ulRowBytes;
307*a67afe4dSAndroid Build Coastguard Worker static png_byte **ppbRowPointers = NULL;
308*a67afe4dSAndroid Build Coastguard Worker int i;
309*a67afe4dSAndroid Build Coastguard Worker
310*a67afe4dSAndroid Build Coastguard Worker /* open the PNG output file */
311*a67afe4dSAndroid Build Coastguard Worker
312*a67afe4dSAndroid Build Coastguard Worker if (!pstrFileName)
313*a67afe4dSAndroid Build Coastguard Worker return FALSE;
314*a67afe4dSAndroid Build Coastguard Worker
315*a67afe4dSAndroid Build Coastguard Worker if (!(pfFile = fopen(pstrFileName, "wb")))
316*a67afe4dSAndroid Build Coastguard Worker return FALSE;
317*a67afe4dSAndroid Build Coastguard Worker
318*a67afe4dSAndroid Build Coastguard Worker /* prepare the standard PNG structures */
319*a67afe4dSAndroid Build Coastguard Worker
320*a67afe4dSAndroid Build Coastguard Worker png_ptr = png_create_write_struct(PNG_LIBPNG_VER_STRING, NULL,
321*a67afe4dSAndroid Build Coastguard Worker (png_error_ptr)png_cexcept_error, (png_error_ptr)NULL);
322*a67afe4dSAndroid Build Coastguard Worker if (!png_ptr)
323*a67afe4dSAndroid Build Coastguard Worker {
324*a67afe4dSAndroid Build Coastguard Worker fclose(pfFile);
325*a67afe4dSAndroid Build Coastguard Worker return FALSE;
326*a67afe4dSAndroid Build Coastguard Worker }
327*a67afe4dSAndroid Build Coastguard Worker
328*a67afe4dSAndroid Build Coastguard Worker info_ptr = png_create_info_struct(png_ptr);
329*a67afe4dSAndroid Build Coastguard Worker if (!info_ptr) {
330*a67afe4dSAndroid Build Coastguard Worker fclose(pfFile);
331*a67afe4dSAndroid Build Coastguard Worker png_destroy_write_struct(&png_ptr, (png_infopp) NULL);
332*a67afe4dSAndroid Build Coastguard Worker return FALSE;
333*a67afe4dSAndroid Build Coastguard Worker }
334*a67afe4dSAndroid Build Coastguard Worker
335*a67afe4dSAndroid Build Coastguard Worker Try
336*a67afe4dSAndroid Build Coastguard Worker {
337*a67afe4dSAndroid Build Coastguard Worker /* initialize the png structure */
338*a67afe4dSAndroid Build Coastguard Worker
339*a67afe4dSAndroid Build Coastguard Worker #ifdef PNG_STDIO_SUPPORTED
340*a67afe4dSAndroid Build Coastguard Worker png_init_io(png_ptr, pfFile);
341*a67afe4dSAndroid Build Coastguard Worker #else
342*a67afe4dSAndroid Build Coastguard Worker png_set_write_fn(png_ptr, (png_voidp)pfFile, png_write_data, png_flush);
343*a67afe4dSAndroid Build Coastguard Worker #endif
344*a67afe4dSAndroid Build Coastguard Worker
345*a67afe4dSAndroid Build Coastguard Worker /* we're going to write a very simple 3x8-bit RGB image */
346*a67afe4dSAndroid Build Coastguard Worker
347*a67afe4dSAndroid Build Coastguard Worker png_set_IHDR(png_ptr, info_ptr, iWidth, iHeight, ciBitDepth,
348*a67afe4dSAndroid Build Coastguard Worker PNG_COLOR_TYPE_RGB, PNG_INTERLACE_NONE, PNG_COMPRESSION_TYPE_BASE,
349*a67afe4dSAndroid Build Coastguard Worker PNG_FILTER_TYPE_BASE);
350*a67afe4dSAndroid Build Coastguard Worker
351*a67afe4dSAndroid Build Coastguard Worker /* write the file header information */
352*a67afe4dSAndroid Build Coastguard Worker
353*a67afe4dSAndroid Build Coastguard Worker png_write_info(png_ptr, info_ptr);
354*a67afe4dSAndroid Build Coastguard Worker
355*a67afe4dSAndroid Build Coastguard Worker /* swap the BGR pixels in the DiData structure to RGB */
356*a67afe4dSAndroid Build Coastguard Worker
357*a67afe4dSAndroid Build Coastguard Worker png_set_bgr(png_ptr);
358*a67afe4dSAndroid Build Coastguard Worker
359*a67afe4dSAndroid Build Coastguard Worker /* row_bytes is the width x number of channels */
360*a67afe4dSAndroid Build Coastguard Worker
361*a67afe4dSAndroid Build Coastguard Worker ulRowBytes = iWidth * ciChannels;
362*a67afe4dSAndroid Build Coastguard Worker
363*a67afe4dSAndroid Build Coastguard Worker /* we can allocate memory for an array of row-pointers */
364*a67afe4dSAndroid Build Coastguard Worker
365*a67afe4dSAndroid Build Coastguard Worker if ((ppbRowPointers = (png_bytepp) malloc(iHeight * sizeof(png_bytep))) == NULL)
366*a67afe4dSAndroid Build Coastguard Worker Throw "Visualpng: Out of memory";
367*a67afe4dSAndroid Build Coastguard Worker
368*a67afe4dSAndroid Build Coastguard Worker /* set the individual row-pointers to point at the correct offsets */
369*a67afe4dSAndroid Build Coastguard Worker
370*a67afe4dSAndroid Build Coastguard Worker for (i = 0; i < iHeight; i++)
371*a67afe4dSAndroid Build Coastguard Worker ppbRowPointers[i] = pDiData + i * (((ulRowBytes + 3) >> 2) << 2);
372*a67afe4dSAndroid Build Coastguard Worker
373*a67afe4dSAndroid Build Coastguard Worker /* write out the entire image data in one call */
374*a67afe4dSAndroid Build Coastguard Worker
375*a67afe4dSAndroid Build Coastguard Worker png_write_image (png_ptr, ppbRowPointers);
376*a67afe4dSAndroid Build Coastguard Worker
377*a67afe4dSAndroid Build Coastguard Worker /* write the additional chunks to the PNG file (not really needed) */
378*a67afe4dSAndroid Build Coastguard Worker
379*a67afe4dSAndroid Build Coastguard Worker png_write_end(png_ptr, info_ptr);
380*a67afe4dSAndroid Build Coastguard Worker
381*a67afe4dSAndroid Build Coastguard Worker /* and we're done */
382*a67afe4dSAndroid Build Coastguard Worker
383*a67afe4dSAndroid Build Coastguard Worker free (ppbRowPointers);
384*a67afe4dSAndroid Build Coastguard Worker ppbRowPointers = NULL;
385*a67afe4dSAndroid Build Coastguard Worker
386*a67afe4dSAndroid Build Coastguard Worker /* clean up after the write, and free any memory allocated */
387*a67afe4dSAndroid Build Coastguard Worker
388*a67afe4dSAndroid Build Coastguard Worker png_destroy_write_struct(&png_ptr, (png_infopp) NULL);
389*a67afe4dSAndroid Build Coastguard Worker
390*a67afe4dSAndroid Build Coastguard Worker /* yepp, done */
391*a67afe4dSAndroid Build Coastguard Worker }
392*a67afe4dSAndroid Build Coastguard Worker
393*a67afe4dSAndroid Build Coastguard Worker Catch (msg)
394*a67afe4dSAndroid Build Coastguard Worker {
395*a67afe4dSAndroid Build Coastguard Worker png_destroy_write_struct(&png_ptr, (png_infopp) NULL);
396*a67afe4dSAndroid Build Coastguard Worker
397*a67afe4dSAndroid Build Coastguard Worker if(ppbRowPointers)
398*a67afe4dSAndroid Build Coastguard Worker free (ppbRowPointers);
399*a67afe4dSAndroid Build Coastguard Worker
400*a67afe4dSAndroid Build Coastguard Worker fclose(pfFile);
401*a67afe4dSAndroid Build Coastguard Worker
402*a67afe4dSAndroid Build Coastguard Worker return FALSE;
403*a67afe4dSAndroid Build Coastguard Worker }
404*a67afe4dSAndroid Build Coastguard Worker
405*a67afe4dSAndroid Build Coastguard Worker fclose (pfFile);
406*a67afe4dSAndroid Build Coastguard Worker
407*a67afe4dSAndroid Build Coastguard Worker return TRUE;
408*a67afe4dSAndroid Build Coastguard Worker }
409*a67afe4dSAndroid Build Coastguard Worker
410*a67afe4dSAndroid Build Coastguard Worker #ifndef PNG_STDIO_SUPPORTED
411*a67afe4dSAndroid Build Coastguard Worker
412*a67afe4dSAndroid Build Coastguard Worker static void
413*a67afe4dSAndroid Build Coastguard Worker png_read_data(png_structp png_ptr, png_bytep data, size_t length)
414*a67afe4dSAndroid Build Coastguard Worker {
415*a67afe4dSAndroid Build Coastguard Worker size_t check;
416*a67afe4dSAndroid Build Coastguard Worker
417*a67afe4dSAndroid Build Coastguard Worker /* fread() returns 0 on error, so it is OK to store this in a size_t
418*a67afe4dSAndroid Build Coastguard Worker * instead of an int, which is what fread() actually returns.
419*a67afe4dSAndroid Build Coastguard Worker */
420*a67afe4dSAndroid Build Coastguard Worker check = fread(data, 1, length, (FILE *)png_ptr->io_ptr);
421*a67afe4dSAndroid Build Coastguard Worker
422*a67afe4dSAndroid Build Coastguard Worker if (check != length)
423*a67afe4dSAndroid Build Coastguard Worker {
424*a67afe4dSAndroid Build Coastguard Worker png_error(png_ptr, "Read Error");
425*a67afe4dSAndroid Build Coastguard Worker }
426*a67afe4dSAndroid Build Coastguard Worker }
427*a67afe4dSAndroid Build Coastguard Worker
428*a67afe4dSAndroid Build Coastguard Worker static void
429*a67afe4dSAndroid Build Coastguard Worker png_write_data(png_structp png_ptr, png_bytep data, size_t length)
430*a67afe4dSAndroid Build Coastguard Worker {
431*a67afe4dSAndroid Build Coastguard Worker png_uint_32 check;
432*a67afe4dSAndroid Build Coastguard Worker
433*a67afe4dSAndroid Build Coastguard Worker check = fwrite(data, 1, length, (FILE *)(png_ptr->io_ptr));
434*a67afe4dSAndroid Build Coastguard Worker if (check != length)
435*a67afe4dSAndroid Build Coastguard Worker {
436*a67afe4dSAndroid Build Coastguard Worker png_error(png_ptr, "Write Error");
437*a67afe4dSAndroid Build Coastguard Worker }
438*a67afe4dSAndroid Build Coastguard Worker }
439*a67afe4dSAndroid Build Coastguard Worker
440*a67afe4dSAndroid Build Coastguard Worker static void
441*a67afe4dSAndroid Build Coastguard Worker png_flush(png_structp png_ptr)
442*a67afe4dSAndroid Build Coastguard Worker {
443*a67afe4dSAndroid Build Coastguard Worker FILE *io_ptr;
444*a67afe4dSAndroid Build Coastguard Worker io_ptr = (FILE *)CVT_PTR((png_ptr->io_ptr));
445*a67afe4dSAndroid Build Coastguard Worker if (io_ptr != NULL)
446*a67afe4dSAndroid Build Coastguard Worker fflush(io_ptr);
447*a67afe4dSAndroid Build Coastguard Worker }
448*a67afe4dSAndroid Build Coastguard Worker
449*a67afe4dSAndroid Build Coastguard Worker #endif
450*a67afe4dSAndroid Build Coastguard Worker
451*a67afe4dSAndroid Build Coastguard Worker /*-----------------
452*a67afe4dSAndroid Build Coastguard Worker * end of source
453*a67afe4dSAndroid Build Coastguard Worker *-----------------
454*a67afe4dSAndroid Build Coastguard Worker */
455