1 /*-------------------------------------
2 * PNGFILE.C -- Image File Functions
3 *-------------------------------------
5 * Copyright 2000, Willem van Schaik.
7 * This code is released under the libpng license.
8 * For conditions of distribution and use, see the disclaimer
22 define_exception_type(const char *);
23 extern struct exception_context the_exception_context
[1];
24 struct exception_context the_exception_context
[1];
27 static OPENFILENAME ofn
;
29 static png_structp png_ptr
= NULL
;
30 static png_infop info_ptr
= NULL
;
33 /* cexcept interface */
36 png_cexcept_error(png_structp png_ptr
, png_const_charp msg
)
40 #ifdef PNG_CONSOLE_IO_SUPPORTED
41 fprintf(stderr
, "libpng error: %s\n", msg
);
48 /* Windows open-file functions */
50 void PngFileInitialize (HWND hwnd
)
52 static TCHAR szFilter
[] = TEXT ("PNG Files (*.PNG)\0*.png\0")
53 TEXT ("All Files (*.*)\0*.*\0\0");
55 ofn
.lStructSize
= sizeof (OPENFILENAME
);
58 ofn
.lpstrFilter
= szFilter
;
59 ofn
.lpstrCustomFilter
= NULL
;
60 ofn
.nMaxCustFilter
= 0;
62 ofn
.lpstrFile
= NULL
; /* Set in Open and Close functions */
63 ofn
.nMaxFile
= MAX_PATH
;
64 ofn
.lpstrFileTitle
= NULL
; /* Set in Open and Close functions */
65 ofn
.nMaxFileTitle
= MAX_PATH
;
66 ofn
.lpstrInitialDir
= NULL
;
67 ofn
.lpstrTitle
= NULL
;
68 ofn
.Flags
= 0; /* Set in Open and Close functions */
70 ofn
.nFileExtension
= 0;
71 ofn
.lpstrDefExt
= TEXT ("png");
74 ofn
.lpTemplateName
= NULL
;
77 BOOL
PngFileOpenDlg (HWND hwnd
, PTSTR pstrFileName
, PTSTR pstrTitleName
)
80 ofn
.lpstrFile
= pstrFileName
;
81 ofn
.lpstrFileTitle
= pstrTitleName
;
82 ofn
.Flags
= OFN_HIDEREADONLY
;
84 return GetOpenFileName (&ofn
);
87 BOOL
PngFileSaveDlg (HWND hwnd
, PTSTR pstrFileName
, PTSTR pstrTitleName
)
90 ofn
.lpstrFile
= pstrFileName
;
91 ofn
.lpstrFileTitle
= pstrTitleName
;
92 ofn
.Flags
= OFN_HIDEREADONLY
| OFN_OVERWRITEPROMPT
;
94 return GetSaveFileName (&ofn
);
97 /* PNG image handler functions */
99 BOOL
PngLoadImage (PTSTR pstrFileName
, png_byte
**ppbImageData
,
100 int *piWidth
, int *piHeight
, int *piChannels
, png_color
*pBkgColor
)
107 png_color_16
*pBackground
;
108 png_uint_32 ulChannels
;
109 png_uint_32 ulRowBytes
;
110 png_byte
*pbImageData
= *ppbImageData
;
111 static png_byte
**ppbRowPointers
= NULL
;
114 /* open the PNG input file */
118 *ppbImageData
= pbImageData
= NULL
;
122 if (!(pfFile
= fopen(pstrFileName
, "rb")))
124 *ppbImageData
= pbImageData
= NULL
;
128 /* first check the eight byte PNG signature */
130 fread(pbSig
, 1, 8, pfFile
);
131 if (png_sig_cmp(pbSig
, 0, 8))
133 *ppbImageData
= pbImageData
= NULL
;
137 /* create the two png(-info) structures */
139 png_ptr
= png_create_read_struct(PNG_LIBPNG_VER_STRING
, NULL
,
140 (png_error_ptr
)png_cexcept_error
, (png_error_ptr
)NULL
);
143 *ppbImageData
= pbImageData
= NULL
;
147 info_ptr
= png_create_info_struct(png_ptr
);
150 png_destroy_read_struct(&png_ptr
, NULL
, NULL
);
151 *ppbImageData
= pbImageData
= NULL
;
158 /* initialize the png structure */
160 #ifdef PNG_STDIO_SUPPORTED
161 png_init_io(png_ptr
, pfFile
);
163 png_set_read_fn(png_ptr
, (png_voidp
)pfFile
, png_read_data
);
166 png_set_sig_bytes(png_ptr
, 8);
168 /* read all PNG info up to image data */
170 png_read_info(png_ptr
, info_ptr
);
172 /* get width, height, bit-depth and color-type */
174 png_get_IHDR(png_ptr
, info_ptr
, piWidth
, piHeight
, &iBitDepth
,
175 &iColorType
, NULL
, NULL
, NULL
);
177 /* expand images of all color-type and bit-depth to 3x8-bit RGB */
178 /* let the library process alpha, transparency, background, etc. */
180 #ifdef PNG_READ_16_TO_8_SUPPORTED
182 # ifdef PNG_READ_SCALE_16_TO_8_SUPPORTED
183 png_set_scale_16(png_ptr
);
185 png_set_strip_16(png_ptr
);
188 if (iColorType
== PNG_COLOR_TYPE_PALETTE
)
189 png_set_expand(png_ptr
);
191 png_set_expand(png_ptr
);
192 if (png_get_valid(png_ptr
, info_ptr
, PNG_INFO_tRNS
))
193 png_set_expand(png_ptr
);
194 if (iColorType
== PNG_COLOR_TYPE_GRAY
||
195 iColorType
== PNG_COLOR_TYPE_GRAY_ALPHA
)
196 png_set_gray_to_rgb(png_ptr
);
198 /* set the background color to draw transparent and alpha images over */
199 if (png_get_bKGD(png_ptr
, info_ptr
, &pBackground
))
201 png_set_background(png_ptr
, pBackground
, PNG_BACKGROUND_GAMMA_FILE
, 1, 1.0);
202 pBkgColor
->red
= (byte
) pBackground
->red
;
203 pBkgColor
->green
= (byte
) pBackground
->green
;
204 pBkgColor
->blue
= (byte
) pBackground
->blue
;
211 /* if required set gamma conversion */
212 if (png_get_gAMA(png_ptr
, info_ptr
, &dGamma
))
213 png_set_gamma(png_ptr
, (double) 2.2, dGamma
);
215 /* after the transformations are registered, update info_ptr data */
217 png_read_update_info(png_ptr
, info_ptr
);
219 /* get again width, height and the new bit-depth and color-type */
221 png_get_IHDR(png_ptr
, info_ptr
, piWidth
, piHeight
, &iBitDepth
,
222 &iColorType
, NULL
, NULL
, NULL
);
225 /* row_bytes is the width x number of channels */
227 ulRowBytes
= png_get_rowbytes(png_ptr
, info_ptr
);
228 ulChannels
= png_get_channels(png_ptr
, info_ptr
);
230 *piChannels
= ulChannels
;
232 /* now we can allocate memory to store the image */
239 if ((pbImageData
= (png_byte
*) malloc(ulRowBytes
* (*piHeight
)
240 * sizeof(png_byte
))) == NULL
)
242 png_error(png_ptr
, "Visual PNG: out of memory");
244 *ppbImageData
= pbImageData
;
246 /* and allocate memory for an array of row-pointers */
248 if ((ppbRowPointers
= (png_bytepp
) malloc((*piHeight
)
249 * sizeof(png_bytep
))) == NULL
)
251 png_error(png_ptr
, "Visual PNG: out of memory");
254 /* set the individual row-pointers to point at the correct offsets */
256 for (i
= 0; i
< (*piHeight
); i
++)
257 ppbRowPointers
[i
] = pbImageData
+ i
* ulRowBytes
;
259 /* now we can go ahead and just read the whole image */
261 png_read_image(png_ptr
, ppbRowPointers
);
263 /* read the additional chunks in the PNG file (not really needed) */
265 png_read_end(png_ptr
, NULL
);
269 free (ppbRowPointers
);
270 ppbRowPointers
= NULL
;
277 png_destroy_read_struct(&png_ptr
, &info_ptr
, NULL
);
279 *ppbImageData
= pbImageData
= NULL
;
282 free (ppbRowPointers
);
295 BOOL
PngSaveImage (PTSTR pstrFileName
, png_byte
*pDiData
,
296 int iWidth
, int iHeight
, png_color bkgColor
)
298 const int ciBitDepth
= 8;
299 const int ciChannels
= 3;
302 png_uint_32 ulRowBytes
;
303 static png_byte
**ppbRowPointers
= NULL
;
306 /* open the PNG output file */
311 if (!(pfFile
= fopen(pstrFileName
, "wb")))
314 /* prepare the standard PNG structures */
316 png_ptr
= png_create_write_struct(PNG_LIBPNG_VER_STRING
, NULL
,
317 (png_error_ptr
)png_cexcept_error
, (png_error_ptr
)NULL
);
324 info_ptr
= png_create_info_struct(png_ptr
);
327 png_destroy_write_struct(&png_ptr
, (png_infopp
) NULL
);
333 /* initialize the png structure */
335 #ifdef PNG_STDIO_SUPPORTED
336 png_init_io(png_ptr
, pfFile
);
338 png_set_write_fn(png_ptr
, (png_voidp
)pfFile
, png_write_data
, png_flush
);
341 /* we're going to write a very simple 3x8-bit RGB image */
343 png_set_IHDR(png_ptr
, info_ptr
, iWidth
, iHeight
, ciBitDepth
,
344 PNG_COLOR_TYPE_RGB
, PNG_INTERLACE_NONE
, PNG_COMPRESSION_TYPE_BASE
,
345 PNG_FILTER_TYPE_BASE
);
347 /* write the file header information */
349 png_write_info(png_ptr
, info_ptr
);
351 /* swap the BGR pixels in the DiData structure to RGB */
353 png_set_bgr(png_ptr
);
355 /* row_bytes is the width x number of channels */
357 ulRowBytes
= iWidth
* ciChannels
;
359 /* we can allocate memory for an array of row-pointers */
361 if ((ppbRowPointers
= (png_bytepp
) malloc(iHeight
* sizeof(png_bytep
))) == NULL
)
362 Throw
"Visualpng: Out of memory";
364 /* set the individual row-pointers to point at the correct offsets */
366 for (i
= 0; i
< iHeight
; i
++)
367 ppbRowPointers
[i
] = pDiData
+ i
* (((ulRowBytes
+ 3) >> 2) << 2);
369 /* write out the entire image data in one call */
371 png_write_image (png_ptr
, ppbRowPointers
);
373 /* write the additional chunks to the PNG file (not really needed) */
375 png_write_end(png_ptr
, info_ptr
);
379 free (ppbRowPointers
);
380 ppbRowPointers
= NULL
;
382 /* clean up after the write, and free any memory allocated */
384 png_destroy_write_struct(&png_ptr
, (png_infopp
) NULL
);
391 png_destroy_write_struct(&png_ptr
, (png_infopp
) NULL
);
394 free (ppbRowPointers
);
406 #ifndef PNG_STDIO_SUPPORTED
409 png_read_data(png_structp png_ptr
, png_bytep data
, png_size_t length
)
413 /* fread() returns 0 on error, so it is OK to store this in a png_size_t
414 * instead of an int, which is what fread() actually returns.
416 check
= (png_size_t
)fread(data
, (png_size_t
)1, length
,
417 (FILE *)png_ptr
->io_ptr
);
421 png_error(png_ptr
, "Read Error");
426 png_write_data(png_structp png_ptr
, png_bytep data
, png_size_t length
)
430 check
= fwrite(data
, 1, length
, (FILE *)(png_ptr
->io_ptr
));
433 png_error(png_ptr
, "Write Error");
438 png_flush(png_structp png_ptr
)
441 io_ptr
= (FILE *)CVT_PTR((png_ptr
->io_ptr
));