xref: /aosp_15_r20/external/libpng/contrib/visupng/PngFile.c (revision a67afe4df73cf47866eedc69947994b8ff839aba)
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