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
45 class Image::Impl
: public Library
<Impl
>
49 explicit Impl(const std::string
& name
, bool flipped
= false) :
54 init(getName(), flipped
);
59 SDL_FreeSurface(mContext
);
66 unsigned char* pixels
= (Uint8
*)(mContext
->pixels
);
68 unsigned pitch
= mContext
->pitch
;
69 unsigned char line
[pitch
];
72 int yEnd
= mContext
->h
- 1;
74 if (SDL_MUSTLOCK(mContext
)) SDL_LockSurface(mContext
);
77 memcpy(line
, pixels
+ pitch
* yBegin
, pitch
);
78 memcpy(pixels
+ pitch
* yBegin
, pixels
+ pitch
* yEnd
, pitch
);
79 memcpy(pixels
+ pitch
* yEnd
, line
, pitch
);
83 if (SDL_MUSTLOCK(mContext
)) SDL_UnlockSurface(mContext
);
86 void setAsIcon() const
88 SDL_WM_SetIcon(mContext
, 0);
92 SDL_Surface
* mContext
;
105 bool init(const std::string
& filePath
, bool flipped
)
107 logInfo("opening image file...");
108 FILE* fp
= fopen(filePath
.c_str(), "rb");
109 if (!fp
) return false;
111 png_byte signature
[8];
114 png_infop pngInfo
= 0;
115 png_infop pngInfoEnd
= 0;
116 png_structp pngObj
= 0;
130 logInfo("checking signature...");
131 bytesRead
= fread(signature
, 1, sizeof(signature
), fp
);
132 logInfo
<< "reading " << bytesRead
<< " bytes of signature" << std::endl
;
133 if (bytesRead
< sizeof(signature
) ||
134 png_sig_cmp(signature
, 0, sizeof(signature
)) != 0) goto cleanup
;
136 logInfo("creating png structures...");
137 pngObj
= png_create_read_struct(PNG_LIBPNG_VER_STRING
, 0, 0, 0);
138 if (!pngObj
) goto cleanup
;
140 pngInfo
= png_create_info_struct(pngObj
);
141 if (!pngInfo
) goto cleanup
;
143 pngInfoEnd
= png_create_info_struct(pngObj
);
144 if (!pngInfoEnd
) goto cleanup
;
146 logInfo("setting up long jump...");
147 if (setjmp(png_jmpbuf(pngObj
))) goto cleanup
;
149 png_init_io(pngObj
, fp
);
150 png_set_sig_bytes(pngObj
, sizeof(signature
));
151 png_read_info(pngObj
, pngInfo
);
153 bpp
= png_get_bit_depth(pngObj
, pngInfo
);
154 logInfo
<< "texture bpp: " << bpp
<< std::endl
;
155 colors
= png_get_color_type(pngObj
, pngInfo
);
158 case PNG_COLOR_TYPE_PALETTE
:
159 png_set_palette_to_rgb(pngObj
);
162 case PNG_COLOR_TYPE_GRAY
:
163 if (bpp
< 8) png_set_expand(pngObj
);
166 case PNG_COLOR_TYPE_GRAY_ALPHA
:
167 png_set_gray_to_rgb(pngObj
);
171 if (bpp
== 16) png_set_strip_16(pngObj
);
173 png_read_update_info(pngObj
, pngInfo
);
175 bpp
= png_get_bit_depth(pngObj
, pngInfo
);
176 channels
= png_get_channels(pngObj
, pngInfo
);
177 mDepth
= bpp
* channels
;
179 logInfo
<< "texture channels: " << channels
<< std::endl
;
180 if (channels
== 3) mColorMode
= GL_RGB
;
181 else mColorMode
= GL_RGBA
;
184 png_get_text(pngObj
, pngInfo
, &texts
, &numTexts
);
185 logInfo
<< "num texts: " << numTexts
<< std::endl
;
186 for (int i
= 0; i
< numTexts
; ++i
)
188 if (strncmp(texts
[i
].key
, "Comment", 7) == 0)
190 mComment
= texts
[i
].text
;
195 width
= png_get_image_width(pngObj
, pngInfo
);
196 height
= png_get_image_height(pngObj
, pngInfo
);
198 pitch
= png_get_rowbytes(pngObj
, pngInfo
);
199 mPixels
= new char[width
* pitch
];
201 rows
= new png_bytep
[height
];
204 for (int i
= 0; i
< height
; ++i
)
206 rows
[height
- 1 - i
] = (png_bytep
)(mPixels
+ i
* channels
* width
);
211 for (int i
= 0; i
< height
; ++i
)
213 rows
[i
] = (png_bytep
)(mPixels
+ i
* channels
* width
);
217 png_read_image(pngObj
, rows
);
218 png_read_end(pngObj
, 0);
220 mContext
= SDL_CreateRGBSurfaceFrom
227 #if SDL_BYTEORDER == SDL_LIL_ENDIAN
242 logInfo("cleaning up...");
244 png_destroy_read_struct(pngObj
? &pngObj
: 0,
245 pngInfo
? &pngInfo
: 0,
246 pngInfoEnd
? &pngInfoEnd
: 0);
254 Image::Image(const std::string
& name
) :
256 mImpl(Image::Impl::getInstance(name
)) {}
259 bool Image::isValid() const
261 return mImpl
->mContext
;
264 int Image::getWidth() const
266 return mImpl
->mContext
->w
;
269 int Image::getHeight() const
271 return mImpl
->mContext
->h
;
274 unsigned Image::getDepth() const
276 return mImpl
->mDepth
;
279 unsigned Image::getPitch() const
281 return mImpl
->mContext
->pitch
;
284 GLuint
Image::getColorMode() const
286 return mImpl
->mColorMode
;
289 std::string
Image::getComment() const
291 return mImpl
->mComment
;
294 const char* Image::getPixels() const
296 return mImpl
->mPixels
;
299 char* Image::getPixels()
301 return mImpl
->mPixels
;
311 void Image::setAsIcon() const
319 std::string
Image::getPath(const std::string
& name
)
321 std::string path
= Resource::getPath("images/" + name
+ ".png");
328 /** vim: set ts=4 sw=4 tw=80: *************************************************/