libresman

view examples/imgthumbs/src/thumbs.c @ 13:a42888d26839

bit more progress...
author John Tsiombikas <nuclear@member.fsf.org>
date Sat, 08 Feb 2014 07:41:39 +0200
parents 84f55eab27cb
children 2fcd1fbb0d18 0a789208498d
line source
1 #include <stdio.h>
2 #include <stdlib.h>
3 #include <string.h>
4 #include <errno.h>
5 #include <assert.h>
6 #include <dirent.h>
7 #include <imago2.h>
8 #include "opengl.h"
9 #include "thumbs.h"
10 #include "resman.h"
12 #ifndef GL_COMPRESSED_RGB
13 #define GL_COMPRESSED_RGB 0x84ed
14 #endif
16 struct resman *texman;
18 static int load_res_texture(const char *fname, int id, void *cls);
19 static int done_res_texture(int id, void *cls);
20 static void free_res_texture(int id, void *cls);
23 struct thumbnail *create_thumbs(const char *dirpath)
24 {
25 DIR *dir;
26 struct dirent *dent;
27 /* allocate dummy head node */
28 struct thumbnail *list = calloc(1, sizeof *list);
30 /*unsigned int intfmt = GL_COMPRESSED_RGB;
31 if(!strstr((char*)glGetString(GL_EXTENSIONS), "GL_ARB_texture_compression")) {
32 printf("warning, no texture compression available.\n");
33 intfmt = GL_RGB;
34 }*/
36 if(!texman) {
37 texman = resman_create();
38 resman_set_load_func(texman, load_res_texture, 0);
39 resman_set_done_func(texman, done_res_texture, 0);
40 resman_set_destroy_func(texman, free_res_texture, 0);
41 }
43 if(!(dir = opendir(dirpath))) {
44 fprintf(stderr, "failed to open directory: %s: %s\n", dirpath, strerror(errno));
45 return 0;
46 }
48 while((dent = readdir(dir))) {
49 /*int xsz, ysz;
50 unsigned char *pixels;*/
51 struct thumbnail *node;
53 if(!(node = malloc(sizeof *node))) {
54 perror("failed to allocate thumbnail list node");
55 continue;
56 }
57 memset(node, 0, sizeof *node);
59 if(!(node->fname = malloc(strlen(dirpath) + strlen(dent->d_name) + 2))) {
60 free(node);
61 continue;
62 }
63 strcpy(node->fname, dirpath);
64 if(dirpath[strlen(dirpath) - 1] != '/') {
65 strcat(node->fname, "/");
66 }
67 strcat(node->fname, dent->d_name);
69 node->aspect = 1.0;/*(float)xsz / (float)ysz;*/
71 resman_lookup(texman, node->fname, node);
73 /*if(!(pixels = img_load_pixels(node->fname, &xsz, &ysz, IMG_FMT_RGBA32))) {
74 free(node->fname);
75 free(node);
76 continue;
77 }
79 printf("loaded image: %s\n", node->fname);
81 glGenTextures(1, &node->tex);
82 glBindTexture(GL_TEXTURE_2D, node->tex);
83 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
84 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
85 glTexImage2D(GL_TEXTURE_2D, 0, intfmt, xsz, ysz, 0, GL_RGBA, GL_UNSIGNED_BYTE, pixels);
86 img_free_pixels(pixels);
87 */
89 node->next = list->next;
90 node->prev = list;
91 }
92 closedir(dir);
94 return list;
95 }
97 void free_thumbs(struct thumbnail *thumbs)
98 {
99 if(!thumbs) return;
101 while(thumbs) {
102 struct thumbnail *tmp = thumbs;
103 thumbs = thumbs->next;
105 free(tmp->fname);
106 free(tmp);
107 }
108 }
111 void update_thumbs(void)
112 {
113 resman_poll(texman);
114 }
116 void draw_thumbs(struct thumbnail *thumbs, float thumb_sz, float start_y)
117 {
118 int vp[4];
119 float gap = thumb_sz / 4.0;
120 float x = gap;
121 float y = gap + start_y;
122 float view_aspect;
124 glGetIntegerv(GL_VIEWPORT, vp);
125 view_aspect = (float)(vp[2] - vp[0]) / (vp[3] - vp[1]);
127 glMatrixMode(GL_PROJECTION);
128 glPushMatrix();
129 glLoadIdentity();
130 glOrtho(0, 1, 1.0 / view_aspect, 0, -1, 1);
132 glMatrixMode(GL_MODELVIEW);
134 thumbs = thumbs->next; /* skip dummy node */
135 while(thumbs) {
136 glPushMatrix();
137 glTranslatef(x, y, 0);
139 glScalef(thumb_sz, thumb_sz, 1);
141 glBegin(GL_QUADS);
142 glColor3f(0.25, 0.25, 0.25);
143 glTexCoord2f(0, 0); glVertex2f(0, 0);
144 glTexCoord2f(1, 0); glVertex2f(1, 0);
145 glTexCoord2f(1, 1); glVertex2f(1, 1);
146 glTexCoord2f(0, 1); glVertex2f(0, 1);
147 glEnd();
149 if(thumbs->tex) {
150 if(thumbs->aspect >= 1.0) {
151 glTranslatef(0, 0.5 - 0.5 / thumbs->aspect, 0);
152 glScalef(1, 1.0 / thumbs->aspect, 1);
153 } else {
154 glTranslatef(0.5 - thumbs->aspect / 2.0, 0, 0);
155 glScalef(thumbs->aspect, 1, 1);
156 }
158 if(glIsTexture(thumbs->tex)) {
159 glEnable(GL_TEXTURE_2D);
160 glBindTexture(GL_TEXTURE_2D, thumbs->tex);
162 glBegin(GL_QUADS);
163 glColor3f(1, 1, 1);
164 glTexCoord2f(0, 0); glVertex2f(0, 0);
165 glTexCoord2f(1, 0); glVertex2f(1, 0);
166 glTexCoord2f(1, 1); glVertex2f(1, 1);
167 glTexCoord2f(0, 1); glVertex2f(0, 1);
168 glEnd();
169 } else {
170 fprintf(stderr, "invalid texture: %u\n", thumbs->tex);
171 }
173 glPopMatrix();
174 glDisable(GL_TEXTURE_2D);
175 }
177 thumbs->layout_pos[0] = x;
178 thumbs->layout_pos[1] = y;
179 thumbs->layout_size[0] = thumb_sz;
180 thumbs->layout_size[1] = thumb_sz;
182 x += thumb_sz + gap;
183 if(x >= 1.0 - thumb_sz) {
184 x = gap;
185 y += thumb_sz + gap;
186 }
188 thumbs = thumbs->next;
189 }
191 glMatrixMode(GL_PROJECTION);
192 glPopMatrix();
193 glMatrixMode(GL_MODELVIEW);
194 }
196 static int load_res_texture(const char *fname, int id, void *cls)
197 {
198 struct thumbnail *rdata = resman_get_res_data(texman, id);
200 assert(rdata);
201 if(!rdata->img) {
202 if(!(rdata->img = img_create())) {
203 return -1;
204 }
205 }
207 if(img_load(rdata->img, fname) == -1) {
208 img_free(rdata->img);
209 rdata->img = 0;
210 return -1;
211 }
212 rdata->aspect = (float)rdata->img->width / (float)rdata->img->height;
214 /* set the resource's data to the loaded image, so that we can use
215 * it in the done callback */
216 resman_set_res_data(texman, id, rdata);
217 return 0;
218 }
220 static int done_res_texture(int id, void *cls)
221 {
222 struct thumbnail *rdata = resman_get_res_data(texman, id);
223 int load_result = resman_get_res_result(texman, id);
225 if(load_result == -1) {
226 /* returning -1 will remove this resource, the free_res_texture
227 * destroy handler will be called, which will remove the node
228 * from the list
229 */
230 return -1;
231 }
233 if(resman_get_res_result(texman, id) != 0 || !rdata) {
234 fprintf(stderr, "failed to load resource %d (%s)\n", id, resman_get_res_name(texman, id));
235 } else {
236 printf("done loading resource %d (%s)\n", id, resman_get_res_name(texman, id));
237 }
239 if(!rdata->tex) {
240 glGenTextures(1, &rdata->tex);
241 }
242 glBindTexture(GL_TEXTURE_2D, rdata->tex);
243 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
244 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
245 glTexImage2D(GL_TEXTURE_2D, 0, img_glintfmt(rdata->img),
246 rdata->img->width, rdata->img->height, 0, img_glfmt(rdata->img),
247 img_gltype(rdata->img), rdata->img->pixels);
248 return 0;
249 }
251 static void free_res_texture(int id, void *cls)
252 {
253 struct thumbnail *thumb = resman_get_res_data(texman, id);
255 if(thumb) {
256 if(thumb->tex) {
257 glDeleteTextures(1, &thumb->tex);
258 }
259 if(thumb->img) {
260 img_free(thumb->img);
261 }
262 }
264 /* remove from the list */
265 if(thumb->prev) {
266 thumb->prev->next = thumb->next;
267 }
268 if(thumb->next) {
269 thumb->next->prev = thumb->prev;
270 }
271 free(thumb);
272 }