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