📄 glpng.c
字号:
/*
* PNG loader library for OpenGL v1.45 (10/07/00)
* by Ben Wyatt ben@wyatt100.freeserve.co.uk
* Using LibPNG 1.0.2 and ZLib 1.1.3
*
* This software is provided 'as-is', without any express or implied warranty.
* In no event will the author be held liable for any damages arising from the
* use of this software.
*
* Permission is hereby granted to use, copy, modify, and distribute this
* source code, or portions hereof, for any purpose, without fee, subject to
* the following restrictions:
*
* 1. The origin of this source code must not be misrepresented. You must not
* claim that you wrote the original software. If you use this software in
* a product, an acknowledgment in the product documentation would be
* appreciated but is not required.
* 2. Altered versions must be plainly marked as such and must not be
* misrepresented as being the original source.
* 3. This notice must not be removed or altered from any source distribution.
*/
#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
#endif
static 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#endif
static 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;
#endif
static 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); // DH: added following lines
if (setjmp(png->jmpbuf))
{
png_destroy_read_struct(&png, &info, &endinfo);
return 0;
}
// ~DH
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++) { if (StandardOrientation)
row_p[height - 1 - i] = &data[png_get_rowbytes(png, info)*i];
else
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);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -