+++ /dev/null
-
-/*] Copyright (c) 2009-2010, Charles McGarvey [**************************
-**] All rights reserved.
-*
-* vi:ts=4 sw=4 tw=75
-*
-* Distributable under the terms and conditions of the 2-clause BSD license;
-* see the file COPYING for a complete text of the license.
-*
-**************************************************************************/
-
-#include <cstdio> // FILE
-#include <cstring> // strncmp
-
-#include <boost/algorithm/string.hpp>
-
-#include <png.h>
-#include <SDL/SDL.h>
-
-#include "Backend.hh"
-#include "Error.hh"
-#include "Image.hh"
-#include "Log.hh"
-#include "Manager.hh"
-
-
-namespace Mf {
-
-
-class Image::Impl : public Manager<Impl>
-{
-public:
-
- explicit Impl() :
- mContext(0),
- mPixels(0) {}
-
- ~Impl()
- {
- SDL_FreeSurface(mContext);
- delete[] mPixels;
- }
-
-
- void flip()
- {
- unsigned char* pixels = (Uint8*)(mContext->pixels);
-
- unsigned pitch = mContext->pitch;
- unsigned char line[pitch];
-
- int yBegin = 0;
- int yEnd = mContext->h - 1;
-
- if (SDL_MUSTLOCK(mContext)) SDL_LockSurface(mContext);
- while (yBegin < yEnd)
- {
- memcpy(line, pixels + pitch * yBegin, pitch);
- memcpy(pixels + pitch * yBegin, pixels + pitch * yEnd, pitch);
- memcpy(pixels + pitch * yEnd, line, pitch);
- yBegin++;
- yEnd--;
- }
- if (SDL_MUSTLOCK(mContext)) SDL_UnlockSurface(mContext);
- }
-
- void setAsIcon() const
- {
- SDL_WM_SetIcon(mContext, 0);
- }
-
-
- void init(const std::string& name, bool flipped = false)
- {
- std::string path(name);
-
- FILE* fp = Image::openFile(path);
- if (!fp) return;
-
- png_byte signature[8];
- size_t bytesRead;
-
- png_infop pngInfo = 0;
- png_infop pngInfoEnd = 0;
- png_structp pngObj = 0;
-
- int width;
- int height;
- int pitch;
- int bpp;
- int channels;
-
- png_byte colors;
- png_bytepp rows = 0;
-
- png_textp texts = 0;
- int numTexts;
-
- bytesRead = fread(signature, 1, sizeof(signature), fp);
- if (bytesRead < sizeof(signature) ||
- png_sig_cmp(signature, 0, sizeof(signature)) != 0) goto cleanup;
-
- pngObj = png_create_read_struct(PNG_LIBPNG_VER_STRING, 0, 0, 0);
- if (!pngObj) goto cleanup;
-
- pngInfo = png_create_info_struct(pngObj);
- if (!pngInfo) goto cleanup;
-
- pngInfoEnd = png_create_info_struct(pngObj);
- if (!pngInfoEnd) goto cleanup;
-
- if (setjmp(png_jmpbuf(pngObj))) goto cleanup;
-
- png_init_io(pngObj, fp);
- png_set_sig_bytes(pngObj, sizeof(signature));
- png_read_info(pngObj, pngInfo);
-
- bpp = png_get_bit_depth(pngObj, pngInfo);
- colors = png_get_color_type(pngObj, pngInfo);
- switch (colors)
- {
- case PNG_COLOR_TYPE_PALETTE:
- png_set_palette_to_rgb(pngObj);
- break;
-
- case PNG_COLOR_TYPE_GRAY:
- if (bpp < 8) png_set_expand(pngObj);
- break;
-
- case PNG_COLOR_TYPE_GRAY_ALPHA:
- png_set_gray_to_rgb(pngObj);
- break;
- }
-
- if (bpp == 16) png_set_strip_16(pngObj);
-
- png_read_update_info(pngObj, pngInfo);
-
- bpp = png_get_bit_depth(pngObj, pngInfo);
- channels = png_get_channels(pngObj, pngInfo);
- mDepth = bpp * channels;
-
- if (channels == 3) mColorMode = GL_RGB;
- else mColorMode = GL_RGBA;
-
- // read comments
- png_get_text(pngObj, pngInfo, &texts, &numTexts);
- for (int i = 0; i < numTexts; ++i)
- {
- if (strncmp(texts[i].key, "TextureInfo", 11) == 0)
- {
- mComment = texts[i].text;
- break;
- }
- }
-
- width = png_get_image_width(pngObj, pngInfo);
- height = png_get_image_height(pngObj, pngInfo);
-
- pitch = png_get_rowbytes(pngObj, pngInfo);
- mPixels = new char[width * pitch];
-
- rows = new png_bytep[height];
- if (flipped)
- {
- for (int i = 0; i < height; ++i)
- {
- rows[height - 1 - i] = (png_bytep)(mPixels +
- i * channels * width);
- }
- }
- else
- {
- for (int i = 0; i < height; ++i)
- {
- rows[i] = (png_bytep)(mPixels + i * channels * width);
- }
- }
-
- png_read_image(pngObj, rows);
- png_read_end(pngObj, 0);
-
- mContext = SDL_CreateRGBSurfaceFrom
- (
- mPixels,
- width,
- height,
- bpp * channels,
- pitch,
-#if SDL_BYTEORDER == SDL_LIL_ENDIAN
- 0x000000FF,
- 0x0000FF00,
- 0x00FF0000,
- 0xFF000000
-#else
- 0xFF000000,
- 0x00FF0000,
- 0x0000FF00,
- 0x000000FF
-#endif
- );
-
- cleanup:
-
- delete[] rows;
- png_destroy_read_struct(pngObj ? &pngObj : 0,
- pngInfo ? &pngInfo : 0,
- pngInfoEnd ? &pngInfoEnd : 0);
- fclose(fp);
- }
-
-
- SDL_Surface* mContext;
- char* mPixels;
-
- unsigned mDepth;
- GLuint mColorMode;
-
- std::string mComment;
-
-private:
-
- Backend mBackend;
-};
-
-
-Image::Image(const std::string& name) :
- // pass through
- mImpl(Image::Impl::getInstance(name)) {}
-
-
-bool Image::isValid() const
-{
- return mImpl->mContext;
-}
-
-int Image::getWidth() const
-{
- return mImpl->mContext->w;
-}
-
-int Image::getHeight() const
-{
- return mImpl->mContext->h;
-}
-
-unsigned Image::getDepth() const
-{
- return mImpl->mDepth;
-}
-
-unsigned Image::getPitch() const
-{
- return mImpl->mContext->pitch;
-}
-
-GLuint Image::getMode() const
-{
- return mImpl->mColorMode;
-}
-
-std::string Image::getComment() const
-{
- return mImpl->mComment;
-}
-
-const char* Image::getPixels() const
-{
- return mImpl->mPixels;
-}
-
-char* Image::getPixels()
-{
- return mImpl->mPixels;
-}
-
-
-void Image::flip()
-{
- // pass through
- mImpl->flip();
-}
-
-void Image::setAsIcon() const
-{
- // pass through
- mImpl->setAsIcon();
-}
-
-
-bool Image::getPath(std::string& name)
-{
- return Resource::getPath(name, "images/", "png");
-}
-
-FILE* Image::openFile(std::string& name)
-{
- return Resource::openFile(name, "images/", "png");
-}
-
-
-} // namespace Mf
-