1PNGDIB - a mini DIB-PNG conversion library for Win32
2By Jason Summers <jason1@pobox.com>
3Version 2.2.0, Apr. 2002
4Web site: http://pobox.com/~jason1/pngdib/
5Note: version 2.2.2 is out which fixes a memory freeing bug
6(presently AbiWord defaults to libpng 1.2.3)
7
8
9This software is distributed in the hope that it will be useful, but
10WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
11or FITNESS FOR A PARTICULAR PURPOSE.
12
13Permission is hereby granted to use, copy, modify, and distribute this
14source code for any purpose, without fee.
15
16
17The pngdib.c file contains two functions that convert between PNG images
18and Windows Device Independent Bitmaps (DIBs). PNGDIB is designed to be
19quick and easy to use, but it does not attempt to support every feature
20that one might want. If you wish use the PNG format to its full
21capabilities, you'll need to use libpng directly, or program our own
22extensions to PNGDIB.
23
24REQUIREMENTS
25
26* zlib <http://www.info-zip.org/pub/infozip/zlib/>
27Tested with v1.1.4; other versions probably also work.
28
29* libpng <http://www.libpng.org/pub/png/>
30Version 1.2.2beta5 or higher recommended. Most versions from about 1.0.5
31on will probably work, but they do not always handle gamma correction
32correctly when combined with alpha transparency.
33
34------
35
36INTRODUCTION
37
38The PNG-to-DIB function creates version 3.0 DIBs/BMPs. The image will be
39uncompressed, with either 1, 4, 8, or 24 bits-per-pixel.
40
41(Note: A BMP image file is basically just a DIB copied directly from
42memory, with a 14-byte file header tacked onto the front. The terms DIB
43and BMP may sometimes be used almost interchangeably.)
44
45
46The DIB-to-PNG function supports approximately version 3.0 DIBs, and also
47OS/2-style DIBs. It supports bit depths of 1, 4, 8, 16, 24, and 32
48bits-per-pixel. It supports 4 bpp and 8 bpp compressed DIBs (it uses
49Windows GDI functions to uncompress them).
50
51If you find a valid BMP file that the bmp2png sample program can't read,
52please let me know.
53
54
55Two sample programs, png2bmp.c and bmp2png.c, are included which demonstrate
56the use of library functions. They can be compiled as "console mode" Win32
57applications.
58
59A third sample, "smview", is a bare-bones Windows program that uses pngdib
60to read and display PNG files. This is intended to demonstrate that it is
61easy to add PNG support to an application that uses DIBs. It is not
62intended to be a usable image viewer.
63
64--------
65
66BRIEF INSTRUCTIONS FOR THE SAMPLE PNG VIEWER (smview)
67
68[This program is just a demo. For a more usable viewer, visit
69http://pobox.com/~jason1/purpleview/.]
70
71Load a PNG image by selecting File|Open from the menu, or by drag-and-drop
72from Windows Explorer.
73
74Gamma Correction - Toggles gamma correction. If you turn this off, some
75images, or parts of images, will look too light or too dark.
76
77Save As PNG - Saves the visible (unstretched) image to a file.
78IMPORTANT--- This saves the image as it is currently being displayed. The
79saved image will not have any transparency, and the background color and
80gamma correction will be applied to the image, not saved as meta-data.
81This means that you can lose information by loading and then saving a PNG
82image.
83
84Background colors - You can define a background color that will be used in
85certain situations. The following logic is used to select a background
86color: If "Use Image's Background Color" is checked, and the current PNG
87image file contains a suggested background color, that suggested
88background color will be used. Otherwise, if "Use Custom Background Color"
89is checked, your custom background color will be used (by default this is
90a very light gray color). Otherwise, no background color will be used at
91all, and transparency information in the image will be completely ignored.
92Some images will not look very good in this situation. (A pure white
93background will be used for the window, but will not be applied to the
94image.)
95
96Any time you make a change to the gamma or background color settings, the
97PNG file will be reloaded from disk. That's not the ideal thing to do, but
98this _is_ just a demo program...
99
100--------
101
102Basic instructions for using the library in your own programs (the
103read_png_to_dib and write_dib_to_png functions) follow the change log
104and TO DO list.
105
106CHANGES in PNGDIB v2.2.0 (vs. 2.1.1)
107------------------------------------
108
109* Option to use HeapAlloc instead of GlobalAlloc (when reading PNGs).
110
111
112CHANGES in PNGDIB v2.1.1 (vs. 2.1.0)
113------------------------------------
114
115* More accurate conversion of 16-bpp DIBs into PNGs.
116
117* Some minor changes (mostly typecasts) to the pngdib.c and smview.c
118code to try to avoid compiler warnings and errors.
119
120
121CHANGES in PNGDIB v2.1.0 (vs. 2.0.0)
122------------------------------------
123
124* Added some fields to return image information (original bit depth,
125resolution, etc.) when reading PNG images.
126
127* Added pngdib_get_version and pngdib_get_version_string functions.
128
129* -Removed- some features from the sample viewer program. It was getting
130too big to be a useful demo. The feature-ful version has been spun off
131into a separate project.
132
133* (v2.1.0 is backward-compatible with v2.0.0. I think.)
134
135
136CHANGES in PNGDIB v2.0.0 (vs. 1.x)
137----------------------------------
138
139* WARNING: v2.0 is neither source- nor binary-compatible with v1.x.
140Compatibility *could* have been done, but frankly I'm not too concerned
141about it. You shouldn't be using this as a shared library anyway. And you
142really ought to update your source to use the new transparency features.
143:-)
144
145* Optional transparency and background-color processing when reading PNG
146images.
147
148* Optional gamma correction when reading PNG images.
149
150* PNG files that you write are now labeled with a gamma of 0.45455,
151indicating that they are in the standard sRGB color space, which is
152(reasonably close to) the color space used by nearly all Windows displays.
153There's no option to change this value, but it can be turned off
154completely.
155
156* Error messages can now be retrieved by the caller.
157
158
159TO DO
160-----
161
162* Improve this documentation.
163
164* Use CreateFile() and related functions instead of fopen(), etc.
165
166* Make the transparency processing code less complicated.
167
168* Investigate the possibility of returning an alpha channel in the DIB or
169elsewhere.
170
171
172======================================================================
173
174int read_png_to_dib(PNGD_P2DINFO *p2dp)
175
176This function takes the filename of an existing PNG file, reads it and
177converts it into an equivalent Windows Device Independent Bitmap (DIB).
178
179USAGE
180
181Create a structure of type PNGD_P2DINFO, zero all the fields, then set the
182fields below as needed.
183
184Field Type Value
185------------ ----------- ------------------------------------------
186.structsize DWORD Set this to sizeof(PNGD_P2DINFO)
187
188.flags DWORD Combination of the following values (see below):
189 PNGD_USE_BKGD
190 PNGD_USE_CUSTOM_BG
191 PNGD_GAMMA_CORRECTION
192 PNGD_USE_HEAPALLOC
193
194.pngfn char* Pointer to null-terminated filename of the PNG
195 file to read.
196
197.bgcolor PNGD_COLOR_struct
198 The background color to use when reading the
199 PNG image (if it includes transparency). You must
200 set the PNGD_USE_CUSTOM_BG flag for this to be used.
201 Note that PNGDIB may modify this field (if you
202 set PNGD_USE_BKGD).
203
204.errmsg char* This should point to a buffer of at least 100
205 characters. If PNGDIB fails, an error message will
206 be written here. This field can be NULL if you don't
207 want error messages.
208
209.heap HANDLE If you set the PNGD_USE_HEAPALLOC flag, PNGDIB will
210 use HeapAlloc instead of GlobalAlloc to allocate
211 memory for the DIB. In that case, you can provide
212 a handle to the heap to use. If you set this to
213 NULL, PNGDIB will use the default heap (from
214 GetProcessHeap).
215
216RETURN VALUE
217
218Returns 0 on success; returns a nonzero error code on error (see table at
219end of this document). If there was an error, the values returned in the
220PNGD_P2DINFO struct are undefined.
221
222If successful, the function will set values for some of the fields in your
223PNGD_P2DINFO structure:
224
225
226FLAGS:
227
228PNGD_USE_BKGD
229
230If set, PNGDIB will use the PNG file's suggested background color, if it
231has one.
232If unset, PNGDIB will ignore any suggested background color in the PNG file.
233
234PNGD_USE_CUSTOM_BG
235
236If set, indicates that you are providing your own background color in the
237bgcolor field. If you are intending only to display (rather than edit) the
238image, it is recommended that you provide a custom background color
239whenever possible -- otherwise some PNG images may look pretty bad. The
240color you choose is up to you, and depends on your application. If you
241have no idea, a gray color may be safer than pure black or white.
242
243IMPORTANT: If you set both PNGD_USE_CUSTOM_BG and PNGD_USE_BKGD, the PNG
244file's suggested background color will be used if it has one. Your custom
245background color will be used if and only if PNG file does not have a
246suggested background color.
247
248PNGD_GAMMA_CORRECTION
249
250If you set this flag, PNGDIB will perform gamma correction when it reads
251PNG images. It assumes that the resulting DIB image will be in the sRGB
252color space. Unlabeled PNG images are assumed to be in the sRGB color
253space. If you do not set this flag, no gamma correction will be done. You
254should usually turn on this flag, especially if you are intending only to
255display (rather than edit) the image.
256
257---
258
259Fields returned or modified by read_png_to_dib:
260
261Field Type Value
262------------ ----------- ------------------------------------------
263.flags DWORD The following bits may be set by the function:
264 PNGD_BG_RETURNED - set if the PNG image was
265 composited against a background color.
266 The color used is then returned in the
267 bgcolor field.
268 PNGD_RES_RETURNED - set if xres,yres,res_units
269 fields are valid
270 PNGD_GAMMA_RETURNED - set if file_gamma is valid
271
272.lpdib LPBITMAPINFOHEADER
273 A pointer to the start of the new DIB in memory.
274 This might more correctly be of type LPBITMAPINFO,
275 but that is less convenient most of the time. Cast
276 its type if necessary. This memory block will
277 contain the BITMAPINFOHEADER, followed by the
278 palette (if present), followed by the bitmap bits.
279 The library will allocate a fixed memory block
280 using GlobalAlloc (or HeapAlloc, if you used the
281 PNGD_USE_HEAPALLOC flag). It is your responsibility
282 to free it with GlobalFree (or HeapFree) when you're
283 done with it.
284
285.dibsize int The size in bytes of the DIB in memory (pointed to
286 by lpdib).
287
288.palette_offs int Integer offset (in bytes) of the palette from the
289 start of lpdib. This will generally be 40.
290
291.bits_offs int Integer offset (in bytes) of the bitmap bits from
292 the start of lpdib. Calculating
293 bits_offset-palette_offset will give you the size
294 of the palette, in bytes.
295
296.palette RGBQUAD* Direct pointer to the palette. Note that this
297 field is redundant and can be calculated from
298 lpdib and palette_offs.
299
300.palette_colors int The number of colors in the palette. This is
301 generally the same as lpdib->biClrUsed.
302
303.lpbits void* Direct pointer to the bitmap bits. Note that this
304 field is redundant and can be calculated from
305 lpdib and bits_offs.
306 This field was accidentally named ".bits" in
307 PNGDIB version 1.x.
308
309.bgcolor PNGD_COLOR_struct
310 If a background color was used when reading the
311 image, it will be returned here and the
312 PNGD_RETURNED_BG flag will be set.
313
314.color_type int The color type (based on the PNG spec).
315.bits_per_sample int Bits per color sample, or per palette entry.
316.bits_per_pixel int Bits per pixel, or per palette entry.
317.interlace int >0 if the image was interlaced.
318.res_x,res_y int X and Y resolution
319.res_units int 1==resolution is in pixels per meter;
320 0==resolution units are unspecified
321.file_gamma double File gamma (e.g. 0.50000)
322
323
324EXAMPLE
325
326See the included file png2bmp.c or smview.c for an example of this function
327being used.
328
329
330======================================================================
331
332int write_dib_to_png(PNGD_D2PINFO *d2pp)
333
334USAGE
335
336Create a structure of type PNGD_D2PINFO, zero all the fields, then set the
337fields below as needed.
338
339Field Type Value
340------------ ----------- ------------------------------------------
341.structsize DWORD Set this to sizeof(PNGD_D2PINFO)
342
343.flags DWORD Set to 0 or a combination of:
344 PNGD_INTERLACE - to write an interlaced PNG image
345 PNGD_NO_GAMMA_LABEL - to suppress writing a gamma
346 value to the file
347
348.pngfn char* Pointer to null-terminated filename of the PNG file
349 to write.
350
351.lpdib LPBITMAPINFOHEADER
352 Set this to point to the start of start of your DIB
353 [header and palette] in memory.
354
355.dibsize int The size in bytes of the data pointed to by lpdib.
356 This field is optional, and can be set to zero. If
357 you set it, it may allow better error checking.
358
359.lpbits void* Pointer to the start of the bitmap bits in memory.
360 Most of the time, the bits data in a DIB
361 immediately follows the header and palette (if
362 present). If that is the case, you can just set
363 lpbits to NULL, and the library will find it.
364
365.bitssize int The size in bytes of the data pointed to by lpbits.
366 This field is optional, and can be set to zero. If
367 you set it, it may allow better error checking.
368
369.software char* Pointer to a brief NULL-terminated string
370 identifying your application. Set to NULL if you
371 don't want your app to be identified in the PNG
372 file.
373
374.errmsg char* This should point to a buffer of at least 100
375 characters. If PNGDIB fails, an error message will
376 be written here. This field can be NULL if you don't
377 want error messages.
378
379RETURN VALUE
380
381Returns 0 on success; returns a nonzero error code on error (see table below).
382
383
384EXAMPLE
385
386See the included file bmp2png.c for an example of this function being used.
387
388
389======================================================================
390
391Table of error codes (from pngdib.h):
392
393
394#define PNGD_E_SUCCESS 0
395#define PNGD_E_ERROR 1 // unspecified error
396#define PNGD_E_VERSION 2 // struct size problem
397#define PNGD_E_NOMEM 3 // could not alloc memory
398#define PNGD_E_UNSUPP 4 // unsupported image type
399#define PNGD_E_LIBPNG 5 // libpng error (invalid PNG?)
400#define PNGD_E_BADBMP 6 // corrupt or unsupported DIB
401#define PNGD_E_BADPNG 7 // corrupt or unsupported PNG
402#define PNGD_E_READ 8 // couldn't read PNG file
403#define PNGD_E_WRITE 9 // couldn't write PNG file
404
405