-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathPngwrite.h
154 lines (126 loc) · 3.18 KB
/
Pngwrite.h
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
#ifndef __PNGWRITE_INCLUDED__
#define __PNGWRITE_INCLUDED__
#include <stdio.h>
#include <stdlib.h>
#include "zlib.h"
#include "typedef.h"
#include "macro.h"
class PNGWRITE
{
public:
bool Write( const char* fname, INT nWidth, INT nHeight, RGBQUAD* pRGB, LPBYTE lpBitmap, DWORD dwScan )
{
FILE* fp = NULL;
LPBYTE pBits = NULL;
LPBYTE pZbuf = NULL;
unsigned long zlibbuffersize;
INT i;
if( !(fp = ::fopen( fname, "wb" )) )
goto error_exit;
if( !WriteSignature( fp ) )
goto error_exit;
if( !(pBits = (LPBYTE)::malloc( (nWidth+1)*nHeight*sizeof(BYTE) )) )
goto error_exit;
LPBYTE pSrc, pDst;
pSrc = lpBitmap;
pDst = pBits;
// No Filter
for( i = 0; i < nHeight; i++ ) {
*(pDst++) = 0;
::memcpy( pDst, pSrc, nWidth );
pSrc += dwScan;
pDst += nWidth;
}
zlibbuffersize = ((nWidth+1)*nHeight)*1.1+12;
if( !(pZbuf = (LPBYTE)::malloc( zlibbuffersize )) )
goto error_exit;
if( compress( pZbuf, &zlibbuffersize, pBits, ((nWidth+1)*nHeight) ) != Z_OK )
goto error_exit;
// write IHDR
{
BYTE temp[13];
// Write Length
ConvertNetworkOrder( nWidth, temp );
ConvertNetworkOrder( nHeight, temp+4 );
*(temp+ 8) = 8; // 8bpp
*(temp+ 9) = 3; // Indexed color
*(temp+10) = 0; // Compression method
*(temp+11) = 0; // Filter method
*(temp+12) = 0; // Interace method
if( !WriteChunk( fp, PNG_CHUNK_IHDR, temp, 13 ) )
goto error_exit;
}
// write PLTE
{
BYTE pal[256*3];
for( INT i = 0; i < 256; i++ ) {
pal[i*3+0] = pRGB[i].rgbRed;
pal[i*3+1] = pRGB[i].rgbGreen;
pal[i*3+2] = pRGB[i].rgbBlue;
}
if( !WriteChunk( fp, PNG_CHUNK_PLTE, pal, 256*3 ) )
goto error_exit;
}
// write IDAT
if( !WriteChunk( fp, PNG_CHUNK_IDAT, pZbuf, zlibbuffersize ) )
goto error_exit;
// write IEND
if( !WriteChunk( fp, PNG_CHUNK_IEND, NULL, 0 ) )
goto error_exit;
FREE( pBits );
FREE( pZbuf );
FCLOSE( fp );
return true;
error_exit:
FREE( pBits );
FREE( pZbuf );
FCLOSE( fp );
return false;
}
protected:
void ConvertNetworkOrder( UINT uData, BYTE* pBuf )
{
pBuf[0] = (BYTE)(uData>>24);
pBuf[1] = (BYTE)(uData>>16);
pBuf[2] = (BYTE)(uData>>8);
pBuf[3] = (BYTE)(uData);
}
bool WriteSignature( FILE* fp )
{
const char PNG_SIGNATURE[] = { "\x89\x50\x4E\x47\x0D\x0A\x1A\x0A" };
if( ::fwrite( PNG_SIGNATURE, 8, 1, fp ) != 1 )
return false;
return true;
}
bool WriteChunk( FILE* fp, UINT uType, BYTE* pData, UINT uLength )
{
BYTE temp[4];
// Write Length
ConvertNetworkOrder( uLength, temp );
if( ::fwrite( temp, sizeof(temp), 1, fp ) != 1 )
return false;
// Write Chunk Type
ConvertNetworkOrder( uType, temp );
if( ::fwrite( temp, sizeof(temp), 1, fp ) != 1 )
return false;
UINT crc = crc32( 0, temp, sizeof(temp) );
if( uLength ) {
if( ::fwrite( pData, uLength, 1, fp ) != 1 )
return false;
crc = crc32( crc, pData, uLength );
}
// Write CRC32
ConvertNetworkOrder( crc, temp );
if( ::fwrite( temp, sizeof(temp), 1, fp ) != 1 )
return false;
return true;
}
private:
enum {
PNG_CHUNK_IHDR = 0x49484452,
PNG_CHUNK_PLTE = 0x504C5445,
PNG_CHUNK_IDAT = 0x49444154,
PNG_CHUNK_IEND = 0x49454E44,
};
};
#endif // !__PNGWRITE_INCLUDED__