2 /*] Copyright (c) 2009-2010, Charles McGarvey [**************************
3 **] All rights reserved.
7 * Distributable under the terms and conditions of the 2-clause BSD license;
8 * see the file COPYING for a complete text of the license.
10 **************************************************************************/
12 #include <cstdio> // FILE
13 #include <cstring> // strncmp
15 #include <boost/algorithm/string.hpp>
30 class Image::Impl
: public Manager
<Impl
>
40 SDL_FreeSurface(mContext
);
47 unsigned char* pixels
= (Uint8
*)(mContext
->pixels
);
49 unsigned pitch
= mContext
->pitch
;
50 unsigned char line
[pitch
];
53 int yEnd
= mContext
->h
- 1;
55 if (SDL_MUSTLOCK(mContext
)) SDL_LockSurface(mContext
);
58 memcpy(line
, pixels
+ pitch
* yBegin
, pitch
);
59 memcpy(pixels
+ pitch
* yBegin
, pixels
+ pitch
* yEnd
, pitch
);
60 memcpy(pixels
+ pitch
* yEnd
, line
, pitch
);
64 if (SDL_MUSTLOCK(mContext
)) SDL_UnlockSurface(mContext
);
67 void setAsIcon() const
69 SDL_WM_SetIcon(mContext
, 0);
73 void init(const std::string
& name
, bool flipped
= false)
75 std::string
path(name
);
77 logInfo
<< "opening image file " << path
<< std::endl
;
78 FILE* fp
= Image::openFile(path
);
81 png_byte signature
[8];
84 png_infop pngInfo
= 0;
85 png_infop pngInfoEnd
= 0;
86 png_structp pngObj
= 0;
100 logInfo("checking signature...");
101 bytesRead
= fread(signature
, 1, sizeof(signature
), fp
);
102 logInfo
<< "reading " << bytesRead
<< " bytes of signature"
104 if (bytesRead
< sizeof(signature
) ||
105 png_sig_cmp(signature
, 0, sizeof(signature
)) != 0) goto cleanup
;
107 logInfo("creating png structures...");
108 pngObj
= png_create_read_struct(PNG_LIBPNG_VER_STRING
, 0, 0, 0);
109 if (!pngObj
) goto cleanup
;
111 pngInfo
= png_create_info_struct(pngObj
);
112 if (!pngInfo
) goto cleanup
;
114 pngInfoEnd
= png_create_info_struct(pngObj
);
115 if (!pngInfoEnd
) goto cleanup
;
117 logInfo("setting up long jump...");
118 if (setjmp(png_jmpbuf(pngObj
))) goto cleanup
;
120 png_init_io(pngObj
, fp
);
121 png_set_sig_bytes(pngObj
, sizeof(signature
));
122 png_read_info(pngObj
, pngInfo
);
124 bpp
= png_get_bit_depth(pngObj
, pngInfo
);
125 logInfo
<< "texture bpp: " << bpp
<< std::endl
;
126 colors
= png_get_color_type(pngObj
, pngInfo
);
129 case PNG_COLOR_TYPE_PALETTE
:
130 png_set_palette_to_rgb(pngObj
);
133 case PNG_COLOR_TYPE_GRAY
:
134 if (bpp
< 8) png_set_expand(pngObj
);
137 case PNG_COLOR_TYPE_GRAY_ALPHA
:
138 png_set_gray_to_rgb(pngObj
);
142 if (bpp
== 16) png_set_strip_16(pngObj
);
144 png_read_update_info(pngObj
, pngInfo
);
146 bpp
= png_get_bit_depth(pngObj
, pngInfo
);
147 channels
= png_get_channels(pngObj
, pngInfo
);
148 mDepth
= bpp
* channels
;
150 logInfo
<< "texture channels: " << channels
<< std::endl
;
151 if (channels
== 3) mColorMode
= GL_RGB
;
152 else mColorMode
= GL_RGBA
;
155 png_get_text(pngObj
, pngInfo
, &texts
, &numTexts
);
156 logInfo
<< "num texts: " << numTexts
<< std::endl
;
157 for (int i
= 0; i
< numTexts
; ++i
)
159 if (strncmp(texts
[i
].key
, "TextureInfo", 11) == 0)
161 mComment
= texts
[i
].text
;
166 width
= png_get_image_width(pngObj
, pngInfo
);
167 height
= png_get_image_height(pngObj
, pngInfo
);
169 pitch
= png_get_rowbytes(pngObj
, pngInfo
);
170 mPixels
= new char[width
* pitch
];
172 rows
= new png_bytep
[height
];
175 for (int i
= 0; i
< height
; ++i
)
177 rows
[height
- 1 - i
] = (png_bytep
)(mPixels
+
178 i
* channels
* width
);
183 for (int i
= 0; i
< height
; ++i
)
185 rows
[i
] = (png_bytep
)(mPixels
+ i
* channels
* width
);
189 png_read_image(pngObj
, rows
);
190 png_read_end(pngObj
, 0);
192 mContext
= SDL_CreateRGBSurfaceFrom
199 #if SDL_BYTEORDER == SDL_LIL_ENDIAN
214 logInfo("cleaning up...");
216 png_destroy_read_struct(pngObj
? &pngObj
: 0,
217 pngInfo
? &pngInfo
: 0,
218 pngInfoEnd
? &pngInfoEnd
: 0);
223 SDL_Surface
* mContext
;
229 std::string mComment
;
237 Image::Image(const std::string
& name
) :
239 mImpl(Image::Impl::getInstance(name
)) {}
242 bool Image::isValid() const
244 return mImpl
->mContext
;
247 int Image::getWidth() const
249 return mImpl
->mContext
->w
;
252 int Image::getHeight() const
254 return mImpl
->mContext
->h
;
257 unsigned Image::getDepth() const
259 return mImpl
->mDepth
;
262 unsigned Image::getPitch() const
264 return mImpl
->mContext
->pitch
;
267 GLuint
Image::getMode() const
269 return mImpl
->mColorMode
;
272 std::string
Image::getComment() const
274 return mImpl
->mComment
;
277 const char* Image::getPixels() const
279 return mImpl
->mPixels
;
282 char* Image::getPixels()
284 return mImpl
->mPixels
;
294 void Image::setAsIcon() const
301 bool Image::getPath(std::string
& name
)
303 return Resource::getPath(name
, "images/", "png");
306 FILE* Image::openFile(std::string
& name
)
308 return Resource::openFile(name
, "images/", "png");