]> git.cworth.org Git - apitrace/blob - image.cpp
Write PNG images instead.
[apitrace] / image.cpp
1 /**************************************************************************
2  *
3  * Copyright 2008-2010 VMware, Inc.
4  * All Rights Reserved.
5  *
6  * Permission is hereby granted, free of charge, to any person obtaining a copy
7  * of this software and associated documentation files (the "Software"), to deal
8  * in the Software without restriction, including without limitation the rights
9  * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10  * copies of the Software, and to permit persons to whom the Software is
11  * furnished to do so, subject to the following conditions:
12  *
13  * The above copyright notice and this permission notice shall be included in
14  * all copies or substantial portions of the Software.
15  *
16  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19  * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21  * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
22  * THE SOFTWARE.
23  *
24  **************************************************************************/
25
26
27 #include <png.h>
28
29 #include <stdint.h>
30
31 #include <fstream>
32
33 #include "image.hpp"
34
35
36 namespace Image {
37
38
39 #pragma pack(push,2)
40 struct FileHeader {
41     uint16_t bfType;
42     uint32_t bfSize;
43     uint16_t bfReserved1;
44     uint16_t bfReserved2;
45     uint32_t bfOffBits;
46 };
47 #pragma pack(pop)
48
49 struct InfoHeader {
50     uint32_t biSize;
51     int32_t biWidth;
52     int32_t biHeight;
53     uint16_t biPlanes;
54     uint16_t biBitCount;
55     uint32_t biCompression;
56     uint32_t biSizeImage;
57     int32_t biXPelsPerMeter;
58     int32_t biYPelsPerMeter;
59     uint32_t biClrUsed;
60     uint32_t biClrImportant;
61 };
62
63 struct Pixel {
64     uint8_t rgbBlue;
65     uint8_t rgbGreen;
66     uint8_t rgbRed;
67     uint8_t rgbAlpha;
68 };
69
70
71 bool
72 Image::writeBMP(const char *filename) const {
73     struct FileHeader bmfh;
74     struct InfoHeader bmih;
75     unsigned x, y;
76
77     bmfh.bfType = 0x4d42;
78     bmfh.bfSize = 14 + 40 + height*width*4;
79     bmfh.bfReserved1 = 0;
80     bmfh.bfReserved2 = 0;
81     bmfh.bfOffBits = 14 + 40;
82
83     bmih.biSize = 40;
84     bmih.biWidth = width;
85     bmih.biHeight = height;
86     bmih.biPlanes = 1;
87     bmih.biBitCount = 32;
88     bmih.biCompression = 0;
89     bmih.biSizeImage = height*width*4;
90     bmih.biXPelsPerMeter = 0;
91     bmih.biYPelsPerMeter = 0;
92     bmih.biClrUsed = 0;
93     bmih.biClrImportant = 0;
94
95     std::ofstream stream(filename, std::ofstream::binary);
96
97     if (!stream)
98         return false;
99
100     stream.write((const char *)&bmfh, 14);
101     stream.write((const char *)&bmih, 40);
102
103     unsigned stride = width*4;
104
105     if (flipped) {
106         for (y = 0; y < height; ++y) {
107             const unsigned char *ptr = pixels + y * stride;
108             for (x = 0; x < width; ++x) {
109                 struct Pixel pixel;
110                 pixel.rgbRed   = ptr[x*4 + 0];
111                 pixel.rgbGreen = ptr[x*4 + 1];
112                 pixel.rgbBlue  = ptr[x*4 + 2];
113                 pixel.rgbAlpha = ptr[x*4 + 3];
114                 stream.write((const char *)&pixel, 4);
115             }
116         }
117     } else {
118         y = height;
119         while (y--) {
120             const unsigned char *ptr = pixels + y * stride;
121             for (x = 0; x < width; ++x) {
122                 struct Pixel pixel;
123                 pixel.rgbRed   = ptr[x*4 + 0];
124                 pixel.rgbGreen = ptr[x*4 + 1];
125                 pixel.rgbBlue  = ptr[x*4 + 2];
126                 pixel.rgbAlpha = ptr[x*4 + 3];
127                 stream.write((const char *)&pixel, 4);
128             }
129         }
130     }
131
132     stream.close();
133
134     return true;
135 }
136
137 bool
138 Image::writePNG(const char *filename) const {
139     FILE *fp;
140     png_structp png_ptr;
141     png_infop info_ptr;
142
143     /* Open the file */
144     fp = fopen(filename, "wb");
145     if (!fp)
146         goto no_fp;
147
148     /* Create and initialize the png_struct with the desired error handler
149      * functions.  If you want to use the default stderr and longjump method,
150      * you can supply NULL for the last three parameters.  We also check that
151      * the library version is compatible with the one used at compile time,
152      * in case we are using dynamically linked libraries.  REQUIRED.
153      */
154     png_ptr = png_create_write_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL);
155     if (!png_ptr)
156         goto no_png;
157
158     /* Allocate/initialize the image information data.  REQUIRED */
159     info_ptr = png_create_info_struct(png_ptr);
160     if (!info_ptr) {
161         png_destroy_write_struct(&png_ptr,  NULL);
162         goto no_png;
163     }
164
165     /* Set error handling.  REQUIRED if you aren't supplying your own
166      * error handling functions in the png_create_write_struct() call.
167      */
168     if (setjmp(png_jmpbuf(png_ptr))) {
169         png_destroy_write_struct(&png_ptr, &info_ptr);
170         goto no_png;
171     }
172
173 #if 1
174     png_init_io(png_ptr, fp);
175 #else
176     png_set_write_fn(png_ptr, (void *)user_io_ptr, user_write_fn,
177         user_IO_flush_function);
178 #endif
179
180     png_set_IHDR(png_ptr, info_ptr, width, height, 8, PNG_COLOR_TYPE_RGB_ALPHA,
181         PNG_INTERLACE_NONE, PNG_COMPRESSION_TYPE_BASE, PNG_FILTER_TYPE_BASE);
182
183     png_set_compression_level(png_ptr, Z_BEST_COMPRESSION);
184
185     png_write_info(png_ptr, info_ptr);
186
187     if (!flipped) {
188         for (unsigned y = 0; y < height; ++y) {
189             png_byte *row = (png_byte *)(pixels + y*width*4);
190             png_write_rows(png_ptr, &row, 1);
191         }
192     } else {
193         unsigned y = height;
194         while (y--) {
195             png_byte *row = (png_byte *)(pixels + y*width*4);
196             png_write_rows(png_ptr, &row, 1);
197         }
198     }
199
200     png_write_end(png_ptr, info_ptr);
201     png_destroy_write_struct(&png_ptr, &info_ptr);
202
203     fclose(fp);
204     return true;
205
206 no_png:
207     fclose(fp);
208 no_fp:
209     return false;
210 }
211
212 } /* namespace Image */