26 #ifdef _WIN32 // Stupid Windows needs to include windows.h before gl.h
41 #define GLPNG_CHECK_SIG(header,size) png_check_sig(header,size) // old libpng
43 #define GLPNG_CHECK_SIG(header,size) (png_sig_cmp(header,0,size)==0)
47 #ifdef GL_COLOR_INDEX1_EXT
48 #define SUPPORTS_PALETTE_EXT
51 #pragma GCC diagnostic ignored "-Wunused-parameter"
60 #ifdef SUPPORTS_PALETTE_EXT
62 static PFNGLCOLORTABLEEXTPROC glColorTableEXT = NULL;
86 char *gammaEnv = getenv(
"VIEWING_GAMMA");
88 if (gammaEnv && !gammaExplicit)
90 sscanf(gammaEnv,
"%lf", &viewingGamma);
101 for (p = 0; p < 24; p++)
109 static void Resize(
int components,
const png_bytep d1,
int w1,
int h1, png_bytep d2,
int w2,
int h2) {
110 const float sx = (float) w1/w2, sy = (
float) h1/h2;
114 for (y = 0; y < h2; y++) {
115 yy = (
int) (y*sy)*w1;
117 for (x = 0; x < w2; x++) {
119 d = d1 + (yy+xx)*components;
121 for (c = 0; c < components; c++)
127 #ifdef SUPPORTS_PALETTE_EXT
129 static int ExtSupported(
const char *x) {
130 static const GLubyte *ext = NULL;
132 int xlen = strlen(x);
134 if (ext == NULL) ext = glGetString(GL_EXTENSIONS);
136 c = (
const char*)ext;
139 if (strcmp(c, x) == 0 && (c[xlen] ==
'\0' || c[xlen] ==
' '))
return 1;
148 #define GET(o) ((int)*(data + (o)))
150 static int HalfSize(GLint components, GLint width, GLint height,
const unsigned char *data,
unsigned char *d,
int filter) {
152 int line = width*components;
154 if (width > 1 && height > 1) {
156 for (y = 0; y < height; y += 2) {
157 for (x = 0; x < width; x += 2) {
158 for (c = 0; c < components; c++) {
159 *d++ = (
GET(0)+
GET(components)+
GET(line)+
GET(line+components)) / 4;
167 for (y = 0; y < height; y += 2) {
168 for (x = 0; x < width; x += 2) {
169 for (c = 0; c < components; c++) {
178 else if (width > 1 && height == 1) {
180 for (y = 0; y < height; y += 1) {
181 for (x = 0; x < width; x += 2) {
182 for (c = 0; c < components; c++) {
183 *d++ = (
GET(0)+
GET(components)) / 2;
190 for (y = 0; y < height; y += 1) {
191 for (x = 0; x < width; x += 2) {
192 for (c = 0; c < components; c++) {
200 else if (width == 1 && height > 1) {
202 for (y = 0; y < height; y += 2) {
203 for (x = 0; x < width; x += 1) {
204 for (c = 0; c < components; c++) {
205 *d++ = (
GET(0)+
GET(line)) / 2;
212 for (y = 0; y < height; y += 2) {
213 for (x = 0; x < width; x += 1) {
214 for (c = 0; c < components; c++) {
232 static void Build2DMipmaps(GLint components, GLint width, GLint height, GLenum
format,
const unsigned char *data,
int filter) {
234 unsigned char *d = (
unsigned char *) malloc((width/2)*(height/2)*components+4);
235 const unsigned char *last = data;
237 glTexImage2D(GL_TEXTURE_2D, level, components, width, height, 0, format, GL_UNSIGNED_BYTE, data);
240 while (
HalfSize(components, width, height, last, d, filter)) {
241 if (width > 1) width /= 2;
242 if (height > 1) height /= 2;
244 glTexImage2D(GL_TEXTURE_2D, level, components, width, height, 0, format, GL_UNSIGNED_BYTE, d);
253 unsigned char header[8];
255 if (fread(header, 1, 8, fp) != 8)
return 0;
266 png_uint_32 width, height, rw, rh;
271 png = png_create_read_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL);
272 info = png_create_info_struct(png);
273 endinfo = png_create_info_struct(png);
276 if (setjmp(png_jmpbuf(png))) {
277 png_destroy_read_struct(&png, &info, &endinfo);
282 png_init_io(png, fp);
283 png_set_sig_bytes(png, 8);
284 png_read_info(png, info);
285 png_get_IHDR(png, info, &width, &height, &depth, &color, NULL, NULL, NULL);
288 pinfo->
Width = width;
290 pinfo->
Depth = depth;
296 #ifdef SUPPORTS_PALETTE_EXT
298 if (PalettedTextures == -1)
299 PalettedTextures = ExtSupported(
"GL_EXT_paletted_texture") && (strstr((
const char *) glGetString(GL_VERSION),
"1.1.0 3Dfx Beta") == NULL);
301 if (PalettedTextures) {
302 if (glColorTableEXT == NULL) {
303 glColorTableEXT = (PFNGLCOLORTABLEEXTPROC) wglGetProcAddress(
"glColorTableEXT");
304 if (glColorTableEXT == NULL)
305 PalettedTextures = 0;
311 if (PalettedTextures == -1)
312 PalettedTextures = 0;
314 if (color == PNG_COLOR_TYPE_GRAY || color == PNG_COLOR_TYPE_GRAY_ALPHA)
315 png_set_gray_to_rgb(png);
317 if (color&PNG_COLOR_MASK_ALPHA && trans !=
GLPNG_ALPHA) {
318 png_set_strip_alpha(png);
319 color &= ~PNG_COLOR_MASK_ALPHA;
322 if (!(PalettedTextures && mipmap >= 0 && trans ==
GLPNG_SOLID))
323 if (color == PNG_COLOR_TYPE_PALETTE)
328 if (png_get_gAMA(png, info, &fileGamma))
333 png_read_update_info(png, info);
335 data = (png_bytep) malloc(png_get_rowbytes(png, info)*height);
336 row_p = (png_bytep *) malloc(
sizeof(png_bytep)*height);
338 for (i = 0; i < height; i++) {
339 if (StandardOrientation)
340 row_p[height - 1 - i] = &data[png_get_rowbytes(png, info)*i];
342 row_p[i] = &data[png_get_rowbytes(png, info)*i];
345 png_read_image(png, row_p);
350 if (rw != width || rh != height) {
351 const int channels = png_get_rowbytes(png, info)/width;
353 png_bytep data2 = (png_bytep) malloc(rw*rh*channels);
359 Resize(channels, data, width, height, data2, rw, rh);
361 width = rw, height = rh;
367 glGetIntegerv(GL_PACK_ALIGNMENT, &pack);
368 glGetIntegerv(GL_UNPACK_ALIGNMENT, &unpack);
369 glPixelStorei(GL_PACK_ALIGNMENT, 1);
370 glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
372 #ifdef SUPPORTS_PALETTE_EXT
373 if (PalettedTextures && mipmap >= 0 && trans ==
GLPNG_SOLID && color == PNG_COLOR_TYPE_PALETTE) {
376 GLint internalFormat;
378 if (pinfo != NULL) pinfo->
Alpha = 0;
379 png_get_PLTE(png, info, &pal, &cols);
382 case 1<<1: internalFormat = GL_COLOR_INDEX1_EXT;
break;
383 case 1<<2: internalFormat = GL_COLOR_INDEX2_EXT;
break;
384 case 1<<4: internalFormat = GL_COLOR_INDEX4_EXT;
break;
385 case 1<<8: internalFormat = GL_COLOR_INDEX8_EXT;
break;
386 case 1<<12: internalFormat = GL_COLOR_INDEX12_EXT;
break;
387 case 1<<16: internalFormat = GL_COLOR_INDEX16_EXT;
break;
391 glColorTableEXT(GL_TEXTURE_2D, GL_RGB8, cols, GL_RGB, GL_UNSIGNED_BYTE, pal);
392 glTexImage2D(GL_TEXTURE_2D, mipmap, internalFormat, width, height, 0, GL_COLOR_INDEX, GL_UNSIGNED_BYTE, data);
396 if (trans ==
GLPNG_SOLID || trans ==
GLPNG_ALPHA || color == PNG_COLOR_TYPE_RGB_ALPHA || color == PNG_COLOR_TYPE_GRAY_ALPHA) {
401 case PNG_COLOR_TYPE_GRAY:
402 case PNG_COLOR_TYPE_RGB:
403 case PNG_COLOR_TYPE_PALETTE:
406 if (pinfo != NULL) pinfo->
Alpha = 0;
409 case PNG_COLOR_TYPE_GRAY_ALPHA:
410 case PNG_COLOR_TYPE_RGB_ALPHA:
413 if (pinfo != NULL) pinfo->
Alpha = 8;
425 glTexImage2D(GL_TEXTURE_2D, mipmap, glcomponent, width, height, 0, glformat, GL_UNSIGNED_BYTE, data);
428 png_bytep p, endp, q, data2;
431 p = data, endp = p+width*height*3;
432 q = data2 = (png_bytep) malloc(
sizeof(png_byte)*width*height*4);
434 if (pinfo != NULL) pinfo->
Alpha = 8;
470 if (a > 255) ALPHA = 255;
else ALPHA = a;
477 if (a > 255*2) ALPHA = 255;
else ALPHA = a/2;
490 if (a > 255) ALPHA = 255;
else ALPHA = a;
497 if (a > 255*2) ALPHA = 255;
else ALPHA = a/2;
504 if (a > 255*3) ALPHA = 255;
else ALPHA = a/3;
511 if (a > 255*255) ALPHA = 255;
else ALPHA = (
int) sqrt(a);
525 glTexImage2D(GL_TEXTURE_2D, mipmap, 4, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, data2);
530 glPixelStorei(GL_PACK_ALIGNMENT, pack);
531 glPixelStorei(GL_UNPACK_ALIGNMENT, unpack);
534 png_read_end(png, endinfo);
535 png_destroy_read_struct(&png, &info, &endinfo);
544 FILE *fp = fopen(filename,
"rb");
545 if (fp == NULL)
return 0;
547 result =
pngLoadF(fp, mipmap, trans, pinfo);
549 if (fclose(fp) != 0)
return 0;
554 static unsigned int SetParams(
int wrapst,
int magfilter,
int minfilter) {
557 glGenTextures(1, &
id);
558 glBindTexture(GL_TEXTURE_2D,
id);
560 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, wrapst);
561 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, wrapst);
563 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, magfilter);
564 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, minfilter);
570 unsigned int id =
SetParams(wrapst, magfilter, minfilter);
572 if (
id != 0 &&
pngLoad(filename, mipmap, trans, info))
static void Resize(int components, const png_bytep d1, int w1, int h1, png_bytep d2, int w2, int h2)
static int SafeSize(int i)
#define GLPNG_SIMPLEMIPMAPS
static char gammaExplicit
AliDataPtr format(AliDataPtr data, const size_t wanted_len, GB_ERROR &error)
static int PalettedTextures
static GLint MaxTextureSize
static unsigned char(* AlphaCallback)(unsigned char red, unsigned char green, unsigned char blue)
#define GLPNG_BUILDMIPMAPS
static unsigned char StencilGreen
unsigned int APIENTRY pngBind(const char *filename, int mipmap, int trans, pngInfo *info, int wrapst, int minfilter, int magfilter)
static void Build2DMipmaps(GLint components, GLint width, GLint height, GLenum format, const unsigned char *data, int filter)
static int APIENTRY pngLoad(const char *filename, int mipmap, int trans, pngInfo *pinfo)
static double screenGamma
static int HalfSize(GLint components, GLint width, GLint height, const unsigned char *data, unsigned char *d, int filter)
static void checkForGammaEnv()
static int StandardOrientation
static unsigned char StencilRed
static int APIENTRY pngLoadF(FILE *fp, int mipmap, int trans, pngInfo *pinfo)
static unsigned char DefaultAlphaCallback(unsigned char red, unsigned char green, unsigned char blue)
static int info[maxsites+1]
static unsigned char StencilBlue
static unsigned int SetParams(int wrapst, int magfilter, int minfilter)
#define GLPNG_CHECK_SIG(header, size)