📄 glpng.c
字号:
#ifdef _WIN32 /* Stupid Windows needs to include windows.h before gl.h */ #undef FAR #include <windows.h>#endif#include <GL/glpng.h>#include <GL/gl.h>#include <stdlib.h>#include <math.h>#include "png/png.h"/* Used to decide if GL/gl.h supports the paletted extension */#ifdef GL_COLOR_INDEX1_EXT#define SUPPORTS_PALETTE_EXT#endifstatic unsigned char DefaultAlphaCallback(unsigned char red, unsigned char green, unsigned char blue) { return 255;}static unsigned char StencilRed = 0, StencilGreen = 0, StencilBlue = 0;static unsigned char (*AlphaCallback)(unsigned char red, unsigned char green, unsigned char blue) = DefaultAlphaCallback;static int StandardOrientation = 0;#ifdef SUPPORTS_PALETTE_EXT#ifdef _WIN32static PFNGLCOLORTABLEEXTPROC glColorTableEXT = NULL;#endif#endifstatic int PalettedTextures = -1;static GLint MaxTextureSize = 0;/* screenGamma = displayGamma/viewingGamma * displayGamma = CRT has gamma of ~2.2 * viewingGamma depends on platform. PC is 1.0, Mac is 1.45, SGI defaults * to 1.7, but this can be checked and changed w/ /usr/sbin/gamma command. * If the environment variable VIEWING_GAMMA is set, adjust gamma per this value. */#ifdef _MAC static double screenGamma = 2.2 / 1.45;#elif SGI static double screenGamma = 2.2 / 1.7;#else /* PC/default */ static double screenGamma = 2.2 / 1.0;#endifstatic char gammaExplicit = 0; /*if */static void checkForGammaEnv(){ double viewingGamma; char *gammaEnv = getenv("VIEWING_GAMMA"); if(gammaEnv && !gammaExplicit) { sscanf(gammaEnv, "%lf", &viewingGamma); screenGamma = 2.2/viewingGamma; }}/* Returns a safe texture size to use (ie a power of 2), based on the current texture size "i" */static int SafeSize(int i) { int p; if (i > MaxTextureSize) return MaxTextureSize; for (p = 0; p < 24; p++) if (i <= (1<<p)) return 1<<p; return MaxTextureSize;}/* Resize the texture since gluScaleImage doesn't work on everything */static void Resize(int components, const png_bytep d1, int w1, int h1, png_bytep d2, int w2, int h2) { const float sx = (float) w1/w2, sy = (float) h1/h2; int x, y, xx, yy, c; png_bytep d; for (y = 0; y < h2; y++) { yy = (int) (y*sy)*w1; for (x = 0; x < w2; x++) { xx = (int) (x*sx); d = d1 + (yy+xx)*components; for (c = 0; c < components; c++) *d2++ = *d++; } }}static int ExtSupported(const char *x) { static const GLubyte *ext = NULL; const char *c; int xlen = strlen(x); if (ext == NULL) ext = glGetString(GL_EXTENSIONS); c = (const char*)ext; while (*c != '\0') { if (strcmp(c, x) == 0 && (c[xlen] == '\0' || c[xlen] == ' ')) return 1; c++; } return 0;}#define GET(o) ((int)*(data + (o)))static int HalfSize(GLint components, GLint width, GLint height, const unsigned char *data, unsigned char *d, int filter) { int x, y, c; int line = width*components; if (width > 1 && height > 1) { if (filter) for (y = 0; y < height; y += 2) { for (x = 0; x < width; x += 2) { for (c = 0; c < components; c++) { *d++ = (GET(0)+GET(components)+GET(line)+GET(line+components)) / 4; data++; } data += components; } data += line; } else for (y = 0; y < height; y += 2) { for (x = 0; x < width; x += 2) { for (c = 0; c < components; c++) { *d++ = GET(0); data++; } data += components; } data += line; } } else if (width > 1 && height == 1) { if (filter) for (y = 0; y < height; y += 1) { for (x = 0; x < width; x += 2) { for (c = 0; c < components; c++) { *d++ = (GET(0)+GET(components)) / 2; data++; } data += components; } } else for (y = 0; y < height; y += 1) { for (x = 0; x < width; x += 2) { for (c = 0; c < components; c++) { *d++ = GET(0); data++; } data += components; } } } else if (width == 1 && height > 1) { if (filter) for (y = 0; y < height; y += 2) { for (x = 0; x < width; x += 1) { for (c = 0; c < components; c++) { *d++ = (GET(0)+GET(line)) / 2; data++; } } data += line; } else for (y = 0; y < height; y += 2) { for (x = 0; x < width; x += 1) { for (c = 0; c < components; c++) { *d++ = GET(0); data++; } } data += line; } } else { return 0; } return 1;}#undef GET/* Replacement for gluBuild2DMipmaps so GLU isn't needed */static void Build2DMipmaps(GLint components, GLint width, GLint height, GLenum format, const unsigned char *data, int filter) { int level = 0; unsigned char *d = (unsigned char *) malloc((width/2)*(height/2)*components+4); const unsigned char *last = data; glTexImage2D(GL_TEXTURE_2D, level, components, width, height, 0, format, GL_UNSIGNED_BYTE, data); level++; while (HalfSize(components, width, height, last, d, filter)) { if (width > 1) width /= 2; if (height > 1) height /= 2; glTexImage2D(GL_TEXTURE_2D, level, components, width, height, 0, format, GL_UNSIGNED_BYTE, d); level++; last = d; } free(d);}int APIENTRY pngLoadRaw(const char *filename, pngRawInfo *pinfo) { int result; FILE *fp = fopen(filename, "rb"); if (fp == NULL) return 0; result = pngLoadRawF(fp, pinfo); if (fclose(fp) != 0) { if (result) { free(pinfo->Data); free(pinfo->Palette); } return 0; } return result;}int APIENTRY pngLoadRawF(FILE *fp, pngRawInfo *pinfo) { unsigned char header[8]; png_structp png; png_infop info; png_infop endinfo; png_bytep data; png_bytep *row_p; double fileGamma; png_uint_32 width, height; int depth, color; png_uint_32 i; if (pinfo == NULL) return 0; fread(header, 1, 8, fp); if (!png_check_sig(header, 8)) return 0; png = png_create_read_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL); info = png_create_info_struct(png); endinfo = png_create_info_struct(png); png_init_io(png, fp); png_set_sig_bytes(png, 8); png_read_info(png, info); png_get_IHDR(png, info, &width, &height, &depth, &color, NULL, NULL, NULL); pinfo->Width = width; pinfo->Height = height; pinfo->Depth = depth; /*--GAMMA--*/ checkForGammaEnv(); if (png_get_gAMA(png, info, &fileGamma)) png_set_gamma(png, screenGamma, fileGamma); else png_set_gamma(png, screenGamma, 1.0/2.2); png_read_update_info(png, info); data = (png_bytep) malloc(png_get_rowbytes(png, info)*height); row_p = (png_bytep *) malloc(sizeof(png_bytep)*height); for (i = 0; i < height; i++) row_p[i] = &data[png_get_rowbytes(png, info)*i]; png_read_image(png, row_p); free(row_p); if (color == PNG_COLOR_TYPE_PALETTE) { int cols; png_get_PLTE(png, info, (png_colorp *) &pinfo->Palette, &cols); } else { pinfo->Palette = NULL; } if (color&PNG_COLOR_MASK_ALPHA) { if (color&PNG_COLOR_MASK_PALETTE || color == PNG_COLOR_TYPE_GRAY_ALPHA) pinfo->Components = 2; else pinfo->Components = 4; pinfo->Alpha = 8; } else { if (color&PNG_COLOR_MASK_PALETTE || color == PNG_COLOR_TYPE_GRAY) pinfo->Components = 1; else pinfo->Components = 3; pinfo->Alpha = 0; } pinfo->Data = data; png_read_end(png, endinfo); png_destroy_read_struct(&png, &info, &endinfo); return 1;}int APIENTRY pngLoad(const char *filename, int mipmap, int trans, pngInfo *pinfo) { int result; FILE *fp = fopen(filename, "rb"); if (fp == NULL) return 0; result = pngLoadF(fp, mipmap, trans, pinfo); if (fclose(fp) != 0) return 0; return result;}int APIENTRY pngLoadF(FILE *fp, int mipmap, int trans, pngInfo *pinfo) { GLint pack, unpack; unsigned char header[8]; png_structp png; png_infop info; png_infop endinfo; png_bytep data, data2; png_bytep *row_p; double fileGamma;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -