]> git.jsancho.org Git - lugaru.git/blob - Dependencies/libpng/contrib/visupng/PngFile.c
CMake: Purge all the bundled dependencies
[lugaru.git] / Dependencies / libpng / contrib / visupng / PngFile.c
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
34 png_cexcept_error(png_structp png_ptr, png_const_charp msg)
35 {
36    if(png_ptr)
37      ;
38 #ifdef PNG_CONSOLE_IO_SUPPORTED
39    fprintf(stderr, "libpng error: %s\n", msg);
40 #endif
41    {
42       Throw msg;
43    }
44 }
45
46 // Windows open-file functions
47
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
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
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
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 #ifdef PNG_STDIO_SUPPORTED
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
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 #ifdef PNG_STDIO_SUPPORTED
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 #ifndef PNG_STDIO_SUPPORTED
399
400 static void
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
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
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 //-----------------