2 /*******************************************************************************
4 Copyright (c) 2009, Charles McGarvey
7 Redistribution and use in source and binary forms, with or without
8 modification, are permitted provided that the following conditions are met:
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.
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.
27 *******************************************************************************/
29 #include <cstdio> // FILE
30 #include <cstring> // strncmp
43 class Image::Impl
: public Library
<Impl
>
47 explicit Impl(const std::string
& name
, bool flipped
= false) :
52 init(getName(), flipped
);
57 SDL_FreeSurface(mContext
);
64 unsigned char* pixels
= (Uint8
*)(mContext
->pixels
);
66 unsigned pitch
= mContext
->pitch
;
67 unsigned char line
[pitch
];
70 int yEnd
= mContext
->h
- 1;
72 if (SDL_MUSTLOCK(mContext
)) SDL_LockSurface(mContext
);
75 memcpy(line
, pixels
+ pitch
* yBegin
, pitch
);
76 memcpy(pixels
+ pitch
* yBegin
, pixels
+ pitch
* yEnd
, pitch
);
77 memcpy(pixels
+ pitch
* yEnd
, line
, pitch
);
81 if (SDL_MUSTLOCK(mContext
)) SDL_UnlockSurface(mContext
);
84 void setAsIcon() const
86 SDL_WM_SetIcon(mContext
, 0);
90 SDL_Surface
* mContext
;
101 bool init(const std::string
& filePath
, bool flipped
)
103 logInfo("opening image file...");
104 FILE* fp
= fopen(filePath
.c_str(), "rb");
105 if (!fp
) return false;
107 png_byte signature
[8];
110 png_infop pngInfo
= 0;
111 png_infop pngInfoEnd
= 0;
112 png_structp pngObj
= 0;
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
;
132 logInfo("creating png structures...");
133 pngObj
= png_create_read_struct(PNG_LIBPNG_VER_STRING
, 0, 0, 0);
134 if (!pngObj
) goto cleanup
;
136 pngInfo
= png_create_info_struct(pngObj
);
137 if (!pngInfo
) goto cleanup
;
139 pngInfoEnd
= png_create_info_struct(pngObj
);
140 if (!pngInfoEnd
) goto cleanup
;
142 logInfo("setting up long jump...");
143 if (setjmp(png_jmpbuf(pngObj
))) goto cleanup
;
145 png_init_io(pngObj
, fp
);
146 png_set_sig_bytes(pngObj
, sizeof(signature
));
147 png_read_info(pngObj
, pngInfo
);
149 bpp
= png_get_bit_depth(pngObj
, pngInfo
);
150 logInfo
<< "texture bpp: " << bpp
<< std::endl
;
151 colors
= png_get_color_type(pngObj
, pngInfo
);
154 case PNG_COLOR_TYPE_PALETTE
:
155 png_set_palette_to_rgb(pngObj
);
158 case PNG_COLOR_TYPE_GRAY
:
159 if (bpp
< 8) png_set_gray_1_2_4_to_8(pngObj
);
162 case PNG_COLOR_TYPE_GRAY_ALPHA
:
163 png_set_gray_to_rgb(pngObj
);
167 if (bpp
== 16) png_set_strip_16(pngObj
);
169 png_read_update_info(pngObj
, pngInfo
);
171 bpp
= png_get_bit_depth(pngObj
, pngInfo
);
172 channels
= png_get_channels(pngObj
, pngInfo
);
173 mDepth
= bpp
* channels
;
175 logInfo
<< "texture channels: " << channels
<< std::endl
;
176 if (channels
== 3) mColorMode
= GL_RGB
;
177 else mColorMode
= GL_RGBA
;
180 png_get_text(pngObj
, pngInfo
, &texts
, &numTexts
);
181 logInfo
<< "num texts: " << numTexts
<< std::endl
;
182 for (int i
= 0; i
< numTexts
; ++i
)
184 if (strncmp(texts
[i
].key
, "Comment", 7) == 0)
186 mComment
= texts
[i
].text
;
191 width
= png_get_image_width(pngObj
, pngInfo
);
192 height
= png_get_image_height(pngObj
, pngInfo
);
194 pitch
= png_get_rowbytes(pngObj
, pngInfo
);
195 mPixels
= new char[width
* pitch
];
197 rows
= new png_bytep
[height
];
200 for (int i
= 0; i
< height
; ++i
)
202 rows
[height
- 1 - i
] = (png_bytep
)(mPixels
+ i
* channels
* width
);
207 for (int i
= 0; i
< height
; ++i
)
209 rows
[i
] = (png_bytep
)(mPixels
+ i
* channels
* width
);
213 png_read_image(pngObj
, rows
);
214 png_read_end(pngObj
, 0);
216 mContext
= SDL_CreateRGBSurfaceFrom
223 #if SDL_BYTEORDER == SDL_LIL_ENDIAN
238 logInfo("cleaning up...");
240 png_destroy_read_struct(pngObj
? &pngObj
: 0,
241 pngInfo
? &pngInfo
: 0,
242 pngInfoEnd
? &pngInfoEnd
: 0);
250 Image::Image(const std::string
& name
) :
252 mImpl(Image::Impl::getInstance(name
)) {}
255 bool Image::isValid() const
257 return mImpl
->mContext
;
260 int Image::getWidth() const
262 return mImpl
->mContext
->w
;
265 int Image::getHeight() const
267 return mImpl
->mContext
->h
;
270 unsigned Image::getDepth() const
272 return mImpl
->mDepth
;
275 unsigned Image::getPitch() const
277 return mImpl
->mContext
->pitch
;
280 GLuint
Image::getColorMode() const
282 return mImpl
->mColorMode
;
285 std::string
Image::getComment() const
287 return mImpl
->mComment
;
290 const char* Image::getPixels() const
292 return mImpl
->mPixels
;
295 char* Image::getPixels()
297 return mImpl
->mPixels
;
307 void Image::setAsIcon() const
315 std::string
Image::getPath(const std::string
& name
)
317 std::string path
= Resource::getPath("images/" + name
+ ".png");
324 /** vim: set ts=4 sw=4 tw=80: *************************************************/