]> git.cworth.org Git - apitrace/blob - image/image_png.cpp
d3dretrace: Force DWM traces to run on a window.
[apitrace] / image / image_png.cpp
1 /**************************************************************************
2  *
3  * Copyright 2011 Jose Fonseca
4  * Copyright 2008-2010 VMware, Inc.
5  * All Rights Reserved.
6  *
7  * Permission is hereby granted, free of charge, to any person obtaining a copy
8  * of this software and associated documentation files (the "Software"), to deal
9  * in the Software without restriction, including without limitation the rights
10  * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
11  * copies of the Software, and to permit persons to whom the Software is
12  * furnished to do so, subject to the following conditions:
13  *
14  * The above copyright notice and this permission notice shall be included in
15  * all copies or substantial portions of the Software.
16  *
17  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
20  * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
21  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
22  * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
23  * THE SOFTWARE.
24  *
25  **************************************************************************/
26
27
28 #include <zlib.h>
29 #include <png.h>
30
31 #include <assert.h>
32 #include <stdint.h>
33 #include <stdlib.h>
34
35 #include <fstream>
36
37 #include "image.hpp"
38
39
40 namespace image {
41
42
43 static const int png_compression_level = Z_BEST_SPEED;
44
45
46 static void
47 pngWriteCallback(png_structp png_ptr, png_bytep data, png_size_t length)
48 {
49     std::ostream *os = (std::ostream *) png_get_io_ptr(png_ptr);
50     os->write((const char *)data, length);
51 }
52
53 bool
54 Image::writePNG(std::ostream &os) const
55 {
56     png_structp png_ptr;
57     png_infop info_ptr;
58     int color_type;
59
60     switch (channels) {
61     case 4:
62         color_type = PNG_COLOR_TYPE_RGB_ALPHA;
63         break;
64     case 3:
65         color_type = PNG_COLOR_TYPE_RGB;
66         break;
67     case 2:
68         color_type = PNG_COLOR_TYPE_GRAY_ALPHA;
69         break;
70     case 1:
71         color_type = PNG_COLOR_TYPE_GRAY;
72         break;
73     default:
74         assert(0);
75         goto no_png;
76     }
77
78     png_ptr = png_create_write_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL);
79     if (!png_ptr)
80         goto no_png;
81
82     info_ptr = png_create_info_struct(png_ptr);
83     if (!info_ptr) {
84         png_destroy_write_struct(&png_ptr,  NULL);
85         goto no_png;
86     }
87
88     if (setjmp(png_jmpbuf(png_ptr))) {
89         png_destroy_write_struct(&png_ptr, &info_ptr);
90         goto no_png;
91     }
92
93     png_set_write_fn(png_ptr, &os, pngWriteCallback, NULL);
94
95     png_set_IHDR(png_ptr, info_ptr, width, height, 8,
96                  color_type, PNG_INTERLACE_NONE,
97                  PNG_COMPRESSION_TYPE_BASE, PNG_FILTER_TYPE_BASE);
98
99     png_set_compression_level(png_ptr, png_compression_level);
100
101     png_write_info(png_ptr, info_ptr);
102
103     if (!flipped) {
104         for (unsigned y = 0; y < height; ++y) {
105             png_bytep row = (png_bytep)(pixels + y*width*channels);
106             png_write_rows(png_ptr, &row, 1);
107         }
108     } else {
109         unsigned y = height;
110         while (y--) {
111             png_bytep row = (png_bytep)(pixels + y*width*channels);
112             png_write_rows(png_ptr, &row, 1);
113         }
114     }
115
116     png_write_end(png_ptr, info_ptr);
117     png_destroy_write_struct(&png_ptr, &info_ptr);
118
119     return true;
120
121 no_png:
122     return false;
123 }
124
125
126 Image *
127 readPNG(const char *filename)
128 {
129     FILE *fp;
130     png_structp png_ptr;
131     png_infop info_ptr;
132     png_infop end_info;
133     Image *image;
134
135     fp = fopen(filename, "rb");
136     if (!fp)
137         goto no_fp;
138
139     png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL);
140     if (!png_ptr)
141         goto no_png;
142
143     info_ptr = png_create_info_struct(png_ptr);
144     if (!info_ptr) {
145         png_destroy_read_struct(&png_ptr, NULL, NULL);
146         goto no_png;
147     }
148
149     end_info = png_create_info_struct(png_ptr);
150     if (!end_info) {
151         png_destroy_read_struct(&png_ptr, &info_ptr, NULL);
152         goto no_png;
153     }
154
155     if (setjmp(png_jmpbuf(png_ptr))) {
156         png_destroy_read_struct(&png_ptr, &info_ptr, &end_info);
157         goto no_png;
158     }
159
160     png_init_io(png_ptr, fp);
161
162     png_read_info(png_ptr, info_ptr);
163
164     png_uint_32 width, height;
165     int bit_depth, color_type, interlace_type, compression_type, filter_method;
166
167     png_get_IHDR(png_ptr, info_ptr,
168                  &width, &height,
169                  &bit_depth, &color_type, &interlace_type,
170                  &compression_type, &filter_method);
171
172     image = new Image(width, height);
173     if (!image)
174         goto no_image;
175
176     /* Convert to RGBA8 */
177     if (color_type == PNG_COLOR_TYPE_PALETTE)
178         png_set_palette_to_rgb(png_ptr);
179     if (color_type == PNG_COLOR_TYPE_GRAY && bit_depth < 8)
180         png_set_expand_gray_1_2_4_to_8(png_ptr);
181     if (png_get_valid(png_ptr, info_ptr, PNG_INFO_tRNS))
182         png_set_tRNS_to_alpha(png_ptr);
183     if (bit_depth == 16)
184         png_set_strip_16(png_ptr);
185
186     for (unsigned y = 0; y < height; ++y) {
187         png_bytep row = (png_bytep)(image->pixels + y*width*4);
188         png_read_row(png_ptr, row, NULL);
189     }
190
191     png_read_end(png_ptr, info_ptr);
192     png_destroy_read_struct(&png_ptr, &info_ptr, &end_info);
193     fclose(fp);
194     return image;
195
196 no_image:
197     png_destroy_read_struct(&png_ptr, &info_ptr, &end_info);
198 no_png:
199     fclose(fp);
200 no_fp:
201     return NULL;
202 }
203
204
205
206 } /* namespace image */