-
Notifications
You must be signed in to change notification settings - Fork 3
/
PngWriter.hpp
149 lines (115 loc) · 4.29 KB
/
PngWriter.hpp
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
#ifndef PNG_WRITER_HPP
#define PNG_WRITER_HPP
// ======================================================================
// PngWriter.hpp
//
// This class can write a png image using libpng routines (i.e. png.h).
//
// Sample usage:
//
// PngWriter png(nx,ny);
//
// // then one or more calls to...
//
// png.set(i, j, red, green, blue); // 0 <= red,green,blue <= 255
//
// png.write("myfile.png");
//
// // at this point you can change the image and write again...
//
// png.set(i, j, red, green, blue);
//
// png.write("myfile2.png");
//
//
// History:
// authors: Frank Ham & Phuc Quang - July 2013
// ======================================================================
// ======================================================================
// Copyright (c) 2013 Frank Ham and Phuc Quang
//
// License: MIT (http://opensource.org/licenses/MIT)
//
// use for any purpose, commercial or otherwise.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
// ======================================================================
#include <png.h>
class PngWriter {
private:
unsigned char (*buffer)[3]; // 0 <= r,g,b < 255
int nx,ny;
public:
PngWriter(const int width,const int height) {
nx = width;
ny = height;
buffer = new unsigned char[nx*ny][3];
// fill buffer with a "nice" cyan [73,175,205] -- eventually a designer should choose this ;)
for (int i = 0; i < nx*ny; ++i) {
buffer[i][0] = 73;
buffer[i][1] = 175;
buffer[i][2] = 205;
}
}
~PngWriter() {
delete[] buffer;
}
void set(const int i,const int j,const unsigned char r,const unsigned char g,const unsigned char b) {
// recall that for png files, the pixels are ordered from the top left, so modify
// this set routine's passed j so that zero is at the bottom left...
buffer[(ny-j-1)*nx+i][0] = r;
buffer[(ny-j-1)*nx+i][1] = g;
buffer[(ny-j-1)*nx+i][2] = b;
}
void write(const char * filename) {
// note: we completely skip any error handling treatment here for simplicity.
FILE * fp = fopen(filename,"wb");
if (!fp) {
std::cout << "Warning: could not open png file: " << filename << std::endl;
return;
}
png_structp png_ptr = png_create_write_struct(PNG_LIBPNG_VER_STRING,
(png_voidp)NULL,NULL,NULL);
if (!png_ptr) {
fclose(fp);
std::cout << "Warning: could not create png_ptr" << std::endl;
return;
}
png_infop info_ptr = png_create_info_struct(png_ptr);
if (!info_ptr) {
png_destroy_write_struct(&png_ptr,(png_infopp)NULL);
std::cout << "Warning: could not create info_ptr" << std::endl;
return;
}
png_init_io(png_ptr, fp);
png_set_IHDR(png_ptr, info_ptr,
nx, ny, // width, height
8, // bits per pixel -- 16 does not work with blockbuster
PNG_COLOR_TYPE_RGB, // non-alpha options are PNG_COLOR_TYPE_RGB,PNG_COLOR_TYPE_GRAY,
PNG_INTERLACE_NONE,
PNG_COMPRESSION_TYPE_DEFAULT,
PNG_FILTER_TYPE_DEFAULT);
// Some bits per pixel notes: 16 does not work with blockbuster, and there are also
// issues with PNG_COLOR_TYPE_GRAY interpretation, so stick to 8 and PNG_COLOR_TYPE_RGB
// for now. Note that if you do use 16, pay attention to MSB/LSB order. Endian is
// flipped on my linux workstation...
png_write_info(png_ptr, info_ptr);
// set up row pointers to point into the raw image data in buffer...
png_byte * row_pointers[ny];
for (int i = 0; i < ny; ++i)
row_pointers[i] = (png_byte*)(buffer + i*nx);
png_write_image(png_ptr, row_pointers);
png_write_end(png_ptr, NULL);
png_destroy_write_struct(&png_ptr, &info_ptr);
fclose(fp);
// leave the image data in buffer to allow the calling process to change it and/or
// write another image. It is deleted in the destructor.
}
};
#endif