2e776388ec7c85f39eab5451f05e757fed954535
[glpng.git] / src / glpng.c
blob2e776388ec7c85f39eab5451f05e757fed954535
1 /*
2 * PNG loader library for OpenGL v1.45 (10/07/00)
3 * by Ben Wyatt ben@wyatt100.freeserve.co.uk
4 * Using LibPNG 1.0.2 and ZLib 1.1.3
6 * This software is provided 'as-is', without any express or implied warranty.
7 * In no event will the author be held liable for any damages arising from the
8 * use of this software.
10 * Permission is hereby granted to use, copy, modify, and distribute this
11 * source code, or portions hereof, for any purpose, without fee, subject to
12 * the following restrictions:
14 * 1. The origin of this source code must not be misrepresented. You must not
15 * claim that you wrote the original software. If you use this software in
16 * a product, an acknowledgment in the product documentation would be
17 * appreciated but is not required.
18 * 2. Altered versions must be plainly marked as such and must not be
19 * misrepresented as being the original source.
20 * 3. This notice must not be removed or altered from any source distribution.
23 #ifdef _WIN32 /* Stupid Windows needs to include windows.h before gl.h */
24 #undef FAR
25 #include <windows.h>
26 #endif
28 #define GL_GLEXT_PROTOTYPES
30 #include <GL/glpng.h>
31 #include <GL/gl.h>
32 #include <GL/glext.h>
33 #include <stdlib.h>
34 #include <stdint.h>
35 #include <string.h>
36 #include <math.h>
37 #include <png.h>
39 /* Used to decide if GL/gl.h supports the paletted extension */
40 #ifdef GL_COLOR_INDEX1_EXT
41 #define SUPPORTS_PALETTE_EXT
42 #endif
44 static unsigned char DefaultAlphaCallback(unsigned char red, unsigned char green, unsigned char blue) {
45 return 255;
48 static unsigned char StencilRed = 0, StencilGreen = 0, StencilBlue = 0;
49 static unsigned char (*AlphaCallback)(unsigned char red, unsigned char green, unsigned char blue) = DefaultAlphaCallback;
50 static int StandardOrientation = 0;
52 #ifdef SUPPORTS_PALETTE_EXT
53 #ifdef _WIN32
54 static PFNGLCOLORTABLEEXTPROC glColorTableEXT = NULL;
55 #endif
56 #endif
58 static int PalettedTextures = -1;
59 static GLint MaxTextureSize = 0;
61 /* screenGamma = displayGamma/viewingGamma
62 * displayGamma = CRT has gamma of ~2.2
63 * viewingGamma depends on platform. PC is 1.0, Mac is 1.45, SGI defaults
64 * to 1.7, but this can be checked and changed w/ /usr/sbin/gamma command.
65 * If the environment variable VIEWING_GAMMA is set, adjust gamma per this value.
67 #ifdef _MAC
68 static double screenGamma = 2.2 / 1.45;
69 #elif SGI
70 static double screenGamma = 2.2 / 1.7;
71 #else /* PC/default */
72 static double screenGamma = 2.2 / 1.0;
73 #endif
75 static char gammaExplicit = 0; /*if */
77 static void checkForGammaEnv()
79 double viewingGamma;
80 char *gammaEnv = getenv("VIEWING_GAMMA");
82 if(gammaEnv && !gammaExplicit)
84 sscanf(gammaEnv, "%lf", &viewingGamma);
85 screenGamma = 2.2/viewingGamma;
89 /* Returns a safe texture size to use (ie a power of 2), based on the current texture size "i" */
90 static int SafeSize(int i) {
91 int p;
93 if (i > MaxTextureSize) return MaxTextureSize;
95 for (p = 0; p < 24; p++)
96 if (i <= (1<<p))
97 return 1<<p;
99 return MaxTextureSize;
102 /* Resize the texture since gluScaleImage doesn't work on everything */
103 static void Resize(int components, const png_bytep d1, int w1, int h1, png_bytep d2, int w2, int h2) {
104 const float sx = (float) w1/w2, sy = (float) h1/h2;
105 int x, y, xx, yy, c;
106 png_bytep d;
108 for (y = 0; y < h2; y++) {
109 yy = (int) (y*sy)*w1;
111 for (x = 0; x < w2; x++) {
112 xx = (int) (x*sx);
113 d = d1 + (yy+xx)*components;
115 for (c = 0; c < components; c++)
116 *d2++ = *d++;
121 #ifdef _WIN32
122 static int ExtSupported(const char *x) {
123 static const GLubyte *ext = NULL;
124 const char *c;
125 int xlen = strlen(x);
127 if (ext == NULL) ext = glGetString(GL_EXTENSIONS);
129 c = (const char*)ext;
131 while (*c != '\0') {
132 if (strcmp(c, x) == 0 && (c[xlen] == '\0' || c[xlen] == ' ')) return 1;
133 c++;
136 return 0;
138 #endif
140 #define GET(o) ((int)*(data + (o)))
142 static int HalfSize(GLint components, GLint width, GLint height, const unsigned char *data, unsigned char *d, int filter) {
143 int x, y, c;
144 int line = width*components;
146 if (width > 1 && height > 1) {
147 if (filter)
148 for (y = 0; y < height; y += 2) {
149 for (x = 0; x < width; x += 2) {
150 for (c = 0; c < components; c++) {
151 *d++ = (GET(0)+GET(components)+GET(line)+GET(line+components)) / 4;
152 data++;
154 data += components;
156 data += line;
158 else
159 for (y = 0; y < height; y += 2) {
160 for (x = 0; x < width; x += 2) {
161 for (c = 0; c < components; c++) {
162 *d++ = GET(0);
163 data++;
165 data += components;
167 data += line;
170 else if (width > 1 && height == 1) {
171 if (filter)
172 for (y = 0; y < height; y += 1) {
173 for (x = 0; x < width; x += 2) {
174 for (c = 0; c < components; c++) {
175 *d++ = (GET(0)+GET(components)) / 2;
176 data++;
178 data += components;
181 else
182 for (y = 0; y < height; y += 1) {
183 for (x = 0; x < width; x += 2) {
184 for (c = 0; c < components; c++) {
185 *d++ = GET(0);
186 data++;
188 data += components;
192 else if (width == 1 && height > 1) {
193 if (filter)
194 for (y = 0; y < height; y += 2) {
195 for (x = 0; x < width; x += 1) {
196 for (c = 0; c < components; c++) {
197 *d++ = (GET(0)+GET(line)) / 2;
198 data++;
201 data += line;
203 else
204 for (y = 0; y < height; y += 2) {
205 for (x = 0; x < width; x += 1) {
206 for (c = 0; c < components; c++) {
207 *d++ = GET(0);
208 data++;
211 data += line;
214 else {
215 return 0;
218 return 1;
221 #undef GET
223 /* Replacement for gluBuild2DMipmaps so GLU isn't needed */
224 static void Build2DMipmaps(GLint components, GLint width, GLint height, GLenum format, const unsigned char *data, int filter) {
225 int level = 0;
226 unsigned char *d = (unsigned char *) malloc((width/2)*(height/2)*components+4);
227 const unsigned char *last = data;
229 glTexImage2D(GL_TEXTURE_2D, level, components, width, height, 0, format, GL_UNSIGNED_BYTE, data);
230 level++;
232 while (HalfSize(components, width, height, last, d, filter)) {
233 if (width > 1) width /= 2;
234 if (height > 1) height /= 2;
236 glTexImage2D(GL_TEXTURE_2D, level, components, width, height, 0, format, GL_UNSIGNED_BYTE, d);
237 level++;
238 last = d;
241 free(d);
244 int APIENTRY pngLoadRaw(const char *filename, pngRawInfo *pinfo) {
245 int result;
246 FILE *fp = fopen(filename, "rb");
247 if (fp == NULL) return 0;
249 result = pngLoadRawF(fp, pinfo);
251 if (fclose(fp) != 0) {
252 if (result) {
253 free(pinfo->Data);
254 free(pinfo->Palette);
256 return 0;
259 return result;
262 int APIENTRY pngLoadRawF(FILE *fp, pngRawInfo *pinfo) {
263 unsigned char header[8];
264 png_structp png;
265 png_infop info;
266 png_infop endinfo;
267 double fileGamma;
269 png_uint_32 width, height, i;
270 int depth, color;
272 png_bytep data = NULL;
273 png_bytep *row_p = NULL;
275 if (pinfo == NULL) return 0;
277 fread(header, 1, 8, fp);
278 if (!png_check_sig(header, 8)) return 0;
280 png = png_create_read_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL);
281 if (!png) return 0;
282 info = png_create_info_struct(png);
283 if (!info) return 0;
284 endinfo = png_create_info_struct(png);
285 if (!endinfo) return 0;
287 if (setjmp(png_jmpbuf(png)))
288 goto error;
290 png_init_io(png, fp);
291 png_set_sig_bytes(png, 8);
292 png_read_info(png, info);
293 png_get_IHDR(png, info, &width, &height, &depth, &color, NULL, NULL, NULL);
295 pinfo->Width = width;
296 pinfo->Height = height;
297 pinfo->Depth = depth;
299 /*--GAMMA--*/
300 checkForGammaEnv();
301 if (png_get_gAMA(png, info, &fileGamma))
302 png_set_gamma(png, screenGamma, fileGamma);
303 else
304 png_set_gamma(png, screenGamma, 1.0/2.2);
306 png_read_update_info(png, info);
308 /* HDG: We allocate all the png data in one linear array, thus
309 height * png_get_rowbytes() may not be > PNG_UINT_32_MAX !
310 This check fixes CVE-2010-1519. */
311 if ((uint64_t)height * png_get_rowbytes(png, info) > PNG_UINT_32_MAX)
312 goto error;
314 data = (png_bytep) malloc(png_get_rowbytes(png, info)*height);
315 row_p = (png_bytep *) malloc(sizeof(png_bytep)*height);
316 if (!data || !row_p)
317 goto error;
319 for (i = 0; i < height; i++) {
320 if (StandardOrientation)
321 row_p[height - 1 - i] = &data[png_get_rowbytes(png, info)*i];
322 else
323 row_p[i] = &data[png_get_rowbytes(png, info)*i];
326 png_read_image(png, row_p);
327 free(row_p);
328 row_p = NULL;
330 if (color == PNG_COLOR_TYPE_PALETTE) {
331 int cols;
332 png_get_PLTE(png, info, (png_colorp *) &pinfo->Palette, &cols);
334 else {
335 pinfo->Palette = NULL;
338 if (color&PNG_COLOR_MASK_ALPHA) {
339 if (color&PNG_COLOR_MASK_PALETTE || color == PNG_COLOR_TYPE_GRAY_ALPHA)
340 pinfo->Components = 2;
341 else
342 pinfo->Components = 4;
343 pinfo->Alpha = 8;
345 else {
346 if (color&PNG_COLOR_MASK_PALETTE || color == PNG_COLOR_TYPE_GRAY)
347 pinfo->Components = 1;
348 else
349 pinfo->Components = 3;
350 pinfo->Alpha = 0;
353 pinfo->Data = data;
355 png_read_end(png, endinfo);
356 png_destroy_read_struct(&png, &info, &endinfo);
357 return 1;
359 error:
360 png_destroy_read_struct(&png, &info, &endinfo);
361 free(data);
362 free(row_p);
363 return 0;
366 static int pngLoadCommon(int mipmap, int trans, pngInfo *pinfo, png_structp png, png_infop info, png_infop endinfo) {
367 GLint pack, unpack;
368 double fileGamma;
370 png_uint_32 width, height, rw, rh, i;
371 int depth, color;
373 png_bytep data = NULL, data2 = NULL;
374 png_bytep *row_p = NULL;
376 int ret = 0;
378 png_set_sig_bytes(png, 8);
379 png_read_info(png, info);
380 png_get_IHDR(png, info, &width, &height, &depth, &color, NULL, NULL, NULL);
382 if (pinfo != NULL) {
383 pinfo->Width = width;
384 pinfo->Height = height;
385 pinfo->Depth = depth;
388 if (MaxTextureSize == 0)
389 glGetIntegerv(GL_MAX_TEXTURE_SIZE, &MaxTextureSize);
391 #ifdef SUPPORTS_PALETTE_EXT
392 #ifdef _WIN32
393 if (PalettedTextures == -1)
394 PalettedTextures = ExtSupported("GL_EXT_paletted_texture") && (strstr((const char *) glGetString(GL_VERSION), "1.1.0 3Dfx Beta") == NULL);
396 if (PalettedTextures) {
397 if (glColorTableEXT == NULL) {
398 glColorTableEXT = (PFNGLCOLORTABLEEXTPROC) wglGetProcAddress("glColorTableEXT");
399 if (glColorTableEXT == NULL)
400 PalettedTextures = 0;
403 #endif
404 #endif
406 if (PalettedTextures == -1)
407 PalettedTextures = 0;
409 if (color == PNG_COLOR_TYPE_GRAY || color == PNG_COLOR_TYPE_GRAY_ALPHA)
410 png_set_gray_to_rgb(png);
412 if (color&PNG_COLOR_MASK_ALPHA && trans != PNG_ALPHA) {
413 png_set_strip_alpha(png);
414 color &= ~PNG_COLOR_MASK_ALPHA;
417 if (!(PalettedTextures && mipmap >= 0 && trans == PNG_SOLID))
418 if (color == PNG_COLOR_TYPE_PALETTE)
419 png_set_expand(png);
421 /*--GAMMA--*/
422 checkForGammaEnv();
423 if (png_get_gAMA(png, info, &fileGamma))
424 png_set_gamma(png, screenGamma, fileGamma);
425 else
426 png_set_gamma(png, screenGamma, 1.0/2.2);
428 png_read_update_info(png, info);
430 /* HDG: We allocate all the png data in one linear array, thus
431 height * png_get_rowbytes() may not be > PNG_UINT_32_MAX !
432 This check fixes CVE-2010-1519. */
433 if ((uint64_t)height * png_get_rowbytes(png, info) > PNG_UINT_32_MAX)
434 goto finish;
436 data = (png_bytep) malloc(png_get_rowbytes(png, info)*height);
437 row_p = (png_bytep *) malloc(sizeof(png_bytep)*height);
438 if (!data || !row_p)
439 goto finish;
441 for (i = 0; i < height; i++) {
442 if (StandardOrientation)
443 row_p[height - 1 - i] = &data[png_get_rowbytes(png, info)*i];
444 else
445 row_p[i] = &data[png_get_rowbytes(png, info)*i];
448 png_read_image(png, row_p);
449 free(row_p);
450 row_p = NULL;
452 rw = SafeSize(width), rh = SafeSize(height);
454 if (rw != width || rh != height) {
455 const int channels = png_get_rowbytes(png, info)/width;
457 data2 = (png_bytep) malloc(rw*rh*channels);
458 if (!data2)
459 goto finish;
461 /* Doesn't work on certain sizes */
462 /* if (gluScaleImage(glformat, width, height, GL_UNSIGNED_BYTE, data, rw, rh, GL_UNSIGNED_BYTE, data2) != 0)
463 goto finish;
465 Resize(channels, data, width, height, data2, rw, rh);
467 width = rw, height = rh;
468 free(data);
469 data = data2;
470 data2 = NULL;
473 { /* OpenGL stuff */
474 glGetIntegerv(GL_PACK_ALIGNMENT, &pack);
475 glGetIntegerv(GL_UNPACK_ALIGNMENT, &unpack);
476 glPixelStorei(GL_PACK_ALIGNMENT, 1);
477 glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
479 #ifdef SUPPORTS_PALETTE_EXT
480 if (PalettedTextures && mipmap >= 0 && trans == PNG_SOLID && color == PNG_COLOR_TYPE_PALETTE) {
481 png_colorp pal;
482 int cols;
483 GLint intf;
485 if (pinfo != NULL) pinfo->Alpha = 0;
486 png_get_PLTE(png, info, &pal, &cols);
488 switch (cols) {
489 case 1<<1: intf = GL_COLOR_INDEX1_EXT; break;
490 case 1<<2: intf = GL_COLOR_INDEX2_EXT; break;
491 case 1<<4: intf = GL_COLOR_INDEX4_EXT; break;
492 case 1<<8: intf = GL_COLOR_INDEX8_EXT; break;
493 case 1<<12: intf = GL_COLOR_INDEX12_EXT; break;
494 case 1<<16: intf = GL_COLOR_INDEX16_EXT; break;
495 default:
496 /*printf("Warning: Colour depth %i not recognised\n", cols);*/
497 goto finish;
499 glColorTableEXT(GL_TEXTURE_2D, GL_RGB8, cols, GL_RGB, GL_UNSIGNED_BYTE, pal);
500 glTexImage2D(GL_TEXTURE_2D, mipmap, intf, width, height, 0, GL_COLOR_INDEX, GL_UNSIGNED_BYTE, data);
502 else
503 #endif
504 if (trans == PNG_SOLID || trans == PNG_ALPHA || color == PNG_COLOR_TYPE_RGB_ALPHA || color == PNG_COLOR_TYPE_GRAY_ALPHA) {
505 GLenum glformat;
506 GLint glcomponent;
508 switch (color) {
509 case PNG_COLOR_TYPE_GRAY:
510 case PNG_COLOR_TYPE_RGB:
511 case PNG_COLOR_TYPE_PALETTE:
512 glformat = GL_RGB;
513 glcomponent = 3;
514 if (pinfo != NULL) pinfo->Alpha = 0;
515 break;
517 case PNG_COLOR_TYPE_GRAY_ALPHA:
518 case PNG_COLOR_TYPE_RGB_ALPHA:
519 glformat = GL_RGBA;
520 glcomponent = 4;
521 if (pinfo != NULL) pinfo->Alpha = 8;
522 break;
524 default:
525 /*puts("glformat not set");*/
526 goto finish;
529 if (mipmap == PNG_BUILDMIPMAPS)
530 Build2DMipmaps(glcomponent, width, height, glformat, data, 1);
531 else if (mipmap == PNG_SIMPLEMIPMAPS)
532 Build2DMipmaps(glcomponent, width, height, glformat, data, 0);
533 else
534 glTexImage2D(GL_TEXTURE_2D, mipmap, glcomponent, width, height, 0, glformat, GL_UNSIGNED_BYTE, data);
536 else {
537 png_bytep p, endp, q;
538 int r, g, b, a;
540 /* HDG another potential 32 bit address overflow, the
541 original png had 3 channels and we are going to
542 4 channels now! */
543 if ((uint64_t)width * height > (PNG_UINT_32_MAX >> 2))
544 goto finish;
546 p = data, endp = p+width*height*3;
547 q = data2 = (png_bytep) malloc(sizeof(png_byte)*width*height*4);
549 if (pinfo != NULL) pinfo->Alpha = 8;
551 #define FORSTART \
552 do { \
553 r = *p++; /*red */ \
554 g = *p++; /*green*/ \
555 b = *p++; /*blue */ \
556 *q++ = r; \
557 *q++ = g; \
558 *q++ = b;
560 #define FOREND \
561 q++; \
562 } while (p != endp);
564 #define ALPHA *q
566 switch (trans) {
567 case PNG_CALLBACKT:
568 FORSTART
569 ALPHA = AlphaCallback((unsigned char) r, (unsigned char) g, (unsigned char) b);
570 FOREND
571 break;
573 case PNG_STENCIL:
574 FORSTART
575 if (r == StencilRed && g == StencilGreen && b == StencilBlue)
576 ALPHA = 0;
577 else
578 ALPHA = 255;
579 FOREND
580 break;
582 case PNG_BLEND1:
583 FORSTART
584 a = r+g+b;
585 if (a > 255) ALPHA = 255; else ALPHA = a;
586 FOREND
587 break;
589 case PNG_BLEND2:
590 FORSTART
591 a = r+g+b;
592 if (a > 255*2) ALPHA = 255; else ALPHA = a/2;
593 FOREND
594 break;
596 case PNG_BLEND3:
597 FORSTART
598 ALPHA = (r+g+b)/3;
599 FOREND
600 break;
602 case PNG_BLEND4:
603 FORSTART
604 a = r*r+g*g+b*b;
605 if (a > 255) ALPHA = 255; else ALPHA = a;
606 FOREND
607 break;
609 case PNG_BLEND5:
610 FORSTART
611 a = r*r+g*g+b*b;
612 if (a > 255*2) ALPHA = 255; else ALPHA = a/2;
613 FOREND
614 break;
616 case PNG_BLEND6:
617 FORSTART
618 a = r*r+g*g+b*b;
619 if (a > 255*3) ALPHA = 255; else ALPHA = a/3;
620 FOREND
621 break;
623 case PNG_BLEND7:
624 FORSTART
625 a = r*r+g*g+b*b;
626 if (a > 255*255) ALPHA = 255; else ALPHA = (int) sqrt(a);
627 FOREND
628 break;
631 #undef FORSTART
632 #undef FOREND
633 #undef ALPHA
635 if (mipmap == PNG_BUILDMIPMAPS)
636 Build2DMipmaps(4, width, height, GL_RGBA, data2, 1);
637 else if (mipmap == PNG_SIMPLEMIPMAPS)
638 Build2DMipmaps(4, width, height, GL_RGBA, data2, 0);
639 else
640 glTexImage2D(GL_TEXTURE_2D, mipmap, 4, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, data2);
644 glPixelStorei(GL_PACK_ALIGNMENT, pack);
645 glPixelStorei(GL_UNPACK_ALIGNMENT, unpack);
646 } /* OpenGL end */
648 png_read_end(png, endinfo);
649 ret = 1;
651 finish:
652 free(data);
653 free(data2);
654 free(row_p);
655 return ret;
658 int APIENTRY pngLoad(const char *filename, int mipmap, int trans, pngInfo *pinfo) {
659 int result;
660 FILE *fp = fopen(filename, "rb");
661 if (fp == NULL) return 0;
663 result = pngLoadF(fp, mipmap, trans, pinfo);
665 if (fclose(fp) != 0) return 0;
667 return result;
670 int APIENTRY pngLoadF(FILE *fp, int mipmap, int trans, pngInfo *pinfo) {
671 unsigned char header[8];
672 png_structp png;
673 png_infop info;
674 png_infop endinfo;
676 int ret = 0;
678 fread(header, 1, 8, fp);
679 if (!png_check_sig(header, 8)) return 0;
681 png = png_create_read_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL);
682 if (!png) return 0;
683 info = png_create_info_struct(png);
684 if (!info) return 0;
685 endinfo = png_create_info_struct(png);
686 if (!endinfo) return 0;
688 if (!setjmp(png_jmpbuf(png))) {
689 png_init_io(png, fp);
690 ret = pngLoadCommon(mipmap, trans, pinfo, png, info, endinfo);
693 png_destroy_read_struct(&png, &info, &endinfo);
694 return ret;
697 typedef struct glpng_memread_struct {
698 png_bytep mem;
699 png_size_t rpos;
700 } glpng_memread;
702 static void glpng_read_mem(png_structp png, png_bytep dst, png_size_t size) {
703 glpng_memread *mr = (glpng_memread*) png_get_io_ptr(png);
704 memcpy(dst, mr->mem + mr->rpos, size);
705 mr->rpos += size;
708 int APIENTRY pngLoadMem(const char *mem, int size, int mipmap, int trans, pngInfo *pinfo) {
709 unsigned char header[8];
710 png_structp png;
711 png_infop info;
712 png_infop endinfo;
713 glpng_memread memread;
715 int ret = 0;
717 if (size < 8)
718 return 0; // error
720 memcpy(header, mem, 8);
721 if (!png_check_sig(header, 8)) return 0;
723 png = png_create_read_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL);
724 if (!png) return 0;
725 info = png_create_info_struct(png);
726 if (!info) return 0;
727 endinfo = png_create_info_struct(png);
728 if (!endinfo) return 0;
730 if (!setjmp(png_jmpbuf(png))) {
731 memread.rpos = 0;
732 memread.mem = ((png_bytep) mem) + 8;
733 png_set_read_fn(png, &memread, glpng_read_mem);
734 ret = pngLoadCommon(mipmap, trans, pinfo, png, info, endinfo);
737 png_destroy_read_struct(&png, &info, &endinfo);
738 return ret;
741 static unsigned int SetParams(int wrapst, int magfilter, int minfilter) {
742 unsigned int id;
744 glGenTextures(1, &id);
745 glBindTexture(GL_TEXTURE_2D, id);
747 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, wrapst);
748 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, wrapst);
750 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, magfilter);
751 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, minfilter);
753 return id;
756 unsigned int APIENTRY pngBind(const char *filename, int mipmap, int trans, pngInfo *info, int wrapst, int minfilter, int magfilter) {
757 unsigned int id = SetParams(wrapst, magfilter, minfilter);
759 if (id != 0 && pngLoad(filename, mipmap, trans, info))
760 return id;
761 return 0;
764 unsigned int APIENTRY pngBindF(FILE *file, int mipmap, int trans, pngInfo *info, int wrapst, int minfilter, int magfilter) {
765 unsigned int id = SetParams(wrapst, magfilter, minfilter);
767 if (id != 0 && pngLoadF(file, mipmap, trans, info))
768 return id;
769 return 0;
772 unsigned int APIENTRY pngBindMem(const char *mem, int size, int mipmap, int trans, pngInfo *info, int wrapst, int minfilter, int magfilter) {
773 unsigned int id = SetParams(wrapst, magfilter, minfilter);
775 if (id != 0 && pngLoadMem(mem, size, mipmap, trans, info))
776 return id;
777 return 0;
780 void APIENTRY pngSetStencil(unsigned char red, unsigned char green, unsigned char blue) {
781 StencilRed = red, StencilGreen = green, StencilBlue = blue;
784 void APIENTRY pngSetAlphaCallback(unsigned char (*callback)(unsigned char red, unsigned char green, unsigned char blue)) {
785 if (callback == NULL)
786 AlphaCallback = DefaultAlphaCallback;
787 else
788 AlphaCallback = callback;
791 void APIENTRY pngSetViewingGamma(double viewingGamma) {
792 if(viewingGamma > 0) {
793 gammaExplicit = 1;
794 screenGamma = 2.2/viewingGamma;
796 else {
797 gammaExplicit = 0;
798 screenGamma = 2.2;
802 void APIENTRY pngSetStandardOrientation(int standardorientation) {
803 StandardOrientation = standardorientation;