*
**************************************************************************/
-#include <cstdio> // FILE
#include <cstring> // strncmp
+#include <fstream>
#include <stdexcept>
#include <png.h>
unsigned image::global_object_ = 0;
+static void read_from_stream(png_structp context, png_bytep data, png_size_t length)
+{
+ std::istream& stream(*(std::istream*)png_get_io_ptr(context));
+ stream.read((char*)data, length);
+}
+
+
image::image(const std::string& path) :
pixels_(0),
object_(0),
min_filter_(GL_NEAREST),
mag_filter_(GL_NEAREST),
+ tile_s_(1),
+ tile_t_(1),
wrap_s_(GL_CLAMP),
- wrap_t_(GL_CLAMP),
- tile_width_(1),
- tile_height_(1)
+ wrap_t_(GL_CLAMP)
{
- FILE* fp = fopen(path.c_str(), "rb");
- if (!fp) throw std::runtime_error("image not found at " + path);
+ std::ifstream file(path.c_str());
+ if (!file.good()) throw std::runtime_error("no valid image found at " + path);
png_byte signature[8];
size_t bytesRead;
- png_infop pngInfo = 0;
- png_infop pngInfoEnd = 0;
- png_structp pngObj = 0;
-
int bpp;
png_byte colors;
png_textp texts = 0;
int nutext_s;
- bytesRead = fread(signature, 1, sizeof(signature), fp);
+ bytesRead = file.read((char*)signature, sizeof(signature)).gcount();
if (bytesRead < sizeof(signature) ||
- png_sig_cmp(signature, 0, sizeof(signature)) != 0) goto cleanup;
+ png_sig_cmp(signature, 0, sizeof(signature)) != 0) throw 0;
- 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;
+ struct png
+ {
+ png_structp context;
+ png_infop info;
+ png() :
+ context(png_create_read_struct(PNG_LIBPNG_VER_STRING, 0, 0, 0)),
+ info(png_create_info_struct(context))
+ {
+ if (!context || !info) throw 0;
+ }
+ ~png()
+ {
+ png_destroy_read_struct(context ? &context : 0,
+ info ? &info : 0, 0);
+ }
+ } png;
- if (setjmp(png_jmpbuf(pngObj))) goto cleanup;
+ if (setjmp(png_jmpbuf(png.context))) throw 0;
- png_init_io(pngObj, fp);
- png_set_sig_bytes(pngObj, sizeof(signature));
- png_read_info(pngObj, pngInfo);
+ png_set_read_fn(png.context, (void*)&file, read_from_stream);
+ png_set_sig_bytes(png.context, sizeof(signature));
+ png_read_info(png.context, png.info);
- bpp = png_get_bit_depth(pngObj, pngInfo);
- colors = png_get_color_type(pngObj, pngInfo);
+ bpp = png_get_bit_depth(png.context, png.info);
+ colors = png_get_color_type(png.context, png.info);
switch (colors)
{
case PNG_COLOR_TYPE_PALETTE:
- png_set_palette_to_rgb(pngObj);
+ png_set_palette_to_rgb(png.context);
break;
case PNG_COLOR_TYPE_GRAY:
- if (bpp < 8) png_set_expand(pngObj);
+ if (bpp < 8) png_set_expand(png.context);
break;
case PNG_COLOR_TYPE_GRAY_ALPHA:
- png_set_gray_to_rgb(pngObj);
+ png_set_gray_to_rgb(png.context);
break;
}
- if (bpp == 16) png_set_strip_16(pngObj);
+ if (bpp == 16) png_set_strip_16(png.context);
- png_read_update_info(pngObj, pngInfo);
+ png_read_update_info(png.context, png.info);
- bpp = png_get_bit_depth(pngObj, pngInfo);
- channels_ = png_get_channels(pngObj, pngInfo);
+ bpp = png_get_bit_depth(png.context, png.info);
+ channels_ = png_get_channels(png.context, png.info);
depth_ = bpp * channels_;
// read comments
- png_get_text(pngObj, pngInfo, &texts, &nutext_s);
+ bool isTexture = false;
+ png_get_text(png.context, png.info, &texts, &nutext_s);
for (int i = 0; i < nutext_s; ++i)
{
- if (strncmp(texts[i].key, "TextureInfo", 11) == 0)
+ if (strncmp(texts[i].key, "X-Yoink-Texture", 11) == 0)
{
set_texture_info(texts[i].text);
+ isTexture = true;
break;
}
}
- width_ = png_get_image_width(pngObj, pngInfo);
- height_ = png_get_image_height(pngObj, pngInfo);
+ width_ = png_get_image_width(png.context, png.info);
+ height_ = png_get_image_height(png.context, png.info);
- pitch_ = png_get_rowbytes(pngObj, pngInfo);
+ pitch_ = png_get_rowbytes(png.context, png.info);
pixels_ = new char[width_ * pitch_];
rows = new png_bytep[height_];
- for (int i = 0; i < height_; ++i)
+ if (isTexture)
{
- rows[height_-1-i] = (png_bytep)(pixels_ + i * channels_ * width_);
+ log_debug("texture detected; loading flipped");
+ for (int i = 0; i < height_; ++i)
+ {
+ rows[height_-1-i] = (png_bytep)(pixels_ + i * channels_ * width_);
+ }
+ }
+ else
+ {
+ log_debug("no texture attributes found");
+ for (int i = 0; i < height_; ++i)
+ {
+ rows[i] = (png_bytep)(pixels_ + i * channels_ * width_);
+ }
}
- png_read_image(pngObj, rows);
- png_read_end(pngObj, 0);
-
-cleanup:
+ png_read_image(png.context, rows);
+ png_read_end(png.context, 0);
+ // TODO leak
delete[] rows;
- png_destroy_read_struct(pngObj ? &pngObj : 0,
- pngInfo ? &pngInfo : 0,
- pngInfoEnd ? &pngInfoEnd : 0);
- fclose(fp);
}
image::~image()
bool image::tile_coordinates(int index, scalar coords[8]) const
{
// make sure the index represents a real tile
- if (index < 0 && index >= tile_width_ * tile_height_) return false;
+ if (index < 0 && index >= tile_s_ * tile_t_) return false;
- scalar w = 1.0 / scalar(tile_width_);
- scalar h = 1.0 / scalar(tile_height_);
+ scalar w = 1.0 / scalar(tile_s_);
+ scalar h = 1.0 / scalar(tile_t_);
- coords[0] = scalar(index % tile_width_) * w;
- coords[1] = (scalar(tile_height_ - 1) - scalar(index / tile_width_)) * h;
+ coords[0] = scalar(index % tile_s_) * w;
+ coords[1] = (scalar(tile_t_ - 1) - scalar(index / tile_s_)) * h;
coords[2] = coords[0] + w;
coords[3] = coords[1];
coords[4] = coords[2];
log_info("loading texture information...");
script::slot globals = script.globals();
- globals.get(tile_width_, "tiles_s");
- globals.get(tile_height_, "tiles_t");
globals.get(min_filter_, "min_filter");
globals.get(mag_filter_, "mag_filter");
+ globals.get(tile_s_, "tile_s");
+ globals.get(tile_t_, "tile_t");
globals.get(wrap_s_, "wrap_s");
globals.get(wrap_t_, "wrap_t");
- //min_filter_ = GL_LINEAR;
- //mag_filter_ = GL_LINEAR;
- //wrap_s_ = GL_CLAMP;
- //wrap_t_ = GL_CLAMP;
}
}