-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathTexture.cpp
More file actions
118 lines (93 loc) · 2.48 KB
/
Texture.cpp
File metadata and controls
118 lines (93 loc) · 2.48 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
#include "Texture.h"
#include <png.h>
#include <GL/gl.h>
#include <stdlib.h>
#include <stdio.h>
#define CLEANUP(x) { ret = (x); goto cleanup; }
int png_to_gl_texture(struct CTexture* tex, char const * const filename) {
int ret = 0;
FILE * file = 0;
uint8_t * data = 0;
png_structp parser = 0;
png_infop info = 0;
png_bytep * row_pointers = 0;
int rowbytes;
GLenum texture_format;
png_uint_32 w, h;
int bit_depth;
int color_type;
if(!tex || !filename) {
CLEANUP(1);
}
file = fopen(filename, "rb");
if(!file) {
CLEANUP(2);
}
parser = png_create_read_struct(PNG_LIBPNG_VER_STRING, 0, 0, 0);
if(!parser) {
CLEANUP(3);
}
info = png_create_info_struct(parser);
if(!info) {
CLEANUP(4);
}
if(setjmp(png_jmpbuf(parser))) {
CLEANUP(5);
}
png_init_io(parser, file);
png_read_info(parser, info);
png_get_IHDR(parser, info, &w, &h, &bit_depth, &color_type, 0, 0, 0);
if((w & (w-1)) || (h & (h-1)) || w < 8 || h < 8) {
CLEANUP(6); // non power 2 texture
}
if(png_get_valid(parser, info, PNG_INFO_tRNS) || (color_type == PNG_COLOR_TYPE_GRAY && bit_depth < 8) || color_type == PNG_COLOR_TYPE_PALETTE) {
png_set_expand(parser);
}
if(bit_depth == 16) {
png_set_strip_16(parser);
}
if(color_type == PNG_COLOR_TYPE_GRAY || color_type == PNG_COLOR_TYPE_GRAY_ALPHA) {
png_set_gray_to_rgb(parser);
}
png_read_update_info(parser, info);
rowbytes = png_get_rowbytes(parser, info);
rowbytes += 3 - ((rowbytes-1) % 4); // align to 4 bytes
data = (uint8_t*)malloc(rowbytes * h * sizeof(png_byte) + 15);
if(!data) {
CLEANUP(7);
}
row_pointers = (png_bytep*)malloc(h * sizeof(png_bytep));
if(!row_pointers) {
CLEANUP(8);
}
// set the individual row_pointers to point at the correct offsets of data
for(png_uint_32 i = 0; i < h; ++i) {
row_pointers[h - 1 - i] = data + i * rowbytes;
}
png_read_image(parser, row_pointers);
// Generate the OpenGL texture object
GLuint texture_id;
glGenTextures(1, &texture_id);
glBindTexture(GL_TEXTURE_2D, texture_id);
texture_format = (color_type & PNG_COLOR_MASK_ALPHA) ? GL_RGBA : GL_RGB;
glTexImage2D(GL_TEXTURE_2D, 0, texture_format, w, h, 0, texture_format, GL_UNSIGNED_BYTE, data);
tex->id = texture_id;
tex->w = w;
tex->h = h;
tex->format = texture_format;
tex->min_filter = tex->mag_filter = GL_NEAREST;
cleanup:
if(parser) {
png_destroy_read_struct(&parser, info ? &info : 0, 0);
}
if(row_pointers) {
free(row_pointers);
}
if(ret && data) {
free(data);
}
if(file) {
fclose(file);
}
return ret;
}