• R/O
  • SSH

thirdparty-pngdib: Commit

A repository containing pngdib, which is planned to be incorporated into WinDirStat.

Its original home is over at http://entropymine.com/jason/pngdib/


Commit MetaInfo

Révision03757ef47fe34a3ea3b92c0ced89c03e26ccf7d4 (tree)
l'heure2014-01-18 13:17:44
AuteurOliver Schneider <oliver@assa...>
CommiterOliver Schneider

Message de Log

Version 2.2.2 from ZIP at http://entropymine.com/jason/pngdib/

Change Summary

Modification

diff -r 000000000000 -r 03757ef47fe3 bmp2png.c
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/bmp2png.c Sat Jan 18 04:17:44 2014 +0000
@@ -0,0 +1,111 @@
1+// bmp2png.c
2+// A sample program that uses the PNGDIB library
3+// converts a BMP image file to a PNG image file
4+
5+#include <windows.h>
6+#include <stdio.h>
7+#include "pngdib.h"
8+
9+//#define DIB_ALPHA32
10+
11+// This is just a generic function to read a file into a memory block.
12+int read_bmp_to_mem(char *bmpfn,unsigned char **bmppp, DWORD *fsizep)
13+{
14+ HANDLE hfile;
15+ DWORD fsize;
16+ unsigned char *fbuf;
17+ DWORD bytesread;
18+
19+ hfile=CreateFile(bmpfn,GENERIC_READ,FILE_SHARE_READ,NULL,
20+ OPEN_EXISTING,FILE_ATTRIBUTE_NORMAL,NULL);
21+ if(hfile==INVALID_HANDLE_VALUE) return 1;
22+
23+ fsize=GetFileSize(hfile,NULL);
24+ if(fsize>0) {
25+ fbuf=(unsigned char*)GlobalAlloc(GPTR,fsize);
26+ if(fbuf) {
27+ if(ReadFile(hfile,(void*)fbuf,fsize,&bytesread,NULL)) {
28+ if(bytesread==fsize) {
29+ (*bmppp) = fbuf;
30+ (*fsizep) = fsize;
31+ CloseHandle(hfile);
32+ return 0; // success
33+ }
34+ }
35+ GlobalFree((void*)fbuf);
36+ }
37+ }
38+ CloseHandle(hfile);
39+ return 1; // error
40+}
41+
42+
43+int main(int argc,char **argv)
44+{
45+ char *bmpfn,*pngfn;
46+ PNGD_D2PINFO d2p;
47+ int ret;
48+ unsigned char *bmpp;
49+ DWORD bmpsize;
50+ LPBITMAPFILEHEADER lpbmfh;
51+ char errmsg[100];
52+
53+ if(argc!=3) {
54+ printf("Usage: %s <file.bmp> <file.png>\n",argv[0]);
55+ return 1;
56+ }
57+ bmpfn=argv[1];
58+ pngfn=argv[2];
59+
60+
61+ if(read_bmp_to_mem(bmpfn,&bmpp, &bmpsize)) {
62+ printf("can't read BMP from file\n");
63+ return 1;
64+ }
65+
66+ ZeroMemory((void*)&d2p,sizeof(PNGD_D2PINFO));
67+
68+ d2p.structsize=sizeof(PNGD_D2PINFO);
69+
70+ d2p.flags=0;
71+#ifdef DIB_ALPHA32
72+ d2p.flags |= PNGD_DIB_ALPHA32;
73+#endif
74+
75+ d2p.pngfn=pngfn;
76+
77+ // The first 14 bytes of a BMP file is a file header, the
78+ // rest is a DIB.
79+ d2p.lpdib = (LPBITMAPINFOHEADER)&bmpp[14];
80+
81+ // This can be left at 0 if you know your DIB is valid.
82+ d2p.dibsize = bmpsize-14;
83+
84+ lpbmfh= (LPBITMAPFILEHEADER)bmpp;
85+ if(lpbmfh->bfOffBits >= bmpsize) {
86+ printf("Corrupt BMP\n");
87+ return 1;
88+ }
89+
90+ // It's usually okay to leave lpbits set to NULL.
91+ d2p.lpbits = &bmpp[lpbmfh->bfOffBits];
92+
93+ // This can be left at 0 if you know your DIB is valid.
94+ d2p.bitssize = bmpsize-lpbmfh->bfOffBits;
95+
96+ d2p.software = "PNGDIB test app";
97+ d2p.errmsg = errmsg; strcpy(errmsg,"");
98+
99+ ret=write_dib_to_png(&d2p);
100+ // returns 0 on success
101+ if(ret) {
102+ printf("Error: %s (%d)\n",d2p.errmsg,ret);
103+ return 1;
104+ }
105+
106+ //
107+ GlobalFree(bmpp);
108+
109+ return 0;
110+}
111+
diff -r 000000000000 -r 03757ef47fe3 png2bmp.c
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/png2bmp.c Sat Jan 18 04:17:44 2014 +0000
@@ -0,0 +1,87 @@
1+// png2dib.c
2+// sample using PNGDIB library
3+// convert a PNG image file to a BMP image file
4+
5+#include <windows.h>
6+#include <stdio.h>
7+#include "pngdib.h"
8+
9+//#define DIB_ALPHA32
10+
11+int write_dib_to_bmp(char *bmpfn, LPBITMAPINFOHEADER lpdib,
12+ int dibsize, int bitsoffset)
13+{
14+ HANDLE hfile;
15+ BITMAPFILEHEADER h;
16+ DWORD written, err;
17+
18+ ZeroMemory((void*)&h,sizeof(h));
19+ h.bfType= MAKEWORD('B','M');
20+ h.bfSize= sizeof(BITMAPFILEHEADER)+dibsize;
21+ h.bfOffBits= sizeof(BITMAPFILEHEADER)+bitsoffset;
22+
23+ hfile=CreateFile(bmpfn,GENERIC_WRITE,FILE_SHARE_READ,NULL,
24+ CREATE_ALWAYS,FILE_ATTRIBUTE_NORMAL,NULL);
25+ if(hfile==INVALID_HANDLE_VALUE) return 1;
26+
27+ if(!WriteFile(hfile,(void*)&h,sizeof(BITMAPFILEHEADER),&written,NULL)) {
28+ err=GetLastError();
29+ CloseHandle(hfile);
30+ return 1;
31+ }
32+ if(!WriteFile(hfile,(void*)lpdib,dibsize,&written,NULL)) {
33+ err=GetLastError();
34+ CloseHandle(hfile);
35+ return 1;
36+ }
37+ CloseHandle(hfile);
38+ return 0;
39+}
40+
41+
42+int main(int argc,char **argv)
43+{
44+ char *bmpfn,*pngfn;
45+ PNGD_P2DINFO p2d;
46+ int ret;
47+ char errmsg[100];
48+
49+
50+ if(argc!=3) {
51+ printf("Usage: %s <file.png> <file.bmp>\n",argv[0]);
52+ return 1;
53+ }
54+ pngfn=argv[1];
55+ bmpfn=argv[2];
56+
57+
58+ ZeroMemory((void*)&p2d,sizeof(PNGD_P2DINFO));
59+
60+ p2d.structsize=sizeof(PNGD_P2DINFO);
61+ p2d.flags=0;
62+#ifdef DIB_ALPHA32
63+ p2d.flags |= PNGD_DIB_ALPHA32;
64+#else
65+ p2d.flags |= PNGD_GAMMA_CORRECTION;
66+#endif
67+ p2d.pngfn=pngfn; // name of the file to read
68+ p2d.errmsg=errmsg; strcpy(errmsg,"");
69+
70+ ret=read_png_to_dib(&p2d);
71+ // returns 0 on success
72+ if(ret) {
73+ // see pngdib.h for a list of error codes
74+ printf("Error: %s (%d)\n",errmsg,ret);
75+ return 1;
76+ }
77+
78+ if(write_dib_to_bmp(bmpfn, p2d.lpdib, p2d.dibsize, p2d.bits_offs)) {
79+ printf("Can't write BMP file\n");
80+ }
81+
82+ // The DIB will have been allocated with GlobalAlloc(GMEM_FIXED...).
83+ // You should free it with GlobalFree when you're done with it.
84+ GlobalFree((void*)p2d.lpdib);
85+
86+ return 0;
87+}
diff -r 000000000000 -r 03757ef47fe3 pngdib.c
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/pngdib.c Sat Jan 18 04:17:44 2014 +0000
@@ -0,0 +1,1102 @@
1+// pngdib.c
2+//
3+// PNGDIB - a mini imaging library for Win32
4+// By Jason Summers
5+// This software may be used without restriction.
6+//
7+// read_png_to_dib()
8+// Read a PNG image file and convert it to a Windows "Device Independent
9+// Bitmap" (DIB)
10+//
11+// write_dib_to_png()
12+// Write a DIB to a PNG image file
13+//
14+// pngdib_get_version_string(void)
15+//
16+// pngdib_get_version(void)
17+//
18+
19+#define PNGDIB_SRC_VERSION 20202
20+#define PNGDIB_SRC_VERSION_STRING "2.2.2"
21+
22+#include <windows.h>
23+#include <stdio.h>
24+#include <stdlib.h>
25+#include <assert.h>
26+#include <malloc.h>
27+#include <math.h>
28+#include "png.h"
29+#include "pngdib.h"
30+
31+#if PNGDIB_SRC_VERSION != PNGDIB_HEADER_VERSION
32+#error Wrong PNGDIB header file version
33+#endif
34+
35+#if (PNG_LIBPNG_VER<10202) || \
36+ (PNG_LIBPNG_VER==10202 && PNG_LIBPNG_BUILD_TYPE<2) || \
37+ (PNG_LIBPNG_VER==10202 && PNG_LIBPNG_BUILD_TYPE==2 && PNG_LIBPNG_VER_BUILD<5)
38+#error libpng 1.2.2b5 or higher is recommended
39+/* You can comment out the previous line if you aren't using gamma
40+ * correction, or don't care about a few obscure gamma correction
41+ * problems that exist in earlier versions of libpng. */
42+#endif
43+
44+
45+// This is basically a Windows-only utility with a simple-as-possible
46+// interface, so I'm not too concerned about allowing a
47+// user-configurable screen gamma.
48+static const double screen_gamma = 2.2;
49+
50+#define MAX_ERRMSGLEN 100
51+
52+struct errstruct {
53+ jmp_buf *jbufp;
54+ char *errmsg;
55+};
56+
57+static void pngd_get_error_message(int rv,char *e)
58+{
59+ switch(rv) {
60+ case PNGD_E_ERROR: strcpy(e,"Unknown error"); break;
61+ case PNGD_E_VERSION: strcpy(e,"Incompatible library version"); break;
62+ case PNGD_E_NOMEM: strcpy(e,"Unable to allocate memory"); break;
63+ case PNGD_E_UNSUPP: strcpy(e,"Invalid or unsupported image"); break;
64+ case PNGD_E_LIBPNG: strcpy(e,"libpng reported an error"); break;
65+ case PNGD_E_BADBMP: strcpy(e,"Invalid BMP image"); break;
66+ case PNGD_E_BADPNG: strcpy(e,"Invalid PNG image"); break;
67+ case PNGD_E_READ: strcpy(e,"Unable to read file"); break;
68+ case PNGD_E_WRITE: strcpy(e,"Unable to write file"); break;
69+ }
70+}
71+
72+static unsigned char* uncompress_dib(LPBITMAPINFO lpbmi1, int infosize, void *lpbits1)
73+{
74+ LPBITMAPINFOHEADER lpdib2;
75+ unsigned char *lpbits2;
76+ void *whatever;
77+ int linesize, bitssize;
78+ HBITMAP hb;
79+ HDC hdc;
80+ HGDIOBJ rvgdi;
81+ int rvi;
82+ int width,height;
83+ LPBITMAPINFOHEADER lpdib1;
84+
85+ lpdib1=(LPBITMAPINFOHEADER)lpbmi1;
86+ width=lpdib1->biWidth;
87+ height=lpdib1->biHeight;
88+
89+ linesize= (((width * lpdib1->biBitCount)+31)/32)*4;
90+ bitssize= linesize*height;
91+
92+ lpdib2= (LPBITMAPINFOHEADER)malloc(infosize);
93+ if(!lpdib2) return NULL;
94+
95+ // create a header for the new uncompressed DIB
96+ CopyMemory((void*)lpdib2,(void*)lpdib1,infosize);
97+ lpdib2->biCompression=BI_RGB;
98+ lpdib2->biSizeImage=0;
99+
100+ lpbits2= (unsigned char*)malloc(bitssize);
101+ if(!lpbits2) { free((void*)lpdib2); return NULL; }
102+
103+
104+ // Windows bitmap handling functions are not exactly convenient,
105+ // especially when trying to deal with DIBs. Every function wants
106+ // to convert them into DDBs. We have to play stupid games and
107+ // convert back and forth. This probably uses too much memory,
108+ // and I'm not 100% sure it is exactly correct, but it seems to
109+ // work for me.
110+
111+ hb=CreateDIBSection(NULL,(LPBITMAPINFO)lpdib2,DIB_RGB_COLORS,&whatever,NULL,0);
112+
113+ hdc=CreateCompatibleDC(NULL);
114+ rvgdi=SelectObject(hdc,hb);
115+ //SetStretchBltMode(hdc,COLORONCOLOR);
116+ rvi=StretchDIBits(hdc,
117+ 0,0,width,height,
118+ 0,0,width,height,
119+ lpbits1, (LPBITMAPINFO)lpdib1,
120+ DIB_RGB_COLORS,SRCCOPY);
121+ rvi=GetDIBits(hdc,hb,0,height, (LPVOID)lpbits2,
122+ (LPBITMAPINFO)lpdib2,DIB_RGB_COLORS);
123+
124+ DeleteDC(hdc);
125+ DeleteObject(hb);
126+ free((void*)lpdib2);
127+
128+ return lpbits2;
129+}
130+
131+
132+static void my_error_fn(png_structp png_ptr, const char *err_msg)
133+{
134+ struct errstruct *errinfop;
135+ jmp_buf *j;
136+
137+ errinfop = (struct errstruct *)png_get_error_ptr(png_ptr);
138+ j = errinfop->jbufp;
139+ _snprintf(errinfop->errmsg,MAX_ERRMSGLEN,"[libpng] %s",err_msg);
140+ errinfop->errmsg[MAX_ERRMSGLEN-1]='\0';
141+ longjmp(*j, -1);
142+}
143+
144+
145+static void my_warning_fn(png_structp png_ptr, const char *warn_msg)
146+{
147+ return;
148+}
149+
150+
151+// This function should perform identically to libpng's gamma correction.
152+// I'd prefer to have libpng do all gamma correction itself,
153+// but I can't figure out how to do that efficiently.
154+static void gamma_correct(double screen_gamma,double file_gamma,
155+ unsigned char *red, unsigned char *green, unsigned char *blue)
156+{
157+ double g;
158+
159+#ifndef PNG_GAMMA_THRESHOLD
160+# define PNG_GAMMA_THRESHOLD 0.05
161+#endif
162+
163+ if(fabs(screen_gamma*file_gamma-1.0)<=PNG_GAMMA_THRESHOLD) return;
164+
165+ if (screen_gamma>0.000001)
166+ g=1.0/(file_gamma*screen_gamma);
167+ else
168+ g=1.0;
169+
170+ (*red) = (unsigned char)(pow((double)(*red )/255.0,g)*255.0+0.5);
171+ (*green) = (unsigned char)(pow((double)(*green)/255.0,g)*255.0+0.5);
172+ (*blue) = (unsigned char)(pow((double)(*blue )/255.0,g)*255.0+0.5);
173+}
174+
175+int read_png_to_dib(PNGD_P2DINFO *p2dp)
176+{
177+ png_structp png_ptr;
178+ png_infop info_ptr;
179+ jmp_buf jbuf;
180+ struct errstruct errinfo;
181+ png_uint_32 width, height;
182+ int png_bit_depth, color_type, interlace_type;
183+ png_colorp png_palette;
184+ png_uint_32 res_x, res_y;
185+ int has_phys, has_gama;
186+ int res_unit_type;
187+ FILE *fp;
188+ int palette_entries;
189+ unsigned char **row_pointers;
190+ unsigned char *lpdib;
191+ unsigned char *dib_palette;
192+ unsigned char *dib_bits;
193+ unsigned char *tmprow;
194+ int dib_bpp, dib_bytesperrow;
195+ int i,j;
196+ int rv;
197+ png_color_16 bkgd; // used with png_set_background
198+ int has_trns, trns_color;
199+ int has_bkgd; // ==1 if there a bkgd chunk, and USE_BKGD flag
200+ png_color_16p temp_colorp;
201+ png_color_16p bg_colorp; // background color (if has_bkgd)
202+ png_bytep trns_trans;
203+ int manual_trns;
204+ int manual_gamma;
205+ struct PNGD_COLOR_struct bkgd_color;
206+ int is_grayscale,has_alpha_channel;
207+ double file_gamma;
208+ char *errmsg;
209+ char dummy_errmsg[MAX_ERRMSGLEN];
210+ int imginfo; // flag for v2.1 fields
211+ int use_heapalloc;
212+ HANDLE heap;
213+ int dib_alpha32;
214+ int write_bitfields;
215+
216+ imginfo=0;
217+ use_heapalloc=0;
218+ dib_alpha32=0;
219+ write_bitfields=0;
220+
221+ // fields through errmsg must exist
222+ if(p2dp->structsize<48) return PNGD_E_VERSION;
223+
224+ // try to be somewhat backward-compatible
225+ if(p2dp->structsize>=88) {
226+ //if(p2dp->reserved1 != 0) return PNGD_E_VERSION;
227+ imginfo=1;
228+ }
229+
230+ if(p2dp->structsize>=96) {
231+ //if(p2dp->reserved2 != 0) return PNGD_E_VERSION;
232+ if(p2dp->flags & PNGD_USE_HEAPALLOC) {
233+ use_heapalloc=1;
234+ heap = p2dp->heap;
235+ if(!heap) heap = GetProcessHeap();
236+ }
237+ }
238+
239+ manual_trns=0;
240+ has_trns=has_bkgd=0;
241+ rv=PNGD_E_ERROR;
242+ png_ptr=NULL;
243+ info_ptr=NULL;
244+ fp=NULL;
245+ row_pointers=NULL;
246+ lpdib=NULL;
247+
248+ // make sure errmsg is not NULL even if user doesn't want it
249+ if(p2dp->errmsg)
250+ errmsg=p2dp->errmsg;
251+ else
252+ errmsg=dummy_errmsg;
253+ errmsg[0]='\0';
254+
255+ if(p2dp->flags&PNGD_USE_CUSTOM_BG) {
256+ bkgd_color.red= p2dp->bgcolor.red;
257+ bkgd_color.green= p2dp->bgcolor.green;
258+ bkgd_color.blue= p2dp->bgcolor.blue;
259+ }
260+ else {
261+ bkgd_color.red= 255; // Should never get used. If the
262+ bkgd_color.green= 128; // background turns orange, it's a bug.
263+ bkgd_color.blue= 0;
264+ }
265+
266+ // Set the user-defined pointer to point to our jmp_buf. This will
267+ // hopefully protect against potentially different sized jmp_buf's in
268+ // libpng, while still allowing this library to be threadsafe.
269+ errinfo.jbufp = &jbuf;
270+ errinfo.errmsg = errmsg;
271+
272+ png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING,(void*)(&errinfo),
273+ my_error_fn, my_warning_fn);
274+ if(!png_ptr) { rv=PNGD_E_NOMEM; goto abort; }
275+
276+
277+ info_ptr = png_create_info_struct(png_ptr);
278+ if(!info_ptr) {
279+ //png_destroy_read_struct(&png_ptr, (png_infopp)NULL, (png_infopp)NULL);
280+ rv=PNGD_E_NOMEM; goto abort;
281+ }
282+
283+ if(setjmp(jbuf)) {
284+ // we'll get here if an error occurred in any of the following
285+ // png_ functions
286+
287+ rv=PNGD_E_LIBPNG;
288+ goto abort;
289+ }
290+
291+ if((fp = fopen(p2dp->pngfn, "rb")) == NULL) {
292+ rv=PNGD_E_READ;
293+ goto abort;
294+ }
295+
296+ png_init_io(png_ptr, fp);
297+
298+ png_read_info(png_ptr, info_ptr);
299+
300+ png_get_IHDR(png_ptr, info_ptr, &width, &height, &png_bit_depth, &color_type,
301+ &interlace_type, NULL, NULL);
302+
303+ if(imginfo) {
304+ // return some info to the caller
305+ p2dp->color_type=color_type;
306+ p2dp->bits_per_sample=png_bit_depth;
307+ p2dp->interlace=interlace_type;
308+ switch(color_type) {
309+ case PNG_COLOR_TYPE_RGB: p2dp->bits_per_pixel=png_bit_depth*3; break;
310+ case PNG_COLOR_TYPE_RGB_ALPHA: p2dp->bits_per_pixel=png_bit_depth*4; break;
311+ case PNG_COLOR_TYPE_GRAY_ALPHA: p2dp->bits_per_pixel=png_bit_depth*2; break;
312+ default: p2dp->bits_per_pixel=png_bit_depth;
313+ }
314+ }
315+
316+ is_grayscale = !(color_type&PNG_COLOR_MASK_COLOR);
317+ has_alpha_channel = (color_type&PNG_COLOR_MASK_ALPHA)?1:0;
318+
319+ has_trns = png_get_valid(png_ptr,info_ptr,PNG_INFO_tRNS);
320+
321+ if(p2dp->flags&PNGD_DIB_ALPHA32 && (has_trns || has_alpha_channel)) {
322+ // Fixme - if trns(for palette) has no transparent entries,
323+ // we could skip this.
324+ dib_alpha32=1;
325+ write_bitfields=1;
326+
327+ if (!(color_type&PNG_COLOR_MASK_COLOR)) {
328+ png_set_gray_to_rgb(png_ptr);
329+ }
330+ else if(color_type==PNG_COLOR_TYPE_PALETTE) {
331+ png_set_palette_to_rgb(png_ptr);
332+ }
333+
334+ if (has_trns) png_set_tRNS_to_alpha(png_ptr);
335+
336+ goto notrans;
337+ }
338+
339+ // look for bKGD chunk, and process if applicable
340+ if(p2dp->flags & PNGD_USE_BKGD) {
341+ if(png_get_bKGD(png_ptr, info_ptr, &bg_colorp)) {
342+ // process the background, store 8-bit RGB in bkgd_color
343+ has_bkgd=1;
344+
345+ if(is_grayscale && png_bit_depth<8) {
346+ bkgd_color.red =
347+ bkgd_color.green=
348+ bkgd_color.blue =
349+ (unsigned char) ( (bg_colorp->gray*255)/( (1<<png_bit_depth)-1 ) );
350+ }
351+ else if(png_bit_depth<=8) {
352+ bkgd_color.red=(unsigned char)(bg_colorp->red);
353+ bkgd_color.green=(unsigned char)(bg_colorp->green);
354+ bkgd_color.blue =(unsigned char)(bg_colorp->blue);
355+ }
356+ else {
357+ bkgd_color.red=(unsigned char)(bg_colorp->red>>8);
358+ bkgd_color.green=(unsigned char)(bg_colorp->green>>8);
359+ bkgd_color.blue =(unsigned char)(bg_colorp->blue>>8);
360+ }
361+ }
362+ }
363+
364+ if( !(color_type & PNG_COLOR_MASK_ALPHA) && !has_trns) {
365+ // If no transparency, we can skip this whole background-color mess.
366+ goto notrans;
367+ }
368+
369+ if(has_bkgd && (png_bit_depth>8 || !is_grayscale || has_alpha_channel)) {
370+ png_set_background(png_ptr, bg_colorp,
371+ PNG_BACKGROUND_GAMMA_FILE, 1, 1.0);
372+ }
373+ else if(is_grayscale && has_trns && png_bit_depth<=8
374+ && (has_bkgd || (p2dp->flags & PNGD_USE_CUSTOM_BG)) )
375+ {
376+ // grayscale binarytrans,<=8bpp: transparency is handle manually
377+ // by modifying a palette entry (later)
378+ png_get_tRNS(png_ptr,info_ptr,&trns_trans, &i, &temp_colorp);
379+ if(i>=1) {
380+ trns_color= temp_colorp->gray; // corresponds to a palette entry
381+ manual_trns=1;
382+ }
383+ }
384+ else if(!has_bkgd && (has_trns || has_alpha_channel) &&
385+ (p2dp->flags & PNGD_USE_CUSTOM_BG) )
386+ { // process most CUSTOM background colors
387+ bkgd.index = 0; // unused
388+ bkgd.red = p2dp->bgcolor.red;
389+ bkgd.green = p2dp->bgcolor.green;
390+ bkgd.blue = p2dp->bgcolor.blue;
391+
392+ // libpng may use bkgd.gray if bkgd.red==bkgd.green==bkgd.blue.
393+ // Not sure if that's a libpng bug or not.
394+ bkgd.gray = p2dp->bgcolor.red;
395+
396+ if(png_bit_depth>8) {
397+ bkgd.red = (bkgd.red <<8)|bkgd.red;
398+ bkgd.green= (bkgd.green<<8)|bkgd.green;
399+ bkgd.blue = (bkgd.blue <<8)|bkgd.blue;
400+ bkgd.gray = (bkgd.gray <<8)|bkgd.gray;
401+ }
402+
403+ if(is_grayscale) {
404+ /* assert(png_bit_depth>8); */
405+
406+ /* Need to expand to full RGB if unless background is pure gray */
407+ if(bkgd.red!=bkgd.green || bkgd.red!=bkgd.blue) {
408+ png_set_gray_to_rgb(png_ptr);
409+
410+ // png_set_tRNS_to_alpha() is called here because otherwise
411+ // binary transparency for 16-bps grayscale images doesn't
412+ // work. Libpng will think black pixels are transparent.
413+ // I don't know exactly why it works. It does *not* add an
414+ // alpha channel, as you might think (adding an alpha
415+ // channnel makes no sense if you are using
416+ // png_set_background).
417+ //
418+ // Here's an alternate hack that also seems to work, but
419+ // uses direct structure access:
420+ //
421+ // png_ptr->trans_values.red =
422+ // png_ptr->trans_values.green =
423+ // png_ptr->trans_values.blue = png_ptr->trans_values.gray;
424+ if(has_trns)
425+ png_set_tRNS_to_alpha(png_ptr);
426+
427+ png_set_background(png_ptr, &bkgd,
428+ PNG_BACKGROUND_GAMMA_SCREEN, 0, 1.0);
429+
430+ }
431+ else { // gray custom background
432+ png_set_background(png_ptr, &bkgd,
433+ PNG_BACKGROUND_GAMMA_SCREEN, 1, 1.0);
434+ }
435+
436+ }
437+ else {
438+ png_set_background(png_ptr, &bkgd,
439+ PNG_BACKGROUND_GAMMA_SCREEN, 0, 1.0);
440+ }
441+ }
442+
443+notrans:
444+
445+ // If we don't have any background color at all that we can use,
446+ // strip the alpha channel.
447+ if(!dib_alpha32 && has_alpha_channel && !has_bkgd &&
448+ !(p2dp->flags & PNGD_USE_CUSTOM_BG) )
449+ {
450+ png_set_strip_alpha(png_ptr);
451+ }
452+
453+ if(png_bit_depth>8)
454+ png_set_strip_16(png_ptr);
455+
456+ if (png_get_sRGB(png_ptr, info_ptr, &i)) {
457+ has_gama=1;
458+ file_gamma = 0.45455;
459+ }
460+ else if(png_get_gAMA(png_ptr, info_ptr, &file_gamma)) {
461+ has_gama=1;
462+ }
463+ else {
464+ has_gama=0;
465+ file_gamma = 0.45455;
466+ }
467+
468+ if(imginfo && has_gama) {
469+ p2dp->file_gamma=file_gamma;
470+ p2dp->flags |= PNGD_GAMMA_RETURNED;
471+ }
472+
473+ manual_gamma=0;
474+ if(p2dp->flags&PNGD_GAMMA_CORRECTION) {
475+
476+ if(!is_grayscale || png_bit_depth>8 || has_alpha_channel) {
477+ png_set_gamma(png_ptr, screen_gamma, file_gamma);
478+ //png_ptr->transformations |= 0x2000; // hack for old libpng versions
479+ }
480+ else manual_gamma=1;
481+
482+ if(has_bkgd) {
483+ // Gamma correct the background color (if we got it from the file)
484+ // before returning it to the app.
485+ gamma_correct(screen_gamma,file_gamma,&bkgd_color.red,&bkgd_color.green,&bkgd_color.blue);
486+ }
487+ }
488+
489+ png_read_update_info(png_ptr, info_ptr);
490+
491+ // color type may have changed, due to our transformations
492+ color_type = png_get_color_type(png_ptr,info_ptr);
493+
494+
495+ switch(color_type) {
496+ case PNG_COLOR_TYPE_RGB_ALPHA:
497+ assert(dib_alpha32);
498+ dib_bpp= 32;
499+ palette_entries=0;
500+ png_set_bgr(png_ptr);
501+ break;
502+ case PNG_COLOR_TYPE_RGB:
503+ dib_bpp= 24;
504+ palette_entries=0;
505+ png_set_bgr(png_ptr);
506+ break;
507+ case PNG_COLOR_TYPE_PALETTE:
508+ dib_bpp=png_bit_depth;
509+ png_get_PLTE(png_ptr,info_ptr,&png_palette,&palette_entries);
510+ break;
511+ case PNG_COLOR_TYPE_GRAY:
512+ case PNG_COLOR_TYPE_GRAY_ALPHA:
513+ dib_bpp=png_bit_depth;
514+ if(png_bit_depth>8) dib_bpp=8;
515+ palette_entries= 1<<dib_bpp;
516+ // we'll construct a grayscale palette later
517+ break;
518+ default:
519+ rv=PNGD_E_BADPNG;
520+ goto abort;
521+ }
522+
523+ if(dib_bpp==2) dib_bpp=4;
524+
525+ // DIBs *do* support physical resolution
526+ has_phys=png_get_valid(png_ptr,info_ptr,PNG_INFO_pHYs);
527+ if(has_phys) {
528+ png_get_pHYs(png_ptr,info_ptr,&res_x,&res_y,&res_unit_type);
529+ if(imginfo && (res_x>0) && (res_y>0)) {
530+ p2dp->res_x=res_x;
531+ p2dp->res_y=res_y;
532+ p2dp->res_units=res_unit_type;
533+ p2dp->flags |= PNGD_RES_RETURNED;
534+ }
535+ }
536+
537+
538+ // DIB scanlines are padded to 4-byte boundaries.
539+ dib_bytesperrow= (((width * dib_bpp)+31)/32)*4;
540+
541+ p2dp->dibsize=sizeof(BITMAPINFOHEADER) + 4*palette_entries +
542+ (write_bitfields?12:0) + height*dib_bytesperrow;
543+ if(use_heapalloc)
544+ lpdib = (unsigned char*)HeapAlloc(heap,HEAP_ZERO_MEMORY,p2dp->dibsize);
545+ else
546+ lpdib = (unsigned char*)GlobalAlloc(GPTR,p2dp->dibsize);
547+
548+ if(!lpdib) { rv=PNGD_E_NOMEM; goto abort; }
549+ p2dp->lpdib = (LPBITMAPINFOHEADER)lpdib;
550+
551+ row_pointers=(unsigned char**)malloc(height*sizeof(unsigned char*));
552+ if(!row_pointers) { rv=PNGD_E_NOMEM; goto abort; }
553+
554+ // there is some redundancy here...
555+ p2dp->palette_offs=sizeof(BITMAPINFOHEADER);
556+ p2dp->bits_offs =sizeof(BITMAPINFOHEADER) + 4*palette_entries + (write_bitfields?12:0);
557+ dib_palette= &lpdib[p2dp->palette_offs];
558+ p2dp->palette= (RGBQUAD*)dib_palette;
559+ dib_bits = &lpdib[p2dp->bits_offs];
560+ p2dp->lpbits = (VOID*)dib_bits;
561+ p2dp->palette_colors = palette_entries;
562+
563+ // set up the DIB palette, if needed
564+ switch(color_type) {
565+ case PNG_COLOR_TYPE_PALETTE:
566+ for(i=0;i<palette_entries;i++) {
567+ p2dp->palette[i].rgbRed = png_palette[i].red;
568+ p2dp->palette[i].rgbGreen = png_palette[i].green;
569+ p2dp->palette[i].rgbBlue = png_palette[i].blue;
570+ }
571+ break;
572+ case PNG_COLOR_TYPE_GRAY:
573+ case PNG_COLOR_TYPE_GRAY_ALPHA:
574+ for(i=0;i<palette_entries;i++) {
575+ p2dp->palette[i].rgbRed =
576+ p2dp->palette[i].rgbGreen =
577+ p2dp->palette[i].rgbBlue = (i*255)/(palette_entries-1);
578+ //if(dib_bpp<=8) {
579+ //if(png_bit_depth<16) {
580+ if(manual_gamma) {
581+ gamma_correct(screen_gamma,file_gamma,
582+ &(p2dp->palette[i].rgbRed),
583+ &(p2dp->palette[i].rgbGreen),
584+ &(p2dp->palette[i].rgbBlue));
585+ }
586+ }
587+ if(manual_trns) {
588+ p2dp->palette[trns_color].rgbRed = bkgd_color.red;
589+ p2dp->palette[trns_color].rgbGreen = bkgd_color.green;
590+ p2dp->palette[trns_color].rgbBlue = bkgd_color.blue;
591+ }
592+ break;
593+ }
594+
595+ // set up BITFIELDS, if needed
596+ if(dib_alpha32) {
597+ static const unsigned char bf_data[12] = {
598+ 0x00,0x00,0xff,0x00,
599+ 0x00,0xff,0x00,0x00,
600+ 0xff,0x00,0x00,0x00
601+ };
602+
603+ for(i=0;i<12;i++) {
604+ lpdib[p2dp->palette_offs+i]=bf_data[i];
605+ }
606+
607+ }
608+
609+ for(j=0;j<(int)height;j++) {
610+ row_pointers[height-1-j]= &dib_bits[j*dib_bytesperrow];
611+ }
612+
613+ png_read_image(png_ptr, row_pointers);
614+
615+ // special handling for this bit depth, since it doesn't exist in DIBs
616+ // expand 2bpp to 4bpp
617+ if(png_bit_depth==2) {
618+ tmprow = (unsigned char*)malloc((width+3)/4 );
619+ if(!tmprow) { rv=PNGD_E_NOMEM; goto abort; }
620+
621+ for(j=0;j<(int)height;j++) {
622+ CopyMemory(tmprow, row_pointers[j], (width+3)/4 );
623+ ZeroMemory(row_pointers[j], (width+1)/2 );
624+
625+ for(i=0;i<(int)width;i++) {
626+ row_pointers[j][i/2] |=
627+ ( ((tmprow[i/4] >> (2*(3-i%4)) ) & 0x03)<< (4*(1-i%2)) );
628+ }
629+ }
630+ free((void*)tmprow);
631+ }
632+
633+ free((void*)row_pointers);
634+ row_pointers=NULL;
635+
636+ png_read_end(png_ptr, info_ptr);
637+
638+ png_destroy_read_struct(&png_ptr, &info_ptr, (png_infopp)NULL);
639+ png_ptr=NULL;
640+
641+ fclose(fp);
642+ fp=NULL;
643+
644+ // fill in the DIB header fields
645+ p2dp->lpdib->biSize= sizeof(BITMAPINFOHEADER);
646+ p2dp->lpdib->biWidth= width;
647+ p2dp->lpdib->biHeight= height;
648+ p2dp->lpdib->biPlanes= 1;
649+ p2dp->lpdib->biBitCount= dib_bpp;
650+ p2dp->lpdib->biCompression= write_bitfields?BI_BITFIELDS:BI_RGB;
651+ // biSizeImage can also be 0 in uncompressed bitmaps
652+ p2dp->lpdib->biSizeImage= height*dib_bytesperrow;
653+
654+ if(has_phys) {
655+ if(res_unit_type==1) {
656+ p2dp->lpdib->biXPelsPerMeter= res_x;
657+ p2dp->lpdib->biYPelsPerMeter= res_y;
658+ }
659+ }
660+ p2dp->lpdib->biClrUsed= palette_entries;
661+ p2dp->lpdib->biClrImportant= 0;
662+
663+ if(has_bkgd || (p2dp->flags&PNGD_USE_CUSTOM_BG)) {
664+ // return the background color if one was used
665+ p2dp->bgcolor.red = bkgd_color.red;
666+ p2dp->bgcolor.green = bkgd_color.green;
667+ p2dp->bgcolor.blue = bkgd_color.blue;
668+ p2dp->flags |= PNGD_BG_RETURNED;
669+ }
670+
671+ return PNGD_E_SUCCESS;
672+
673+abort:
674+
675+ if(png_ptr) png_destroy_read_struct(&png_ptr, &info_ptr, (png_infopp)NULL);
676+ if(fp) fclose(fp);
677+ if(row_pointers) free((void*)row_pointers);
678+ if(lpdib) {
679+ if(use_heapalloc)
680+ HeapFree(heap,0,(LPVOID)lpdib);
681+ else
682+ GlobalFree((HGLOBAL)lpdib);
683+ }
684+
685+ // If we don't have an error message yet, use a
686+ // default one based on the code
687+ if(!strlen(errmsg)) {
688+ pngd_get_error_message(rv,errmsg);
689+ }
690+
691+ return rv;
692+}
693+
694+
695+//--------------------------------------------------------------------
696+
697+int write_dib_to_png(PNGD_D2PINFO *d2pp)
698+{
699+ png_structp png_ptr;
700+ png_infop info_ptr;
701+ jmp_buf jbuf;
702+ struct errstruct errinfo;
703+ png_text text_ptr[1];
704+ unsigned char *bits;
705+ unsigned char *newimage;
706+ RGBQUAD* dib_palette;
707+ int headersize, dib_bpp;
708+ int png_color_type;
709+ png_uint_32 res_x, res_y;
710+ png_color_8 pngc8;
711+ int height,width;
712+ int palette_entries;
713+ int topdown;
714+ int dib_bytesperrow;
715+ int compression;
716+ FILE *fp;
717+ png_color png_palette[256];
718+ unsigned char **row_pointers;
719+ int i,x,y,size;
720+ DWORD *bitfields;
721+ unsigned int v;
722+ int bf_format; // bitfields format identifier
723+ int iscompressed;
724+ int bfsize; // bytes in "bitfields" section
725+ int palsize; // bytes in palette
726+
727+ int palentsize; // bytes in a palette entry: 3 or 4;
728+ BITMAPCOREHEADER *lpolddib;
729+ int rv; // return code
730+ char *errmsg;
731+ char dummy_errmsg[MAX_ERRMSGLEN];
732+ int dib_alpha32;
733+
734+ if(d2pp->structsize != sizeof(PNGD_D2PINFO)) return PNGD_E_VERSION;
735+
736+ rv=PNGD_E_ERROR; // this should always get changed before returning
737+ png_ptr=NULL;
738+ info_ptr=NULL;
739+ fp=NULL;
740+ row_pointers=NULL;
741+ newimage=NULL;
742+ dib_alpha32=0;
743+
744+ if(d2pp->errmsg)
745+ errmsg=d2pp->errmsg;
746+ else
747+ errmsg=dummy_errmsg;
748+ errmsg[0]='\0';
749+
750+ headersize= d2pp->lpdib->biSize;
751+
752+ if(headersize<40 && headersize!=12) {
753+ sprintf(errmsg,"Unexpected BMP header size (%d)",headersize);
754+ rv=PNGD_E_BADBMP; goto abort;
755+ }
756+
757+ if(headersize==12) {
758+ // This is to support an old kind of DIBs (OS/2) that aren't really
759+ // used anymore.
760+ palentsize= 3;
761+ lpolddib= (BITMAPCOREHEADER*) d2pp->lpdib;
762+ width= lpolddib->bcWidth;
763+ height= lpolddib->bcHeight;
764+ dib_bpp= lpolddib->bcBitCount;
765+ compression = BI_RGB;
766+ res_x = res_y = 0;
767+
768+ // This will get adjusted later if there is a palette.
769+ // Not sure it's right, though. Do old DIBs always have a
770+ // full-sized palette?
771+ palette_entries=0;
772+ }
773+ else {
774+ palentsize=4;
775+ width= d2pp->lpdib->biWidth;
776+ height= d2pp->lpdib->biHeight;
777+ dib_bpp= d2pp->lpdib->biBitCount;
778+ compression= d2pp->lpdib->biCompression;
779+ res_x = d2pp->lpdib->biXPelsPerMeter;
780+ res_y = d2pp->lpdib->biYPelsPerMeter;
781+ palette_entries = d2pp->lpdib->biClrUsed;
782+ }
783+
784+ // supposedly, if the height is negative, the top scanline is stored first
785+ topdown=0;
786+ if(height<0) {
787+ height= -height;
788+ topdown=1;
789+ }
790+
791+ // sanity check
792+ if(height<1 || height>1000000 || width<1 || width>1000000) {
793+ sprintf(errmsg,"Unreasonable image dimensions (%dx%d)",width,height);
794+ rv=PNGD_E_BADBMP; goto abort;
795+ }
796+
797+ if(dib_bpp==32 && (d2pp->flags&PNGD_DIB_ALPHA32)) {
798+ dib_alpha32=1;
799+ }
800+
801+ // only certain combinations of compression and bpp are allowed
802+ switch(compression) {
803+ case BI_RGB:
804+ if(dib_bpp!=1 && dib_bpp!=4 && dib_bpp!=8 && dib_bpp!=16
805+ && dib_bpp!=24 && dib_bpp!=32)
806+ {
807+ sprintf(errmsg,"Unsupported bit depth (%d)",dib_bpp);
808+ rv=PNGD_E_UNSUPP; goto abort;
809+ }
810+ break;
811+ case BI_RLE4:
812+ if(dib_bpp!=4) {
813+ rv=PNGD_E_UNSUPP; goto abort;
814+ }
815+ break;
816+ case BI_RLE8:
817+ if(dib_bpp!=8) {
818+ rv=PNGD_E_UNSUPP; goto abort;
819+ }
820+ break;
821+ case BI_BITFIELDS:
822+ if(dib_bpp!=16 && dib_bpp!=32) {
823+ rv=PNGD_E_UNSUPP; goto abort;
824+ }
825+ break;
826+ default:
827+ sprintf(errmsg,"Unsupported compression scheme");
828+ return PNGD_E_UNSUPP;
829+ }
830+
831+ iscompressed= (compression==BI_RLE4 || compression==BI_RLE8);
832+
833+ // uncompressed dibs are padded to 4-byte bondaries
834+ dib_bytesperrow= (((width * dib_bpp)+31)/32)*4;
835+
836+ if(dib_bpp<16) {
837+ if(palette_entries==0) palette_entries = 1<<dib_bpp;
838+ }
839+
840+ //if(dib_bpp>8) {
841+ // palette_entries=0;
842+ //}
843+ //else {
844+ // // 0 means it has a full palette
845+ // if(palette_entries==0) palette_entries = 1<<dib_bpp;
846+ //}
847+
848+ bfsize = (compression==BI_BITFIELDS)?12:0;
849+
850+ //if(compression==BI_BITFIELDS) palsize=12;
851+ //else palsize=palentsize*palette_entries;
852+ palsize=palentsize*palette_entries;
853+
854+ // bounds check
855+ size= headersize + bfsize + palsize;
856+ if(d2pp->dibsize) {
857+ if(size>d2pp->dibsize) {
858+ rv=PNGD_E_BADBMP; goto abort;
859+ }
860+ }
861+
862+ if(d2pp->lpbits) {
863+ if(d2pp->bitssize && !iscompressed) { // bounds check
864+ size=dib_bytesperrow*height;
865+ if(size>d2pp->bitssize) { rv=PNGD_E_BADBMP; goto abort; }
866+ }
867+
868+ bits=(unsigned char*)d2pp->lpbits;
869+ }
870+ else {
871+ // If not provided by user, assume the bits immediately
872+ // follow the palette.
873+
874+ if(d2pp->dibsize && !iscompressed) { // bounds check
875+ size= headersize+bfsize+palsize+dib_bytesperrow*height;
876+ if(size>d2pp->dibsize) { rv=PNGD_E_BADBMP; goto abort; }
877+ }
878+
879+ bits= &((unsigned char*)(d2pp->lpdib))[headersize+bfsize+palsize];
880+ }
881+
882+ bitfields = (DWORD*) ( &((unsigned char*)(d2pp->lpdib))[headersize] );
883+ dib_palette = (RGBQUAD*) ( &((unsigned char*)(d2pp->lpdib))[headersize+bfsize] );
884+
885+ //bitfields=(DWORD*)dib_palette;
886+
887+ bf_format=0;
888+ if(compression==BI_BITFIELDS) {
889+ if(dib_bpp==16) {
890+ if (bitfields[0]==0x00007c00 && bitfields[1]==0x000003e0 &&
891+ bitfields[2]==0x0000001f) bf_format=11; // 555
892+ else if(bitfields[0]==0x0000f800 && bitfields[1]==0x000007e0 &&
893+ bitfields[2]==0x0000001f) bf_format=12; // 565
894+ else { rv=PNGD_E_UNSUPP; goto abort; }
895+ }
896+ if(dib_bpp==32) {
897+ if (bitfields[0]==0x00ff0000 && bitfields[1]==0x0000ff00 &&
898+ bitfields[2]==0x000000ff) bf_format=21;
899+ else { rv=PNGD_E_UNSUPP; goto abort; }
900+ }
901+ }
902+
903+ if(bf_format==0 && dib_bpp==16) bf_format=10;
904+ if(bf_format==0 && dib_bpp==32) bf_format=20;
905+
906+
907+ // Done analyzing the DIB, now time to convert it to PNG
908+
909+
910+ // jbuf: see comments in read_png_to_dib()
911+ errinfo.jbufp = &jbuf;
912+ errinfo.errmsg = errmsg;
913+ png_ptr = png_create_write_struct(PNG_LIBPNG_VER_STRING, (void*)(&errinfo),
914+ my_error_fn, my_warning_fn);
915+ if (!png_ptr) { rv=PNGD_E_NOMEM; goto abort; }
916+
917+
918+ info_ptr = png_create_info_struct(png_ptr);
919+ if (!info_ptr) {
920+ //png_destroy_write_struct(&png_ptr,(png_infopp)NULL);
921+ rv=PNGD_E_NOMEM; goto abort;
922+ }
923+
924+ if(setjmp(jbuf)) {
925+ // we'll get here if an error occurred in any of the following
926+ // png_ functions
927+ rv=PNGD_E_LIBPNG;
928+ goto abort;
929+ }
930+
931+ fp=fopen(d2pp->pngfn,"wb");
932+ if(!fp) {
933+ rv=PNGD_E_WRITE;
934+ goto abort;
935+ }
936+
937+ png_init_io(png_ptr, fp);
938+
939+ if(dib_alpha32) {
940+ png_color_type = PNG_COLOR_TYPE_RGB_ALPHA;
941+ }
942+ else {
943+ png_color_type = (dib_bpp>8)?PNG_COLOR_TYPE_RGB:PNG_COLOR_TYPE_PALETTE;
944+ }
945+
946+ png_set_IHDR(png_ptr, info_ptr, width, height, (dib_bpp>8)?8:dib_bpp,
947+ png_color_type,
948+ (d2pp->flags&PNGD_INTERLACED)?PNG_INTERLACE_ADAM7:PNG_INTERLACE_NONE,
949+ PNG_COMPRESSION_TYPE_BASE, PNG_FILTER_TYPE_BASE);
950+
951+ // write sRGB and gAMA chunks
952+ if(!(d2pp->flags&PNGD_NO_GAMMA_LABEL)) {
953+ png_set_sRGB(png_ptr, info_ptr, PNG_sRGB_INTENT_RELATIVE);
954+ png_set_gAMA(png_ptr, info_ptr, 0.45455);
955+ }
956+
957+ // For 16-bit DIBs, we get to write an sBIT chunk.
958+ if(bf_format==10 || bf_format==11) {
959+ pngc8.red= 5; pngc8.green= 5; pngc8.blue= 5;
960+ png_set_sBIT(png_ptr, info_ptr, &pngc8);
961+ }
962+ if(bf_format==12) {
963+ pngc8.red= 5; pngc8.green= 6; pngc8.blue= 5;
964+ png_set_sBIT(png_ptr, info_ptr, &pngc8);
965+ }
966+
967+ // pHYs
968+ if(res_x>0 && res_y>0)
969+ png_set_pHYs(png_ptr, info_ptr, res_x, res_y, 1);
970+
971+
972+ if(palette_entries>0) {
973+ for(i=0;i<palette_entries;i++) {
974+ if(palentsize==3) {
975+ png_palette[i].red = ((RGBTRIPLE*)dib_palette)[i].rgbtRed;
976+ png_palette[i].green = ((RGBTRIPLE*)dib_palette)[i].rgbtGreen;
977+ png_palette[i].blue = ((RGBTRIPLE*)dib_palette)[i].rgbtBlue;
978+ }
979+ else {
980+ png_palette[i].red = dib_palette[i].rgbRed;
981+ png_palette[i].green = dib_palette[i].rgbGreen;
982+ png_palette[i].blue = dib_palette[i].rgbBlue;
983+ }
984+ }
985+ png_set_PLTE(png_ptr, info_ptr, png_palette, palette_entries);
986+ }
987+
988+ if(dib_bpp>8)
989+ png_set_bgr(png_ptr);
990+
991+ png_write_info(png_ptr, info_ptr);
992+
993+ row_pointers=(unsigned char**)malloc(height*sizeof(unsigned char*));
994+ if(!row_pointers) { rv=PNGD_E_NOMEM; goto abort; }
995+
996+
997+ if(dib_bpp==16 || (dib_bpp==32 && !dib_alpha32)) {
998+
999+ // Special handling for these bit depths.
1000+ // This uses a lot of memory, and could be improved by processing
1001+ // one line at a time (but that makes it tricky to write interlaced
1002+ // images).
1003+
1004+ newimage=(unsigned char*)malloc(height*width*3);
1005+ if(!newimage) { rv=PNGD_E_NOMEM; goto abort; }
1006+
1007+ for(y=0;y<height;y++) {
1008+ for(x=0;x<width;x++) {
1009+ switch(bf_format) {
1010+ case 10: case 11: // 16-bit, format 555 (xRRRRRGG GGGBBBBB)
1011+ v= bits[y*dib_bytesperrow+x*2+0] | (bits[y*dib_bytesperrow+x*2+1]<<8);
1012+ newimage[(y*width+x)*3+0]= (v & 0x0000001f)<<3 | (v & 0x0000001f)>>2; // blue
1013+ newimage[(y*width+x)*3+1]= (v & 0x000003e0)>>2 | (v & 0x000003e0)>>7; // green
1014+ newimage[(y*width+x)*3+2]= (v & 0x00007c00)>>7 | (v & 0x00007c00)>>12; // red
1015+ break;
1016+ case 12: // 16-bit, format 565 (RRRRRGGG GGGBBBBB)
1017+ v= bits[y*dib_bytesperrow+x*2+0] | (bits[y*dib_bytesperrow+x*2+1]<<8);
1018+ newimage[(y*width+x)*3+0]= (v & 0x0000001f)<<3 | (v & 0x0000001f)>>2; // blue
1019+ newimage[(y*width+x)*3+1]= (v & 0x000007e0)>>3 | (v & 0x000007e0)>>9; // green
1020+ newimage[(y*width+x)*3+2]= (v & 0x0000f800)>>8 | (v & 0x0000f800)>>13; // red
1021+ break;
1022+ case 20: case 21: // 32-bit, every 4th byte wasted (b g r x)
1023+ newimage[(y*width+x)*3+0]= bits[y*dib_bytesperrow+x*4+0]; // blue
1024+ newimage[(y*width+x)*3+1]= bits[y*dib_bytesperrow+x*4+1]; // green
1025+ newimage[(y*width+x)*3+2]= bits[y*dib_bytesperrow+x*4+2]; // red
1026+ break;
1027+ }
1028+ }
1029+ }
1030+
1031+ for(i=0;i<height;i++) {
1032+ if(topdown)
1033+ row_pointers[i]= &newimage[i*width*3];
1034+ else
1035+ row_pointers[height-1-i]= &newimage[i*width*3];
1036+ }
1037+ png_write_image(png_ptr, row_pointers);
1038+
1039+ free(newimage);
1040+ newimage=NULL;
1041+ }
1042+ else if(iscompressed) {
1043+ newimage= uncompress_dib((LPBITMAPINFO)d2pp->lpdib, headersize+bfsize+palsize, bits);
1044+ if(!newimage) { rv=PNGD_E_NOMEM; goto abort; }
1045+ for(i=0;i<height;i++) {
1046+ if(topdown)
1047+ row_pointers[i]= &newimage[i*dib_bytesperrow];
1048+ else
1049+ row_pointers[height-1-i]= &newimage[i*dib_bytesperrow];
1050+ }
1051+ png_write_image(png_ptr, row_pointers);
1052+
1053+ free(newimage);
1054+ newimage=NULL;
1055+ }
1056+ else {
1057+ for(i=0;i<height;i++) {
1058+ if(topdown)
1059+ row_pointers[i]= &bits[i*dib_bytesperrow];
1060+ else
1061+ row_pointers[height-1-i]= &bits[i*dib_bytesperrow];
1062+ }
1063+ png_write_image(png_ptr, row_pointers);
1064+ }
1065+
1066+ free((VOID*)row_pointers);
1067+ row_pointers=NULL;
1068+
1069+ if(d2pp->software) {
1070+ text_ptr[0].key = "Software";
1071+ text_ptr[0].text = d2pp->software;
1072+ text_ptr[0].compression = PNG_TEXT_COMPRESSION_NONE;
1073+ png_set_text(png_ptr, info_ptr, text_ptr, 1);
1074+ }
1075+
1076+ png_write_end(png_ptr, info_ptr);
1077+
1078+ rv=PNGD_E_SUCCESS;
1079+
1080+abort:
1081+ if(png_ptr) png_destroy_write_struct(&png_ptr, &info_ptr);
1082+ if(fp) fclose(fp);
1083+ if(row_pointers) free(row_pointers);
1084+ if(newimage) free(newimage);
1085+
1086+ // If we don't have an error message yet, use a
1087+ // default one based on the code
1088+ if(!strlen(errmsg)) {
1089+ pngd_get_error_message(rv,errmsg);
1090+ }
1091+ return rv;
1092+}
1093+
1094+char* pngdib_get_version_string(void)
1095+{
1096+ return PNGDIB_SRC_VERSION_STRING;
1097+}
1098+
1099+int pngdib_get_version(void)
1100+{
1101+ return PNGDIB_SRC_VERSION;
1102+}
diff -r 000000000000 -r 03757ef47fe3 pngdib.h
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/pngdib.h Sat Jan 18 04:17:44 2014 +0000
@@ -0,0 +1,100 @@
1+// pngdib.h
2+
3+#define PNGDIB_HEADER_VERSION 20202
4+#define PNGDIB_HEADER_VERSION_STRING "2.2.2"
5+
6+
7+// error codes returned by read_png_to_dib() and/or
8+// write_dib_to_png()
9+
10+#define PNGD_E_SUCCESS 0
11+#define PNGD_E_ERROR 1 // unspecified error
12+#define PNGD_E_VERSION 2 // struct size problem
13+#define PNGD_E_NOMEM 3 // could not alloc memory
14+#define PNGD_E_UNSUPP 4 // unsupported image type
15+#define PNGD_E_LIBPNG 5 // libpng error (corrupt PNG?)
16+#define PNGD_E_BADBMP 6 // corrupt or unsupported DIB
17+#define PNGD_E_BADPNG 7 // corrupt or unsupported PNG
18+#define PNGD_E_READ 8 // couldn't read PNG file
19+#define PNGD_E_WRITE 9 // couldn't write PNG file
20+
21+struct PNGD_COLOR_struct {
22+ unsigned char red, green, blue, reserved;
23+};
24+
25+typedef struct PNGD_D2PINFO_struct {
26+ DWORD structsize; // sizeof(PNGD_D2PINFO)
27+ DWORD flags;
28+#define PNGD_INTERLACED 0x00000001
29+#define PNGD_NO_GAMMA_LABEL 0x00000002
30+#define PNGD_DIB_ALPHA32 0x00000010
31+
32+ char* pngfn; // PNG filename to write
33+
34+ LPBITMAPINFOHEADER lpdib;
35+ int dibsize; // can be 0
36+
37+ VOID* lpbits; // can be NULL
38+ int bitssize; // can be 0
39+
40+ char* software; // (NULL==don't include)
41+// added in v2.0
42+ char* errmsg; // user can set to null or 100-char buffer
43+} PNGD_D2PINFO;
44+
45+
46+typedef struct PNGD_IMAGEINFO_struct {
47+ DWORD structsize; // sizeof(PNGD_IMAGEINFO)
48+ DWORD flags;
49+
50+} PNGD_IMAGEINFO;
51+
52+typedef struct PNGD_P2DINFO_struct {
53+ DWORD structsize; // sizeof(PNGD_P2DINFO)
54+
55+ DWORD flags; // combination of below:
56+#define PNGD_USE_BKGD 0x00000001
57+#define PNGD_USE_CUSTOM_BG 0x00000002
58+#define PNGD_GAMMA_CORRECTION 0x00000004
59+#define PNGD_USE_HEAPALLOC 0x00000008
60+//#define PNGD_DIB_ALPHA32 0x00000010 already defined above
61+
62+#define PNGD_BG_RETURNED 0x00010000 // return value only
63+#define PNGD_RES_RETURNED 0x00020000 // set if xres,yres,res_units are valid
64+#define PNGD_GAMMA_RETURNED 0x00040000 // set if file_gamma is valid
65+
66+ char* pngfn; // PNG filename to read
67+
68+ LPBITMAPINFOHEADER lpdib; // return value only
69+ int dibsize; // return value only
70+ int palette_offs; // return value only
71+ int bits_offs; // return value only
72+ RGBQUAD* palette; // return value only
73+ int palette_colors; // return value only
74+ VOID* lpbits; // return value only
75+// added in v2.0 (size=48)
76+ struct PNGD_COLOR_struct bgcolor; // IN OUT
77+ char* errmsg; // user can set to null or 100-char buffer
78+// added in v2.1 (size=88)
79+ int color_type;
80+ int bits_per_sample;
81+ int bits_per_pixel;
82+ int interlace;
83+ int res_x,res_y;
84+ int res_units;
85+ int reserved1;
86+ double file_gamma;
87+// added in v2.2 (size=96)
88+ HANDLE heap;
89+ int reserved2;
90+
91+} PNGD_P2DINFO;
92+
93+
94+
95+int read_png_to_dib(PNGD_P2DINFO *p2dinfo);
96+
97+int write_dib_to_png(PNGD_D2PINFO *d2pinfo);
98+
99+char* pngdib_get_version_string(void);
100+int pngdib_get_version(void);
diff -r 000000000000 -r 03757ef47fe3 readme.txt
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/readme.txt Sat Jan 18 04:17:44 2014 +0000
@@ -0,0 +1,417 @@
1+PNGDIB - a mini DIB-PNG conversion library for Win32
2+By Jason Summers <jason1@pobox.com>
3+Version 2.2.2, Jul. 2002
4+Web site: http://pobox.com/~jason1/pngdib/
5+
6+
7+This software is distributed in the hope that it will be useful, but
8+WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
9+or FITNESS FOR A PARTICULAR PURPOSE.
10+
11+Permission is hereby granted to use, copy, modify, and distribute this
12+source code for any purpose, without fee.
13+
14+
15+The pngdib.c file contains functions that convert between PNG images
16+and Windows Device Independent Bitmaps (DIBs). PNGDIB is designed to be
17+quick and easy to use, but it does not attempt to support every feature
18+that one might want. If you wish use the PNG format to its full
19+capabilities, you'll need to use libpng directly, or program our own
20+extensions to PNGDIB.
21+
22+REQUIREMENTS
23+
24+* zlib <http://www.info-zip.org/pub/infozip/zlib/>
25+Tested with v1.1.4; other versions probably also work.
26+
27+* libpng <http://www.libpng.org/pub/png/>
28+Version 1.2.2beta5 or higher recommended. Most versions from about 1.0.5
29+on will probably work, but they do not always handle gamma correction
30+correctly when combined with alpha transparency.
31+
32+------
33+
34+INTRODUCTION
35+
36+The PNG-to-DIB function creates version 3.0 DIBs/BMPs. The image will be
37+uncompressed, with either 1, 4, 8, or 24 bits-per-pixel.
38+
39+(Note: A BMP image file is basically just a DIB copied directly from
40+memory, with a 14-byte file header tacked onto the front. The terms DIB
41+and BMP may sometimes be used almost interchangeably.)
42+
43+
44+The DIB-to-PNG function supports approximately version 3.0 DIBs, and also
45+OS/2-style DIBs. It supports bit depths of 1, 4, 8, 16, 24, and 32
46+bits-per-pixel. It supports 4 bpp and 8 bpp compressed DIBs (it uses
47+Windows GDI functions to uncompress them).
48+
49+If you find a valid BMP file that the bmp2png sample program can't read,
50+please let me know.
51+
52+
53+Two sample programs, png2bmp.c and bmp2png.c, are included which demonstrate
54+the use of library functions. They can be compiled as "console mode" Win32
55+applications.
56+
57+A third sample, "smview", is a bare-bones Windows program that uses pngdib
58+to read and display PNG files. This is intended to demonstrate that it is
59+easy to add PNG support to an application that uses DIBs.
60+
61+--------
62+
63+BRIEF INSTRUCTIONS FOR THE SAMPLE PNG VIEWER (smview)
64+
65+[This program is just a demo. For a more usable viewer, visit
66+http://pobox.com/~jason1/purpleview/.]
67+
68+Load a PNG image by selecting File|Open from the menu, or by drag-and-drop
69+from Windows Explorer.
70+
71+Gamma Correction - Toggles gamma correction. If you turn this off, some
72+images, or parts of images, will look too light or too dark.
73+
74+Save As PNG - Saves the visible image to a file.
75+IMPORTANT--- This saves the image as it is currently being displayed. The
76+saved image will not have any transparency, and the background color and
77+gamma correction will be applied to the image, not saved as meta-data.
78+This means that you can lose information by loading and then saving a PNG
79+image.
80+
81+Background colors - You can define a background color that will be used in
82+certain situations. The following logic is used to select a background
83+color: If "Use Image's Background Color" is checked, and the current PNG
84+image file contains a suggested background color, that suggested
85+background color will be used. Otherwise, if "Use Custom Background Color"
86+is checked, your custom background color will be used (by default this is
87+a very light gray color). Otherwise, no background color will be used at
88+all, and transparency information in the image will be completely ignored.
89+Some images will not look very good in this situation. (A pure white
90+background will be used for the window, but will not be applied to the
91+image.)
92+
93+Any time you make a change to the gamma or background color settings, the
94+PNG file will be reloaded from disk. That's not the ideal thing to do, but
95+this _is_ just a demo program...
96+
97+--------
98+
99+Basic instructions for using the library in your own programs (the
100+read_png_to_dib and write_dib_to_png functions) follow the change log
101+and TO DO list.
102+
103+CHANGES in PNGDIB v2.2.2 (vs. 2.2.0)
104+------------------------------------
105+
106+* Fixed a memory allocation bug in write_dib_to_png().
107+* Experimental optional support for 32bpp DIBs with an alpha channel.
108+
109+
110+CHANGES in PNGDIB v2.2.0 (vs. 2.1.1)
111+------------------------------------
112+
113+* Option to use HeapAlloc instead of GlobalAlloc (when reading PNGs).
114+
115+
116+CHANGES in PNGDIB v2.1.1 (vs. 2.1.0)
117+------------------------------------
118+
119+* More accurate conversion of 16-bpp DIBs into PNGs.
120+
121+* Some minor changes (mostly typecasts) to the pngdib.c and smview.c
122+code to try to avoid compiler warnings and errors.
123+
124+
125+CHANGES in PNGDIB v2.1.0 (vs. 2.0.0)
126+------------------------------------
127+
128+* Added some fields to return image information (original bit depth,
129+resolution, etc.) when reading PNG images.
130+
131+* Added pngdib_get_version and pngdib_get_version_string functions.
132+
133+* -Removed- some features from the sample viewer program. It was getting
134+too big to be a useful demo. The feature-ful version has been spun off
135+into a separate project.
136+
137+* (v2.1.0 is backward-compatible with v2.0.0. I think.)
138+
139+
140+CHANGES in PNGDIB v2.0.0 (vs. 1.x)
141+----------------------------------
142+
143+* WARNING: v2.0 is neither source- nor binary-compatible with v1.x.
144+Compatibility *could* have been done, but frankly I'm not too concerned
145+about it. You shouldn't be using this as a shared library anyway. And you
146+really ought to update your source to use the new transparency features.
147+:-)
148+
149+* Optional transparency and background-color processing when reading PNG
150+images.
151+
152+* Optional gamma correction when reading PNG images.
153+
154+* PNG files that you write are now labeled with a gamma of 0.45455,
155+indicating that they are in the standard sRGB color space, which is
156+(reasonably close to) the color space used by nearly all Windows displays.
157+There's no option to change this value, but it can be turned off
158+completely.
159+
160+* Error messages can now be retrieved by the caller.
161+
162+
163+TO DO
164+-----
165+
166+* Improve this documentation.
167+
168+* Use CreateFile() and related functions instead of fopen(), etc.
169+
170+* Make the transparency processing code less complicated.
171+
172+
173+======================================================================
174+
175+int read_png_to_dib(PNGD_P2DINFO *p2dp)
176+
177+This function takes the filename of an existing PNG file, reads it and
178+converts it into an equivalent Windows Device Independent Bitmap (DIB).
179+
180+USAGE
181+
182+Create a structure of type PNGD_P2DINFO, zero all the fields, then set the
183+fields below as needed.
184+
185+Field Type Value
186+------------ ----------- ------------------------------------------
187+.structsize DWORD Set this to sizeof(PNGD_P2DINFO)
188+
189+.flags DWORD Combination of the following values (see below):
190+ PNGD_USE_BKGD
191+ PNGD_USE_CUSTOM_BG
192+ PNGD_GAMMA_CORRECTION
193+ PNGD_USE_HEAPALLOC
194+ PNGD_DIB_ALPHA32
195+
196+.pngfn char* Pointer to null-terminated filename of the PNG
197+ file to read.
198+
199+.bgcolor PNGD_COLOR_struct
200+ The background color to use when reading the
201+ PNG image (if it includes transparency). You must
202+ set the PNGD_USE_CUSTOM_BG flag for this to be used.
203+ Note that PNGDIB may modify this field (if you
204+ set PNGD_USE_BKGD).
205+
206+.errmsg char* This should point to a buffer of at least 100
207+ characters. If PNGDIB fails, an error message will
208+ be written here. This field can be NULL if you don't
209+ want error messages.
210+
211+.heap HANDLE If you set the PNGD_USE_HEAPALLOC flag, PNGDIB will
212+ use HeapAlloc instead of GlobalAlloc to allocate
213+ memory for the DIB. In that case, you can provide
214+ a handle to the heap to use. If you set this to
215+ NULL, PNGDIB will use the default heap (from
216+ GetProcessHeap).
217+
218+RETURN VALUE
219+
220+Returns 0 on success; returns a nonzero error code on error (see table at
221+end of this document). If there was an error, the values returned in the
222+PNGD_P2DINFO struct are undefined.
223+
224+If successful, the function will set values for some of the fields in your
225+PNGD_P2DINFO structure:
226+
227+
228+FLAGS:
229+
230+PNGD_USE_BKGD
231+
232+If set, PNGDIB will use the PNG file's suggested background color, if it
233+has one.
234+If unset, PNGDIB will ignore any suggested background color in the PNG file.
235+
236+PNGD_USE_CUSTOM_BG
237+
238+If set, indicates that you are providing your own background color in the
239+bgcolor field. If you are intending only to display (rather than edit) the
240+image, it is recommended that you provide a custom background color
241+whenever possible -- otherwise some PNG images may look pretty bad. The
242+color you choose is up to you, and depends on your application. If you
243+have no idea, a gray color may be safer than pure black or white.
244+
245+IMPORTANT: If you set both PNGD_USE_CUSTOM_BG and PNGD_USE_BKGD, the PNG
246+file's suggested background color will be used if it has one. Your custom
247+background color will be used if and only if PNG file does not have a
248+suggested background color.
249+
250+PNGD_GAMMA_CORRECTION
251+
252+If you set this flag, PNGDIB will perform gamma correction when it reads
253+PNG images. It assumes that the resulting DIB image will be in the sRGB
254+color space. Unlabeled PNG images are assumed to be in the sRGB color
255+space. If you do not set this flag, no gamma correction will be done. You
256+should usually turn on this flag, especially if you are intending only to
257+display (rather than edit) the image.
258+
259+PNGD_DIB_ALPHA32
260+
261+If you set this flag, PNGs with transparency will be returned as 32-bpp
262+DIBs with an alpha channel. This is nonstandard, and not recommended
263+unless you know what you are doing. This should probably not be used with
264+PNGD_GAMMA_CORRECTION -- the interaction between these flags is not
265+well-defined.
266+
267+---
268+
269+Fields returned or modified by read_png_to_dib:
270+
271+Field Type Value
272+------------ ----------- ------------------------------------------
273+.flags DWORD The following bits may be set by the function:
274+ PNGD_BG_RETURNED - set if the PNG image was
275+ composited against a background color.
276+ The color used is then returned in the
277+ bgcolor field.
278+ PNGD_RES_RETURNED - set if xres,yres,res_units
279+ fields are valid
280+ PNGD_GAMMA_RETURNED - set if file_gamma is valid
281+
282+.lpdib LPBITMAPINFOHEADER
283+ A pointer to the start of the new DIB in memory.
284+ This might more correctly be of type LPBITMAPINFO,
285+ but that is less convenient most of the time. Cast
286+ its type if necessary. This memory block will
287+ contain the BITMAPINFOHEADER, followed by the
288+ palette (if present), followed by the bitmap bits.
289+ The library will allocate a fixed memory block
290+ using GlobalAlloc (or HeapAlloc, if you used the
291+ PNGD_USE_HEAPALLOC flag). It is your responsibility
292+ to free it with GlobalFree (or HeapFree) when you're
293+ done with it.
294+
295+.dibsize int The size in bytes of the DIB in memory (pointed to
296+ by lpdib).
297+
298+.palette_offs int Integer offset (in bytes) of the palette from the
299+ start of lpdib. This will generally be 40.
300+
301+.bits_offs int Integer offset (in bytes) of the bitmap bits from
302+ the start of lpdib. Calculating
303+ bits_offset-palette_offset will give you the size
304+ of the palette, in bytes.
305+
306+.palette RGBQUAD* Direct pointer to the palette. Note that this
307+ field is redundant and can be calculated from
308+ lpdib and palette_offs.
309+
310+.palette_colors int The number of colors in the palette. This is
311+ generally the same as lpdib->biClrUsed.
312+
313+.lpbits void* Direct pointer to the bitmap bits. Note that this
314+ field is redundant and can be calculated from
315+ lpdib and bits_offs.
316+ This field was accidentally named ".bits" in
317+ PNGDIB version 1.x.
318+
319+.bgcolor PNGD_COLOR_struct
320+ If a background color was used when reading the
321+ image, it will be returned here and the
322+ PNGD_RETURNED_BG flag will be set.
323+
324+.color_type int The color type (based on the PNG spec).
325+.bits_per_sample int Bits per color sample, or per palette entry.
326+.bits_per_pixel int Bits per pixel, or per palette entry.
327+.interlace int >0 if the image was interlaced.
328+.res_x,res_y int X and Y resolution
329+.res_units int 1==resolution is in pixels per meter;
330+ 0==resolution units are unspecified
331+.file_gamma double File gamma (e.g. 0.50000)
332+
333+
334+EXAMPLE
335+
336+See the included file png2bmp.c or smview.c for an example of this function
337+being used.
338+
339+
340+======================================================================
341+
342+int write_dib_to_png(PNGD_D2PINFO *d2pp)
343+
344+USAGE
345+
346+Create a structure of type PNGD_D2PINFO, zero all the fields, then set the
347+fields below as needed.
348+
349+Field Type Value
350+------------ ----------- ------------------------------------------
351+.structsize DWORD Set this to sizeof(PNGD_D2PINFO)
352+
353+.flags DWORD Set to 0 or a combination of:
354+ PNGD_INTERLACE - to write an interlaced PNG image
355+ PNGD_NO_GAMMA_LABEL - to suppress writing a gamma
356+ value to the file
357+ PNGD_DIB_ALPHA32 - if your DIB is 32bpp, treat the
358+ extra 8 bits as an alpha channel.
359+
360+
361+.pngfn char* Pointer to null-terminated filename of the PNG file
362+ to write.
363+
364+.lpdib LPBITMAPINFOHEADER
365+ Set this to point to the start of start of your DIB
366+ [header and palette] in memory.
367+
368+.dibsize int The size in bytes of the data pointed to by lpdib.
369+ This field is optional, and can be set to zero. If
370+ you set it, it may allow better error checking.
371+
372+.lpbits void* Pointer to the start of the bitmap bits in memory.
373+ Most of the time, the bits data in a DIB
374+ immediately follows the header and palette (if
375+ present). If that is the case, you can just set
376+ lpbits to NULL, and the library will find it.
377+
378+.bitssize int The size in bytes of the data pointed to by lpbits.
379+ This field is optional, and can be set to zero. If
380+ you set it, it may allow better error checking.
381+
382+.software char* Pointer to a brief NULL-terminated string
383+ identifying your application. Set to NULL if you
384+ don't want your app to be identified in the PNG
385+ file.
386+
387+.errmsg char* This should point to a buffer of at least 100
388+ characters. If PNGDIB fails, an error message will
389+ be written here. This field can be NULL if you don't
390+ want error messages.
391+
392+RETURN VALUE
393+
394+Returns 0 on success; returns a nonzero error code on error (see table below).
395+
396+
397+EXAMPLE
398+
399+See the included file bmp2png.c for an example of this function being used.
400+
401+
402+======================================================================
403+
404+Table of error codes (from pngdib.h):
405+
406+
407+#define PNGD_E_SUCCESS 0
408+#define PNGD_E_ERROR 1 // unspecified error
409+#define PNGD_E_VERSION 2 // struct size problem
410+#define PNGD_E_NOMEM 3 // could not alloc memory
411+#define PNGD_E_UNSUPP 4 // unsupported image type
412+#define PNGD_E_LIBPNG 5 // libpng error (invalid PNG?)
413+#define PNGD_E_BADBMP 6 // corrupt or unsupported DIB
414+#define PNGD_E_BADPNG 7 // corrupt or unsupported PNG
415+#define PNGD_E_READ 8 // couldn't read PNG file
416+#define PNGD_E_WRITE 9 // couldn't write PNG file
417+
diff -r 000000000000 -r 03757ef47fe3 smview/resource.h
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/smview/resource.h Sat Jan 18 04:17:44 2014 +0000
@@ -0,0 +1,30 @@
1+//{{NO_DEPENDENCIES}}
2+// Microsoft Developer Studio generated include file.
3+// Used by smview.rc
4+//
5+#define IDC_ABOUTINFO 1000
6+#define IDC_TEXT1 1002
7+#define ID_EXIT 40001
8+#define ID_STRETCH 40002
9+#define ID_OPEN 40003
10+#define ID_CLOSE 40004
11+#define ID_ABOUT 40005
12+#define ID_SETBG 40006
13+#define ID_BG_CUSTOM 40008
14+#define ID_BG_BKGD 40010
15+#define ID_GAMMACORRECT 40011
16+#define ID_SAVEASPNG 40012
17+#define ID_SAVEASBMP 40013
18+#define ID_COPY 40014
19+#define ID_IMAGEINFO 40015
20+
21+// Next default values for new objects
22+//
23+#ifdef APSTUDIO_INVOKED
24+#ifndef APSTUDIO_READONLY_SYMBOLS
25+#define _APS_NEXT_RESOURCE_VALUE 106
26+#define _APS_NEXT_COMMAND_VALUE 40016
27+#define _APS_NEXT_CONTROL_VALUE 1003
28+#define _APS_NEXT_SYMED_VALUE 101
29+#endif
30+#endif
diff -r 000000000000 -r 03757ef47fe3 smview/smview.c
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/smview/smview.c Sat Jan 18 04:17:44 2014 +0000
@@ -0,0 +1,384 @@
1+/* Image Viewer Demo
2+ * A really basic PNG image viewer for windows.
3+ * This program is a demonstration of the pngdib library.
4+ * It also requires the libpng and zlib libraries (needed by pngdib).
5+ *
6+ * By Jason Summers
7+ *
8+ * Copyright is hereby disclaimed on this source code.
9+ */
10+
11+#include <windows.h>
12+#include <commdlg.h>
13+#include <stdio.h>
14+#include "resource.h"
15+#include "pngdib.h"
16+
17+#define MYNAME "Simple PNG Image Viewer"
18+#define SMVIEW_VERS "2.2.0"
19+
20+HINSTANCE hInst;
21+LPBITMAPINFOHEADER lpdib;
22+int lpdib_size, lpdib_bits_offs;
23+void *lpbits;
24+int use_bkgd, use_custom_bg;
25+int use_gamma;
26+COLORREF custom_bg, default_bg, image_bg;
27+int which_bg; /* 0==custom or default (depending on use_custom_bg) */
28+ /* 1==image's */
29+char png_filename[MAX_PATH];
30+
31+static COLORREF g_custcolors[16];
32+
33+LRESULT CALLBACK WndProcMain(HWND hwnd,UINT msg,WPARAM wParam,LPARAM lParam);
34+BOOL CALLBACK DlgProcAbout(HWND hwnd,UINT msg,WPARAM wParam,LPARAM lParam);
35+
36+int choose_color_dialog(HWND hwnd, COLORREF *color)
37+{
38+ CHOOSECOLOR cc;
39+
40+ ZeroMemory(&cc,sizeof(CHOOSECOLOR));
41+ cc.lStructSize=sizeof(CHOOSECOLOR);
42+ cc.hwndOwner=hwnd;
43+ cc.rgbResult= *color; /* set initial value */
44+ cc.lpCustColors=g_custcolors;
45+ cc.Flags=CC_RGBINIT|CC_FULLOPEN;
46+
47+ if(ChooseColor(&cc)) {
48+ (*color) = cc.rgbResult;
49+ return 1;
50+ }
51+ return 0;
52+}
53+
54+int open_png_by_name(HWND hwnd, char *fn)
55+{
56+ PNGD_P2DINFO p2d;
57+ char buf[1000];
58+ int ret;
59+ char errmsg[100];
60+
61+ if(!strlen(fn)) {
62+ InvalidateRect(hwnd,NULL,TRUE);
63+ return 0;
64+ }
65+
66+ ZeroMemory((void*)&p2d,sizeof(PNGD_P2DINFO));
67+ p2d.structsize=sizeof(PNGD_P2DINFO);
68+ p2d.pngfn=fn;
69+ p2d.flags |= (use_bkgd?PNGD_USE_BKGD:0)
70+ | (use_custom_bg?PNGD_USE_CUSTOM_BG:0)
71+ | (use_gamma?PNGD_GAMMA_CORRECTION:0)
72+ | PNGD_USE_HEAPALLOC;
73+ p2d.bgcolor.red = GetRValue(custom_bg);
74+ p2d.bgcolor.green = GetGValue(custom_bg);
75+ p2d.bgcolor.blue = GetBValue(custom_bg);
76+ p2d.errmsg=errmsg; strcpy(errmsg,"");
77+ p2d.heap = GetProcessHeap();
78+
79+ ret=read_png_to_dib(&p2d);
80+ if(ret) { /* returns 0 on success */
81+ SetForegroundWindow(hwnd);
82+ sprintf(buf,"Cannot load image: %s (%d)",errmsg,ret);
83+ MessageBox(hwnd,buf,MYNAME,MB_OK|MB_ICONWARNING);
84+ InvalidateRect(hwnd,NULL,TRUE);
85+ return 0;
86+ }
87+
88+ /* get rid of previous image */
89+ if(lpdib) { HeapFree(GetProcessHeap(),0,(LPVOID)lpdib); lpdib=NULL; }
90+
91+ lpdib = p2d.lpdib;
92+ lpdib_size = p2d.dibsize;
93+ lpdib_bits_offs = p2d.bits_offs;
94+ lpbits = p2d.lpbits;
95+
96+ InvalidateRect(hwnd,NULL,TRUE);
97+ strcpy(png_filename,fn);
98+
99+ if(p2d.flags & PNGD_BG_RETURNED) {
100+ image_bg = RGB(p2d.bgcolor.red,p2d.bgcolor.green,p2d.bgcolor.blue);
101+ which_bg=1;
102+ }
103+ else {
104+ which_bg=0;
105+ }
106+
107+ return 1;
108+}
109+
110+int open_png_dialog(HWND hwnd)
111+{
112+ char fn[MAX_PATH];
113+ OPENFILENAME ofn;
114+
115+ strcpy(fn,"");
116+
117+ ZeroMemory(&ofn,sizeof(OPENFILENAME));
118+
119+ ofn.lStructSize=sizeof(OPENFILENAME);
120+ ofn.hwndOwner=hwnd;
121+ ofn.lpstrFilter="PNG image (*.png)\0*.png\0All files\0*.*\0\0";
122+ ofn.nFilterIndex=1;
123+ ofn.lpstrTitle="Open PNG file";
124+
125+ ofn.lpstrInitialDir=NULL;
126+ ofn.lpstrFile=fn;
127+ ofn.nMaxFile=MAX_PATH;
128+ ofn.Flags=OFN_FILEMUSTEXIST|OFN_HIDEREADONLY;
129+
130+ if(!GetOpenFileName(&ofn)) return 0; /* canceled by user */
131+ return open_png_by_name(hwnd,fn);
132+}
133+
134+void dropped_files(HWND hwnd, HDROP hDrop)
135+{
136+ UINT ret;
137+ char fn[MAX_PATH];
138+
139+ ret=DragQueryFile(hDrop,0xFFFFFFFF,NULL,0);
140+ if(ret==1) { /* number of files dropped */
141+ ret=DragQueryFile(hDrop,0,fn,MAX_PATH);
142+ if(ret) open_png_by_name(hwnd,fn);
143+ }
144+ DragFinish(hDrop);
145+}
146+
147+void save_as_png(HWND hwnd)
148+{
149+ PNGD_D2PINFO d2p;
150+ int ret;
151+ OPENFILENAME ofn;
152+ char fn[MAX_PATH];
153+ char errmsg[100];
154+ char buf[200];
155+
156+ strcpy(fn,png_filename);
157+
158+ ZeroMemory(&ofn,sizeof(OPENFILENAME));
159+ ofn.lStructSize=sizeof(OPENFILENAME);
160+ ofn.hwndOwner=hwnd;
161+ ofn.lpstrFilter="PNG image (*.png)\0*.png\0\0";
162+ ofn.nFilterIndex=1;
163+ ofn.lpstrTitle="Save As PNG";
164+
165+ ofn.lpstrInitialDir=NULL;
166+ ofn.lpstrFile=fn;
167+ ofn.nMaxFile=MAX_PATH;
168+ ofn.Flags=OFN_PATHMUSTEXIST|OFN_HIDEREADONLY|OFN_OVERWRITEPROMPT;
169+ ofn.lpstrDefExt="png";
170+
171+ if(!GetSaveFileName(&ofn)) return; /* canceled by user */
172+
173+ ZeroMemory((void*)&d2p,sizeof(PNGD_D2PINFO));
174+
175+ d2p.structsize=sizeof(PNGD_D2PINFO);
176+ d2p.flags=0;
177+ d2p.pngfn=fn;
178+ d2p.lpdib=lpdib;
179+ d2p.dibsize=0;
180+ d2p.lpbits=0;
181+ d2p.bitssize=0;
182+ d2p.software="PNGDIB";
183+ d2p.errmsg = errmsg; strcpy(errmsg,"");
184+
185+ ret=write_dib_to_png(&d2p);
186+ if(ret) {
187+ sprintf(buf,"Cannot save file: %s (%d)",errmsg,ret);
188+ MessageBox(hwnd,buf,MYNAME,MB_OK|MB_ICONWARNING);
189+ }
190+}
191+
192+void init_globals(void)
193+{
194+ lpdib=NULL;
195+ use_bkgd=1; use_custom_bg=1; use_gamma=1;
196+ strcpy(png_filename,"");
197+ default_bg = RGB(255,255,255);
198+ image_bg=default_bg;
199+ custom_bg = RGB(240,240,240);
200+ which_bg=0;
201+ ZeroMemory((void*)g_custcolors,16*sizeof(COLORREF));
202+}
203+
204+int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,
205+ LPSTR lpCmdLine,int nCmdShow)
206+{
207+ MSG msg;
208+ WNDCLASS wc;
209+ HWND hwnd;
210+
211+ init_globals();
212+
213+ hInst=hInstance;
214+ hwnd=NULL;
215+
216+ wc.style = CS_DBLCLKS;
217+ wc.lpfnWndProc = (WNDPROC)WndProcMain;
218+ wc.cbClsExtra = 0;
219+ wc.cbWndExtra = 0;
220+ wc.hInstance = hInst;
221+ wc.hIcon = LoadIcon(hInst,"ICONMAIN");
222+ wc.hCursor = LoadCursor(NULL, IDC_ARROW);
223+ wc.hbrBackground = NULL;
224+ wc.lpszMenuName = "MENUMAIN";
225+ wc.lpszClassName = "SMVIEWCLASS";
226+ if(!RegisterClass(&wc)) return 0;
227+
228+ hwnd = CreateWindow(
229+ "SMVIEWCLASS",MYNAME,
230+ WS_VISIBLE|WS_OVERLAPPEDWINDOW|WS_CLIPCHILDREN,
231+ CW_USEDEFAULT,CW_USEDEFAULT,CW_USEDEFAULT,CW_USEDEFAULT,
232+ NULL,NULL,hInst,NULL);
233+ if (!hwnd) return 0;
234+
235+ DragAcceptFiles(hwnd,TRUE);
236+
237+ while(GetMessage(&msg,NULL,0,0)){
238+ TranslateMessage(&msg);
239+ DispatchMessage(&msg);
240+ }
241+ return (msg.wParam);
242+}
243+
244+LRESULT CALLBACK WndProcMain(HWND hwnd, UINT msg,
245+ WPARAM wParam, LPARAM lParam)
246+{
247+ WORD id;
248+ id=LOWORD(wParam);
249+
250+ switch(msg) {
251+
252+ case WM_ERASEBKGND:
253+ {
254+ HDC hdc;
255+ RECT rect;
256+ HBRUSH oldbr,br;
257+
258+ hdc=(HDC)wParam;
259+ if(!GetClientRect(hwnd,&rect)) return 0;
260+ if(which_bg) {
261+ br=CreateSolidBrush(image_bg);
262+ }
263+ else {
264+ if(use_custom_bg)
265+ br=CreateSolidBrush(custom_bg);
266+ else
267+ br=CreateSolidBrush(default_bg);
268+ }
269+ oldbr=(HBRUSH)SelectObject(hdc,br);
270+ FillRect(hdc,&rect,br);
271+ SelectObject(hdc,oldbr);
272+ DeleteObject(br);
273+ }
274+ return 1;
275+
276+ case WM_PAINT:
277+ {
278+ PAINTSTRUCT paintStruct;
279+ HDC hdc;
280+
281+ hdc = BeginPaint( hwnd, &paintStruct );
282+ if(lpdib) {
283+ StretchDIBits(hdc,
284+ 0,0,lpdib->biWidth,lpdib->biHeight,
285+ 0,0,lpdib->biWidth,lpdib->biHeight,
286+ lpbits,(LPBITMAPINFO)lpdib,
287+ DIB_RGB_COLORS,SRCCOPY);
288+ }
289+ EndPaint(hwnd, &paintStruct);
290+ return 0;
291+ }
292+
293+ case WM_DESTROY:
294+ if(lpdib) { HeapFree(GetProcessHeap(),0,(LPVOID)lpdib); lpdib=NULL; }
295+ PostQuitMessage(0);
296+ return 0;
297+
298+ case WM_DROPFILES:
299+ dropped_files(hwnd, (HDROP)wParam);
300+ return 0;
301+
302+ case WM_INITMENU:
303+ CheckMenuItem((HMENU)wParam, ID_BG_BKGD , MF_BYCOMMAND|
304+ (use_bkgd?MF_CHECKED:MF_UNCHECKED) );
305+ CheckMenuItem((HMENU)wParam, ID_BG_CUSTOM , MF_BYCOMMAND|
306+ (use_custom_bg?MF_CHECKED:MF_UNCHECKED) );
307+ CheckMenuItem((HMENU)wParam, ID_GAMMACORRECT , MF_BYCOMMAND|
308+ (use_gamma?MF_CHECKED:MF_UNCHECKED) );
309+ EnableMenuItem((HMENU)wParam, ID_CLOSE, MF_BYCOMMAND|
310+ (lpdib?MF_ENABLED:MF_GRAYED) );
311+ EnableMenuItem((HMENU)wParam, ID_SAVEASPNG, MF_BYCOMMAND|
312+ (lpdib?MF_ENABLED:MF_GRAYED) );
313+ EnableMenuItem((HMENU)wParam, ID_SAVEASBMP, MF_BYCOMMAND|
314+ (lpdib?MF_ENABLED:MF_GRAYED) );
315+ return 0;
316+
317+ case WM_COMMAND:
318+ switch(id) {
319+ case ID_EXIT:
320+ DestroyWindow(hwnd);
321+ return 0;
322+ case ID_OPEN:
323+ open_png_dialog(hwnd);
324+ return 0;
325+ case ID_SAVEASPNG:
326+ if(lpdib) save_as_png(hwnd);
327+ return 0;
328+ case ID_CLOSE:
329+ if(lpdib) { HeapFree(GetProcessHeap(),0,(LPVOID)lpdib); lpdib=NULL; }
330+ strcpy(png_filename,"");
331+ which_bg=0;
332+ InvalidateRect(hwnd,NULL,TRUE);
333+ return 0;
334+ case ID_BG_BKGD:
335+ use_bkgd = !use_bkgd;
336+ open_png_by_name(hwnd,png_filename); /* reload image */
337+ return 0;
338+ case ID_BG_CUSTOM:
339+ use_custom_bg = !use_custom_bg;
340+ open_png_by_name(hwnd,png_filename);
341+ return 0;
342+ case ID_GAMMACORRECT:
343+ use_gamma = !use_gamma;
344+ open_png_by_name(hwnd,png_filename);
345+ return 0;
346+ case ID_SETBG:
347+ if(choose_color_dialog(hwnd,&custom_bg)) {
348+ open_png_by_name(hwnd,png_filename);
349+ }
350+ return 0;
351+ case ID_ABOUT:
352+ DialogBox(hInst,"ABOUTDLG",hwnd,DlgProcAbout);
353+ return 0;
354+ }
355+ break;
356+ }
357+ return (DefWindowProc(hwnd, msg, wParam, lParam));
358+}
359+
360+BOOL CALLBACK DlgProcAbout(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
361+{
362+ WORD id;
363+ char buf[1000];
364+ id=LOWORD(wParam);
365+
366+ switch (msg) {
367+
368+ case WM_INITDIALOG:
369+ sprintf(buf,"Demonstration PNG image viewer that uses the PNGDIB library.\r\n"
370+ "Version %s\r\nBy Jason Summers, 8/2000-4/2002\r\nPNGDIB version %s",
371+ SMVIEW_VERS,pngdib_get_version_string());
372+ SetDlgItemText(hwnd,IDC_TEXT1,buf);
373+
374+ return 1;
375+ case WM_COMMAND:
376+ switch(id) {
377+ case IDOK:
378+ case IDCANCEL:
379+ EndDialog(hwnd, 0);
380+ return 1;
381+ }
382+ }
383+ return 0;
384+}
diff -r 000000000000 -r 03757ef47fe3 smview/smview.ico
Binary file smview/smview.ico has changed
diff -r 000000000000 -r 03757ef47fe3 smview/smview.rc
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/smview/smview.rc Sat Jan 18 04:17:44 2014 +0000
@@ -0,0 +1,136 @@
1+//Microsoft Developer Studio generated resource script.
2+//
3+#include "resource.h"
4+
5+#define APSTUDIO_READONLY_SYMBOLS
6+/////////////////////////////////////////////////////////////////////////////
7+//
8+// Generated from the TEXTINCLUDE 2 resource.
9+//
10+#include "afxres.h"
11+
12+/////////////////////////////////////////////////////////////////////////////
13+#undef APSTUDIO_READONLY_SYMBOLS
14+
15+/////////////////////////////////////////////////////////////////////////////
16+// English (U.S.) resources
17+
18+#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ENU)
19+#ifdef _WIN32
20+LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US
21+#pragma code_page(1252)
22+#endif //_WIN32
23+
24+#ifdef APSTUDIO_INVOKED
25+/////////////////////////////////////////////////////////////////////////////
26+//
27+// TEXTINCLUDE
28+//
29+
30+1 TEXTINCLUDE DISCARDABLE
31+BEGIN
32+ "resource.h\0"
33+END
34+
35+2 TEXTINCLUDE DISCARDABLE
36+BEGIN
37+ "#include ""afxres.h""\r\n"
38+ "\0"
39+END
40+
41+3 TEXTINCLUDE DISCARDABLE
42+BEGIN
43+ "\r\n"
44+ "\0"
45+END
46+
47+#endif // APSTUDIO_INVOKED
48+
49+
50+/////////////////////////////////////////////////////////////////////////////
51+//
52+// Menu
53+//
54+
55+MENUMAIN MENU DISCARDABLE
56+BEGIN
57+ POPUP "&File"
58+ BEGIN
59+ MENUITEM "&Open...", ID_OPEN
60+ MENUITEM "Save &As...", ID_SAVEASPNG
61+ MENUITEM "&Close", ID_CLOSE
62+ MENUITEM SEPARATOR
63+ MENUITEM "E&xit", ID_EXIT
64+ END
65+ POPUP "&Options"
66+ BEGIN
67+ MENUITEM "&Gamma Correction", ID_GAMMACORRECT
68+ MENUITEM SEPARATOR
69+ MENUITEM "Use &Image's Background Color", ID_BG_BKGD
70+ MENUITEM "Use &Custom Background Color", ID_BG_CUSTOM
71+ MENUITEM SEPARATOR
72+ MENUITEM "Set Custom &Background Color...", ID_SETBG
73+ END
74+ POPUP "&Help"
75+ BEGIN
76+ MENUITEM "&About...", ID_ABOUT
77+ END
78+END
79+
80+
81+/////////////////////////////////////////////////////////////////////////////
82+//
83+// Icon
84+//
85+
86+// Icon with lowest ID value placed first to ensure application icon
87+// remains consistent on all systems.
88+ICONMAIN ICON DISCARDABLE "smview.ico"
89+
90+/////////////////////////////////////////////////////////////////////////////
91+//
92+// Dialog
93+//
94+
95+ABOUTDLG DIALOG DISCARDABLE 0, 0, 236, 63
96+STYLE DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU
97+CAPTION "Simple PNG Image Viewer"
98+FONT 8, "MS Sans Serif"
99+BEGIN
100+ DEFPUSHBUTTON "OK",IDOK,179,7,50,14
101+ LTEXT "",IDC_TEXT1,7,7,167,49
102+END
103+
104+
105+/////////////////////////////////////////////////////////////////////////////
106+//
107+// DESIGNINFO
108+//
109+
110+#ifdef APSTUDIO_INVOKED
111+GUIDELINES DESIGNINFO DISCARDABLE
112+BEGIN
113+ "ABOUTDLG", DIALOG
114+ BEGIN
115+ LEFTMARGIN, 7
116+ RIGHTMARGIN, 229
117+ TOPMARGIN, 7
118+ END
119+END
120+#endif // APSTUDIO_INVOKED
121+
122+#endif // English (U.S.) resources
123+/////////////////////////////////////////////////////////////////////////////
124+
125+
126+
127+#ifndef APSTUDIO_INVOKED
128+/////////////////////////////////////////////////////////////////////////////
129+//
130+// Generated from the TEXTINCLUDE 3 resource.
131+//
132+
133+
134+/////////////////////////////////////////////////////////////////////////////
135+#endif // not APSTUDIO_INVOKED
136+
Afficher sur ancien navigateur de dépôt.