]> Dogcows Code - chaz/yoink/blob - src/Moof/Image.cc
simplified win32 installer build script
[chaz/yoink] / src / Moof / Image.cc
1
2 /*******************************************************************************
3
4 Copyright (c) 2009, Charles McGarvey
5 All rights reserved.
6
7 Redistribution and use in source and binary forms, with or without
8 modification, are permitted provided that the following conditions are met:
9
10 * Redistributions of source code must retain the above copyright notice,
11 this list of conditions and the following disclaimer.
12 * Redistributions in binary form must reproduce the above copyright notice,
13 this list of conditions and the following disclaimer in the documentation
14 and/or other materials provided with the distribution.
15
16 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
17 AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
18 IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
19 DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
20 FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
21 DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
22 SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
23 CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
24 OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
25 OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26
27 *******************************************************************************/
28
29 #include <cstdio> // FILE
30 #include <cstring> // strncmp
31
32 #include <SDL/SDL.h>
33 #include <png.h>
34
35 #include "Image.hh"
36 #include "Library.hh"
37 #include "Log.hh"
38
39
40 namespace Mf {
41
42
43 class Image::Impl : public Library<Impl>
44 {
45 public:
46
47 explicit Impl(const std::string& name, bool flipped = false) :
48 Library<Impl>(name),
49 mContext(0),
50 mPixels(0)
51 {
52 init(getName(), flipped);
53 }
54
55 ~Impl()
56 {
57 SDL_FreeSurface(mContext);
58 delete[] mPixels;
59 }
60
61
62 void flip()
63 {
64 unsigned char* pixels = (Uint8*)(mContext->pixels);
65
66 unsigned pitch = mContext->pitch;
67 unsigned char line[pitch];
68
69 int yBegin = 0;
70 int yEnd = mContext->h - 1;
71
72 if (SDL_MUSTLOCK(mContext)) SDL_LockSurface(mContext);
73 while (yBegin < yEnd)
74 {
75 memcpy(line, pixels + pitch * yBegin, pitch);
76 memcpy(pixels + pitch * yBegin, pixels + pitch * yEnd, pitch);
77 memcpy(pixels + pitch * yEnd, line, pitch);
78 yBegin++;
79 yEnd--;
80 }
81 if (SDL_MUSTLOCK(mContext)) SDL_UnlockSurface(mContext);
82 }
83
84 void setAsIcon() const
85 {
86 SDL_WM_SetIcon(mContext, 0);
87 }
88
89
90 SDL_Surface* mContext;
91 char* mPixels;
92
93 unsigned mDepth;
94 GLuint mColorMode;
95
96 std::string mComment;
97
98
99 private:
100
101 bool init(const std::string& filePath, bool flipped)
102 {
103 logInfo("opening image file...");
104 FILE* fp = fopen(filePath.c_str(), "rb");
105 if (!fp) return false;
106
107 png_byte signature[8];
108 size_t bytesRead;
109
110 png_infop pngInfo = 0;
111 png_infop pngInfoEnd = 0;
112 png_structp pngObj = 0;
113
114 int width;
115 int height;
116 int pitch;
117 int bpp;
118 int channels;
119
120 png_byte colors;
121 png_bytepp rows = 0;
122
123 png_textp texts = 0;
124 int numTexts;
125
126 logInfo("checking signature...");
127 bytesRead = fread(signature, 1, sizeof(signature), fp);
128 logInfo << "reading " << bytesRead << " bytes of signature" << std::endl;
129 if (bytesRead < sizeof(signature) ||
130 png_sig_cmp(signature, 0, sizeof(signature)) != 0) goto cleanup;
131
132 logInfo("creating png structures...");
133 pngObj = png_create_read_struct(PNG_LIBPNG_VER_STRING, 0, 0, 0);
134 if (!pngObj) goto cleanup;
135
136 pngInfo = png_create_info_struct(pngObj);
137 if (!pngInfo) goto cleanup;
138
139 pngInfoEnd = png_create_info_struct(pngObj);
140 if (!pngInfoEnd) goto cleanup;
141
142 logInfo("setting up long jump...");
143 if (setjmp(png_jmpbuf(pngObj))) goto cleanup;
144
145 png_init_io(pngObj, fp);
146 png_set_sig_bytes(pngObj, sizeof(signature));
147 png_read_info(pngObj, pngInfo);
148
149 bpp = png_get_bit_depth(pngObj, pngInfo);
150 logInfo << "texture bpp: " << bpp << std::endl;
151 colors = png_get_color_type(pngObj, pngInfo);
152 switch (colors)
153 {
154 case PNG_COLOR_TYPE_PALETTE:
155 png_set_palette_to_rgb(pngObj);
156 break;
157
158 case PNG_COLOR_TYPE_GRAY:
159 if (bpp < 8) png_set_gray_1_2_4_to_8(pngObj);
160 break;
161
162 case PNG_COLOR_TYPE_GRAY_ALPHA:
163 png_set_gray_to_rgb(pngObj);
164 break;
165 }
166
167 if (bpp == 16) png_set_strip_16(pngObj);
168
169 png_read_update_info(pngObj, pngInfo);
170
171 bpp = png_get_bit_depth(pngObj, pngInfo);
172 channels = png_get_channels(pngObj, pngInfo);
173 mDepth = bpp * channels;
174
175 logInfo << "texture channels: " << channels << std::endl;
176 if (channels == 3) mColorMode = GL_RGB;
177 else mColorMode = GL_RGBA;
178
179 // read comments
180 png_get_text(pngObj, pngInfo, &texts, &numTexts);
181 logInfo << "num texts: " << numTexts << std::endl;
182 for (int i = 0; i < numTexts; ++i)
183 {
184 if (strncmp(texts[i].key, "Comment", 7) == 0)
185 {
186 mComment = texts[i].text;
187 break;
188 }
189 }
190
191 width = png_get_image_width(pngObj, pngInfo);
192 height = png_get_image_height(pngObj, pngInfo);
193
194 pitch = png_get_rowbytes(pngObj, pngInfo);
195 mPixels = new char[width * pitch];
196
197 rows = new png_bytep[height];
198 if (flipped)
199 {
200 for (int i = 0; i < height; ++i)
201 {
202 rows[height - 1 - i] = (png_bytep)(mPixels + i * channels * width);
203 }
204 }
205 else
206 {
207 for (int i = 0; i < height; ++i)
208 {
209 rows[i] = (png_bytep)(mPixels + i * channels * width);
210 }
211 }
212
213 png_read_image(pngObj, rows);
214 png_read_end(pngObj, 0);
215
216 mContext = SDL_CreateRGBSurfaceFrom
217 (
218 mPixels,
219 width,
220 height,
221 bpp * channels,
222 pitch,
223 #if SDL_BYTEORDER == SDL_LIL_ENDIAN
224 0x000000FF,
225 0x0000FF00,
226 0x00FF0000,
227 0xFF000000
228 #else
229 0xFF000000,
230 0x00FF0000,
231 0x0000FF00,
232 0x000000FF
233 #endif
234 );
235
236 cleanup:
237
238 logInfo("cleaning up...");
239 delete[] rows;
240 png_destroy_read_struct(pngObj ? &pngObj : 0,
241 pngInfo ? &pngInfo : 0,
242 pngInfoEnd ? &pngInfoEnd : 0);
243 fclose(fp);
244
245 return mContext;
246 }
247 };
248
249
250 Image::Image(const std::string& name) :
251 // pass through
252 mImpl(Image::Impl::getInstance(name)) {}
253
254
255 bool Image::isValid() const
256 {
257 return mImpl->mContext;
258 }
259
260 int Image::getWidth() const
261 {
262 return mImpl->mContext->w;
263 }
264
265 int Image::getHeight() const
266 {
267 return mImpl->mContext->h;
268 }
269
270 unsigned Image::getDepth() const
271 {
272 return mImpl->mDepth;
273 }
274
275 unsigned Image::getPitch() const
276 {
277 return mImpl->mContext->pitch;
278 }
279
280 GLuint Image::getColorMode() const
281 {
282 return mImpl->mColorMode;
283 }
284
285 std::string Image::getComment() const
286 {
287 return mImpl->mComment;
288 }
289
290 const char* Image::getPixels() const
291 {
292 return mImpl->mPixels;
293 }
294
295 char* Image::getPixels()
296 {
297 return mImpl->mPixels;
298 }
299
300
301 void Image::flip()
302 {
303 // pass through
304 mImpl->flip();
305 }
306
307 void Image::setAsIcon() const
308 {
309 // pass through
310 mImpl->setAsIcon();
311 }
312
313
314
315 std::string Image::getPath(const std::string& name)
316 {
317 std::string path = Resource::getPath("images/" + name + ".png");
318 return path;
319 }
320
321
322 } // namespace Mf
323
324 /** vim: set ts=4 sw=4 tw=80: *************************************************/
325
This page took 0.045383 seconds and 4 git commands to generate.