summaryrefslogtreecommitdiffstats
path: root/texture.c
diff options
context:
space:
mode:
Diffstat (limited to 'texture.c')
-rw-r--r--texture.c194
1 files changed, 135 insertions, 59 deletions
diff --git a/texture.c b/texture.c
index 276fc94..2d6112b 100644
--- a/texture.c
+++ b/texture.c
@@ -3,69 +3,145 @@
#include <string.h>
#include <GL/gl.h>
#include <zoom/texture.h>
-
-
-#pragma pack(push,2)
-typedef struct _TEXHEADER {
- unsigned char t;
- unsigned char x;
- unsigned long w;
- unsigned long h;
-} TEXHEADER;
-#pragma pack(pop)
+#include <png.h>
int nTex;
TEXLIST *texlist;
+
GLuint LoadTexture(char *filename) {
- GLuint tex;
- FILE *file;
- TEXHEADER txh;
- unsigned char *data;
- int i;
- char name[100];
-
- for(i = 0; i < nTex; i++) {
- if(strcasecmp(filename, texlist[i].name) == 0) return texlist[i].id;
- }
-
- strcpy(name, "tex/");
- strcat(name, filename);
- file = fopen(name, "rb");
- if(!file) return 0;
-
- fread(&txh, sizeof(txh), 1, file);
- if(txh.t != 'T' || txh.x != 'X') {
- fclose(file);
- return 0;
- }
-
- data = malloc(txh.w*txh.h*4);
- if(!data) {
- fclose(file);
- return 0;
- }
- fread(data, txh.w*txh.h*4, 1, file);
-
- glGenTextures(1, &tex);
- glBindTexture(GL_TEXTURE_2D, tex);
- glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
- glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
- glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
- glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
- glTexImage2D(GL_TEXTURE_2D, 0, 4, txh.w, txh.h, 0, GL_RGBA, GL_UNSIGNED_BYTE, data);
-
- free(data);
- fclose(file);
-
- nTex++;
-
- if(nTex == 1) texlist = malloc(sizeof(TEXLIST));
- else texlist = realloc(texlist, sizeof(TEXLIST)*nTex);
-
- strcpy(texlist[nTex-1].name, filename);
- texlist[nTex-1].id = tex;
-
- return tex;
+ FILE *file;
+ GLuint tex;
+ char *name;
+ png_byte header[8];
+ png_structp png_ptr;
+ png_infop info_ptr;
+ png_bytep *row_pointers;
+ png_bytep data;
+ png_uint_32 width, height;
+ int bit_depth, color_type, i;
+ GLenum format;
+
+
+ for(i = 0; i < nTex; i++) {
+ if(strcasecmp(filename, texlist[i].name) == 0) return texlist[i].id;
+ }
+
+ name = malloc(strlen(filename)+5);
+ strcpy(name, "tex/");
+ strcat(name, filename);
+
+ file = fopen(name, "rb");
+
+ free(name);
+
+ if(!file) return 0;
+
+ fread(&header, 1, sizeof(header), file);
+ if(png_sig_cmp(header, 0, sizeof(header))) {
+ fclose(file);
+ return 0;
+ }
+
+ png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL);
+ if(!png_ptr) {
+ fclose(file);
+ return 0;
+ }
+
+ info_ptr = png_create_info_struct(png_ptr);
+ if(!info_ptr) {
+ png_destroy_read_struct(&png_ptr, NULL, NULL);
+ fclose(file);
+ return 0;
+ }
+
+ if(setjmp(png_jmpbuf(png_ptr))) {
+ png_destroy_read_struct(&png_ptr, &info_ptr, NULL);
+ fclose(file);
+ return 0;
+ }
+
+ png_init_io(png_ptr, file);
+ png_set_sig_bytes(png_ptr, sizeof(header));
+
+ png_read_info(png_ptr, info_ptr);
+
+ width = png_get_image_width(png_ptr, info_ptr);
+ height = png_get_image_height(png_ptr, info_ptr);
+ bit_depth = png_get_bit_depth(png_ptr, info_ptr);
+ color_type = png_get_color_type(png_ptr, info_ptr);
+
+ if(color_type == PNG_COLOR_TYPE_PALETTE)
+ png_set_palette_to_rgb(png_ptr);
+ if(color_type == PNG_COLOR_TYPE_GRAY && bit_depth < 8)
+ png_set_expand_gray_1_2_4_to_8(png_ptr);
+ if(png_get_valid(png_ptr, info_ptr, PNG_INFO_tRNS))
+ png_set_tRNS_to_alpha(png_ptr);
+ if(bit_depth < 8)
+ png_set_packing(png_ptr);
+
+ png_read_update_info(png_ptr, info_ptr);
+
+ bit_depth = png_get_bit_depth(png_ptr, info_ptr);
+ color_type = png_get_color_type(png_ptr, info_ptr);
+
+ if((bit_depth != 8 && bit_depth != 16) || color_type & PNG_COLOR_MASK_PALETTE) {
+ png_destroy_read_struct(&png_ptr, &info_ptr, NULL);
+ fclose(file);
+ return 0;
+ }
+
+ data = png_malloc(png_ptr, png_get_rowbytes(png_ptr, info_ptr)*height);
+ row_pointers = png_malloc(png_ptr, height*png_sizeof(png_bytep));
+ for(i = 0; i < height; i++)
+ row_pointers[i] = data + png_get_rowbytes(png_ptr, info_ptr)*i;
+
+ png_read_image(png_ptr, row_pointers);
+
+ switch(color_type) {
+ case PNG_COLOR_TYPE_GRAY:
+ format = GL_LUMINANCE;
+ break;
+ case PNG_COLOR_TYPE_GRAY_ALPHA:
+ format = GL_LUMINANCE_ALPHA;
+ break;
+ case PNG_COLOR_TYPE_RGB:
+ format = GL_RGB;
+ break;
+ case PNG_COLOR_TYPE_RGBA:
+ format = GL_RGBA;
+ break;
+ default:
+ png_destroy_read_struct(&png_ptr, &info_ptr, NULL);
+ fclose(file);
+ return 0;
+ }
+
+ glGenTextures(1, &tex);
+ glBindTexture(GL_TEXTURE_2D, tex);
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
+ glTexImage2D(GL_TEXTURE_2D, 0, png_get_channels(png_ptr, info_ptr), width, height, 0,
+ format, (bit_depth == 8) ? GL_UNSIGNED_BYTE : GL_UNSIGNED_SHORT, data);
+
+ png_free(png_ptr, row_pointers);
+ png_free(png_ptr, data);
+
+ png_destroy_read_struct(&png_ptr, &info_ptr, NULL);
+
+ fclose(file);
+
+ nTex++;
+
+ if(nTex == 1) texlist = malloc(sizeof(TEXLIST));
+ else texlist = realloc(texlist, sizeof(TEXLIST)*nTex);
+
+ strcpy(texlist[nTex-1].name, filename);
+ texlist[nTex-1].id = tex;
+
+ return tex;
}