libresman
changeset 1:469ce01809bc
rudimentary imgthumbs "example program". doesn't use libresman yet
author | John Tsiombikas <nuclear@member.fsf.org> |
---|---|
date | Fri, 31 Jan 2014 03:17:24 +0200 |
parents | 61d7ff6da54b |
children | 026cdd1737ff |
files | .hgignore examples/imgthumbs/Makefile examples/imgthumbs/src/main.c examples/imgthumbs/src/opengl.h examples/imgthumbs/src/thumbs.c examples/imgthumbs/src/thumbs.h src/resman.h |
diffstat | 7 files changed, 464 insertions(+), 35 deletions(-) [+] |
line diff
1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/.hgignore Fri Jan 31 03:17:24 2014 +0200 1.3 @@ -0,0 +1,17 @@ 1.4 +\.o$ 1.5 +\.swp$ 1.6 +\.d$ 1.7 +^libresman.so 1.8 +^libresman.a 1.9 +\.jpg$ 1.10 +\.png$ 1.11 +\.gif$ 1.12 +\.tga$ 1.13 +\.jpeg$ 1.14 +\.targa$ 1.15 +\.tif$ 1.16 +\.bmp$ 1.17 +\.ppm$ 1.18 +\.pnm$ 1.19 +\.xpm$ 1.20 +\.rgba$
2.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 2.2 +++ b/examples/imgthumbs/Makefile Fri Jan 31 03:17:24 2014 +0200 2.3 @@ -0,0 +1,19 @@ 2.4 +src = $(wildcard src/*.c) 2.5 +obj = $(src:.c=.o) 2.6 +bin = imgthumbs 2.7 + 2.8 +CFLAGS = -pedantic -Wall -g -I../../src 2.9 +LDFLAGS = $(libgl) -limago 2.10 + 2.11 +ifeq ($(shell uname -s), Darwin) 2.12 + libgl = -framework OpenGL -framework GLUT 2.13 +else 2.14 + libgl = -lGL -lGLU -lglut 2.15 +endif 2.16 + 2.17 +$(bin): $(obj) 2.18 + $(CC) -o $@ $(obj) $(LDFLAGS) 2.19 + 2.20 +.PHONY: clean 2.21 +clean: 2.22 + rm -f $(obj) $(bin)
3.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 3.2 +++ b/examples/imgthumbs/src/main.c Fri Jan 31 03:17:24 2014 +0200 3.3 @@ -0,0 +1,232 @@ 3.4 +#include <stdio.h> 3.5 +#include <stdlib.h> 3.6 +#include <assert.h> 3.7 +#include "opengl.h" 3.8 +#include "resman.h" 3.9 +#include "thumbs.h" 3.10 + 3.11 +static int init(void); 3.12 +static void cleanup(void); 3.13 +static void display(void); 3.14 +/*static void idle(void);*/ 3.15 +static void reshape(int x, int y); 3.16 +static void keyb(unsigned char key, int x, int y); 3.17 +static void mouse(int bn, int st, int x, int y); 3.18 +static void motion(int x, int y); 3.19 +static struct thumbnail *find_thumb(int x, int y); 3.20 + 3.21 +const char *path = "."; 3.22 +struct resman *texman; 3.23 +int win_width, win_height; 3.24 +float win_aspect; 3.25 +float pan_x, pan_y; 3.26 +float show_pan_x, show_pan_y; 3.27 +float show_zoom = 1.0; 3.28 +float thumbs_size = 0.25; 3.29 + 3.30 +struct thumbnail *thumbs, *show_thumb; 3.31 + 3.32 +int main(int argc, char **argv) 3.33 +{ 3.34 + glutInit(&argc, argv); 3.35 + 3.36 + if(argv[1]) { 3.37 + path = argv[1]; 3.38 + } 3.39 + 3.40 + glutInitWindowSize(800, 600); 3.41 + glutInitDisplayMode(GLUT_RGB | GLUT_DOUBLE); 3.42 + glutCreateWindow("imgthumbs"); 3.43 + 3.44 + glutDisplayFunc(display); 3.45 + glutReshapeFunc(reshape); 3.46 + glutKeyboardFunc(keyb); 3.47 + glutMouseFunc(mouse); 3.48 + glutMotionFunc(motion); 3.49 + 3.50 + if(init() == -1) { 3.51 + return 1; 3.52 + } 3.53 + atexit(cleanup); 3.54 + 3.55 + glutMainLoop(); 3.56 + return 0; 3.57 +} 3.58 + 3.59 +static int init(void) 3.60 +{ 3.61 + thumbs = create_thumbs(path); 3.62 + return 0; 3.63 +} 3.64 + 3.65 +static void cleanup(void) 3.66 +{ 3.67 + free_thumbs(thumbs); 3.68 +} 3.69 + 3.70 +static void display(void) 3.71 +{ 3.72 + glClear(GL_COLOR_BUFFER_BIT); 3.73 + 3.74 + glMatrixMode(GL_MODELVIEW); 3.75 + glLoadIdentity(); 3.76 + 3.77 + if(show_thumb) { 3.78 + glEnable(GL_TEXTURE_2D); 3.79 + glBindTexture(GL_TEXTURE_2D, show_thumb->tex); 3.80 + 3.81 + glScalef(show_zoom, show_zoom, 1); 3.82 + glTranslatef(2.0 * show_pan_x, 2.0 * show_pan_y, 0); 3.83 + if(show_thumb->aspect >= 1.0) { 3.84 + glScalef(1, 1.0 / show_thumb->aspect, 1); 3.85 + } else { 3.86 + glScalef(show_thumb->aspect, 1, 1); 3.87 + } 3.88 + 3.89 + glBegin(GL_QUADS); 3.90 + glColor3f(1, 1, 1); 3.91 + glTexCoord2f(0, 0); glVertex2f(-1, -1); 3.92 + glTexCoord2f(1, 0); glVertex2f(1, -1); 3.93 + glTexCoord2f(1, 1); glVertex2f(1, 1); 3.94 + glTexCoord2f(0, 1); glVertex2f(-1, 1); 3.95 + glEnd(); 3.96 + 3.97 + glDisable(GL_TEXTURE_2D); 3.98 + } else { 3.99 + draw_thumbs(thumbs, thumbs_size, pan_y); 3.100 + } 3.101 + 3.102 + glutSwapBuffers(); 3.103 + assert(glGetError() == GL_NO_ERROR); 3.104 +} 3.105 + 3.106 +/* 3.107 +static void idle(void) 3.108 +{ 3.109 + glutPostRedisplay(); 3.110 +} 3.111 +*/ 3.112 + 3.113 +static void reshape(int x, int y) 3.114 +{ 3.115 + win_aspect = (float)x / (float)y; 3.116 + 3.117 + glViewport(0, 0, x, y); 3.118 + 3.119 + glMatrixMode(GL_PROJECTION); 3.120 + glLoadIdentity(); 3.121 + glOrtho(-1, 1, 1.0 / win_aspect, -1.0 / win_aspect, -1, 1); 3.122 + 3.123 + win_width = x; 3.124 + win_height = y; 3.125 +} 3.126 + 3.127 +static void keyb(unsigned char key, int x, int y) 3.128 +{ 3.129 + switch(key) { 3.130 + case 27: 3.131 + exit(0); 3.132 + 3.133 + case ' ': 3.134 + show_zoom = 1.0; 3.135 + thumbs_size = 0.25; 3.136 + pan_x = pan_y = show_pan_x = show_pan_y = 0; 3.137 + glutPostRedisplay(); 3.138 + break; 3.139 + } 3.140 +} 3.141 + 3.142 +static int bnstate[32]; 3.143 +static int prev_x, prev_y; 3.144 +static int click_x[32], click_y[32]; 3.145 + 3.146 +static void mouse(int bn, int st, int x, int y) 3.147 +{ 3.148 + int bidx = bn - GLUT_LEFT_BUTTON; 3.149 + int state = st == GLUT_DOWN ? 1 : 0; 3.150 + 3.151 + bnstate[bidx] = state; 3.152 + 3.153 + prev_x = x; 3.154 + prev_y = y; 3.155 + 3.156 + if(state) { 3.157 + click_x[bidx] = x; 3.158 + click_y[bidx] = y; 3.159 + } else { 3.160 + int is_drag = abs(x - click_x[bidx]) > 3 || abs(y - click_y[bidx]) > 3; 3.161 + 3.162 + if(bidx == 0) { 3.163 + if(!show_thumb) { 3.164 + if(!is_drag) { 3.165 + struct thumbnail *sel = find_thumb(x, y); 3.166 + if(sel) { 3.167 + show_thumb = sel; 3.168 + show_pan_x = show_pan_y = 0; 3.169 + glutPostRedisplay(); 3.170 + } 3.171 + } 3.172 + } 3.173 + } else { 3.174 + if(!is_drag) { 3.175 + show_thumb = 0; 3.176 + glutPostRedisplay(); 3.177 + } 3.178 + } 3.179 + } 3.180 +} 3.181 + 3.182 +static void motion(int x, int y) 3.183 +{ 3.184 + int dx = x - prev_x; 3.185 + int dy = y - prev_y; 3.186 + prev_x = x; 3.187 + prev_y = y; 3.188 + 3.189 + if(!dx && !dy) return; 3.190 + 3.191 + if(bnstate[0]) { 3.192 + float fdx = dx / (float)win_width; 3.193 + float fdy = dy / (float)win_height / win_aspect; 3.194 + 3.195 + if(show_thumb) { 3.196 + show_pan_x += fdx / show_zoom; 3.197 + show_pan_y += fdy / show_zoom; 3.198 + } else { 3.199 + pan_x += fdx; 3.200 + pan_y += fdy; 3.201 + } 3.202 + glutPostRedisplay(); 3.203 + } 3.204 + 3.205 + if(bnstate[2]) { 3.206 + if(show_thumb) { 3.207 + show_zoom -= dy * 0.0075; 3.208 + if(show_zoom <= 0) show_zoom = 0; 3.209 + } else { 3.210 + thumbs_size -= dy * 0.005; 3.211 + if(thumbs_size <= 0.01) thumbs_size = 0.01; 3.212 + } 3.213 + glutPostRedisplay(); 3.214 + } 3.215 +} 3.216 + 3.217 +static struct thumbnail *find_thumb(int x, int y) 3.218 +{ 3.219 + float fx = (float)x / (float)win_width; 3.220 + float fy = (float)y / (float)win_height / win_aspect; 3.221 + struct thumbnail *node; 3.222 + 3.223 + node = thumbs; 3.224 + while(node) { 3.225 + float nx = node->layout_pos[0]; 3.226 + float ny = node->layout_pos[1]; 3.227 + 3.228 + if(fx >= nx && fx < nx + node->layout_size[0] && 3.229 + fy >= ny && fy < ny + node->layout_size[1]) { 3.230 + return node; 3.231 + } 3.232 + node = node->next; 3.233 + } 3.234 + return 0; 3.235 +}
4.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 4.2 +++ b/examples/imgthumbs/src/opengl.h Fri Jan 31 03:17:24 2014 +0200 4.3 @@ -0,0 +1,10 @@ 4.4 +#ifndef OPENGL_H_ 4.5 +#define OPENGL_H_ 4.6 + 4.7 +#ifdef __APPLE__ 4.8 +#include <GLUT/glut.h> 4.9 +#else 4.10 +#include <GL/glut.h> 4.11 +#endif 4.12 + 4.13 +#endif /* OPENGL_H_ */
5.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 5.2 +++ b/examples/imgthumbs/src/thumbs.c Fri Jan 31 03:17:24 2014 +0200 5.3 @@ -0,0 +1,152 @@ 5.4 +#include <stdio.h> 5.5 +#include <stdlib.h> 5.6 +#include <string.h> 5.7 +#include <errno.h> 5.8 +#include <dirent.h> 5.9 +#include <imago2.h> 5.10 +#include "opengl.h" 5.11 +#include "thumbs.h" 5.12 + 5.13 +struct thumbnail *create_thumbs(const char *dirpath) 5.14 +{ 5.15 + DIR *dir; 5.16 + struct dirent *dent; 5.17 + struct thumbnail *list = 0; 5.18 + 5.19 + if(!(dir = opendir(dirpath))) { 5.20 + fprintf(stderr, "failed to open directory: %s: %s\n", dirpath, strerror(errno)); 5.21 + return 0; 5.22 + } 5.23 + 5.24 + while((dent = readdir(dir))) { 5.25 + int xsz, ysz; 5.26 + unsigned char *pixels; 5.27 + struct thumbnail *node; 5.28 + 5.29 + if(!(node = malloc(sizeof *node))) { 5.30 + perror("failed to allocate thumbnail list node"); 5.31 + continue; 5.32 + } 5.33 + 5.34 + if(!(node->fname = malloc(strlen(dirpath) + strlen(dent->d_name) + 2))) { 5.35 + free(node); 5.36 + continue; 5.37 + } 5.38 + strcpy(node->fname, dirpath); 5.39 + if(dirpath[strlen(dirpath) - 1] != '/') { 5.40 + strcat(node->fname, "/"); 5.41 + } 5.42 + strcat(node->fname, dent->d_name); 5.43 + 5.44 + if(!(pixels = img_load_pixels(node->fname, &xsz, &ysz, IMG_FMT_RGBA32))) { 5.45 + free(node->fname); 5.46 + free(node); 5.47 + continue; 5.48 + } 5.49 + 5.50 + printf("loaded image: %s\n", node->fname); 5.51 + 5.52 + glGenTextures(1, &node->tex); 5.53 + glBindTexture(GL_TEXTURE_2D, node->tex); 5.54 + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); 5.55 + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); 5.56 + glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, xsz, ysz, 0, GL_RGBA, GL_UNSIGNED_BYTE, pixels); 5.57 + img_free_pixels(pixels); 5.58 + 5.59 + node->aspect = (float)xsz / (float)ysz; 5.60 + 5.61 + node->next = list; 5.62 + list = node; 5.63 + } 5.64 + closedir(dir); 5.65 + 5.66 + return list; 5.67 +} 5.68 + 5.69 +void free_thumbs(struct thumbnail *thumbs) 5.70 +{ 5.71 + if(!thumbs) return; 5.72 + 5.73 + while(thumbs) { 5.74 + struct thumbnail *tmp = thumbs; 5.75 + thumbs = thumbs->next; 5.76 + 5.77 + free(tmp->fname); 5.78 + free(tmp); 5.79 + } 5.80 +} 5.81 + 5.82 + 5.83 +void draw_thumbs(struct thumbnail *thumbs, float thumb_sz, float start_y) 5.84 +{ 5.85 + int vp[4]; 5.86 + float gap = thumb_sz / 4.0; 5.87 + float x = gap; 5.88 + float y = gap + start_y; 5.89 + float view_aspect; 5.90 + 5.91 + glGetIntegerv(GL_VIEWPORT, vp); 5.92 + view_aspect = (float)(vp[2] - vp[0]) / (vp[3] - vp[1]); 5.93 + 5.94 + glMatrixMode(GL_PROJECTION); 5.95 + glPushMatrix(); 5.96 + glLoadIdentity(); 5.97 + glOrtho(0, 1, 1.0 / view_aspect, 0, -1, 1); 5.98 + 5.99 + glMatrixMode(GL_MODELVIEW); 5.100 + 5.101 + while(thumbs) { 5.102 + 5.103 + glPushMatrix(); 5.104 + glTranslatef(x, y, 0); 5.105 + 5.106 + glScalef(thumb_sz, thumb_sz, 1); 5.107 + 5.108 + glBegin(GL_QUADS); 5.109 + glColor3f(0.25, 0.25, 0.25); 5.110 + glTexCoord2f(0, 0); glVertex2f(0, 0); 5.111 + glTexCoord2f(1, 0); glVertex2f(1, 0); 5.112 + glTexCoord2f(1, 1); glVertex2f(1, 1); 5.113 + glTexCoord2f(0, 1); glVertex2f(0, 1); 5.114 + glEnd(); 5.115 + 5.116 + if(thumbs->aspect >= 1.0) { 5.117 + glTranslatef(0, 0.5 - 0.5 / thumbs->aspect, 0); 5.118 + glScalef(1, 1.0 / thumbs->aspect, 1); 5.119 + } else { 5.120 + glTranslatef(0.5 - thumbs->aspect / 2.0, 0, 0); 5.121 + glScalef(thumbs->aspect, 1, 1); 5.122 + } 5.123 + 5.124 + glEnable(GL_TEXTURE_2D); 5.125 + glBindTexture(GL_TEXTURE_2D, thumbs->tex); 5.126 + 5.127 + glBegin(GL_QUADS); 5.128 + glColor3f(1, 1, 1); 5.129 + glTexCoord2f(0, 0); glVertex2f(0, 0); 5.130 + glTexCoord2f(1, 0); glVertex2f(1, 0); 5.131 + glTexCoord2f(1, 1); glVertex2f(1, 1); 5.132 + glTexCoord2f(0, 1); glVertex2f(0, 1); 5.133 + glEnd(); 5.134 + 5.135 + glPopMatrix(); 5.136 + glDisable(GL_TEXTURE_2D); 5.137 + 5.138 + thumbs->layout_pos[0] = x; 5.139 + thumbs->layout_pos[1] = y; 5.140 + thumbs->layout_size[0] = thumb_sz; 5.141 + thumbs->layout_size[1] = thumb_sz; 5.142 + 5.143 + x += thumb_sz + gap; 5.144 + if(x >= 1.0 - thumb_sz) { 5.145 + x = gap; 5.146 + y += thumb_sz + gap; 5.147 + } 5.148 + 5.149 + thumbs = thumbs->next; 5.150 + } 5.151 + 5.152 + glMatrixMode(GL_PROJECTION); 5.153 + glPopMatrix(); 5.154 + glMatrixMode(GL_MODELVIEW); 5.155 +}
6.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 6.2 +++ b/examples/imgthumbs/src/thumbs.h Fri Jan 31 03:17:24 2014 +0200 6.3 @@ -0,0 +1,21 @@ 6.4 +#ifndef THUMBS_H_ 6.5 +#define THUMBS_H_ 6.6 + 6.7 + 6.8 +struct thumbnail { 6.9 + char *fname; 6.10 + unsigned int tex; 6.11 + float aspect; 6.12 + 6.13 + float layout_pos[2]; 6.14 + float layout_size[2]; 6.15 + 6.16 + struct thumbnail *next; 6.17 +}; 6.18 + 6.19 +struct thumbnail *create_thumbs(const char *dirpath); 6.20 +void free_thumbs(struct thumbnail *thumbs); 6.21 + 6.22 +void draw_thumbs(struct thumbnail *thumbs, float thumb_sz, float start_y); 6.23 + 6.24 +#endif /* THUMBS_H_ */
7.1 --- a/src/resman.h Wed Jan 29 08:17:31 2014 +0200 7.2 +++ b/src/resman.h Fri Jan 31 03:17:24 2014 +0200 7.3 @@ -1,53 +1,31 @@ 7.4 #ifndef RESOURCE_MANAGER_H_ 7.5 #define RESOURCE_MANAGER_H_ 7.6 7.7 -/* TODO API */ 7.8 - 7.9 -/* usage example: 7.10 -int texload(const char *fname, void *cls) 7.11 -{ 7.12 - // open image, parse data ... 7.13 -} 7.14 - 7.15 -struct resman rman; 7.16 - 7.17 -resman_init(&rman); 7.18 -resman_set_load_func(&rman, texload, 0); 7.19 -resman_set_done_func(&rman, texload_done, 0); 7.20 -... 7.21 - 7.22 -struct texture *tex; 7.23 -struct resman_job *rjob; 7.24 - 7.25 -rjob = resman_get(&rman, "tex.png", 0); 7.26 -... 7.27 -resman_wait_job(&rman, rjob); 7.28 -tex = resman_get_job_data(rjob); 7.29 -resman_free_job(&rman, rjob); 7.30 - 7.31 -... 7.32 -resman_destroy(&rman); 7.33 -*/ 7.34 - 7.35 struct resman; 7.36 7.37 -typedef int (*resman_load_func_t)(const char *fname, void *cls); 7.38 -typedef void (*resman_done_func_t)(int status, void *cls); 7.39 - 7.40 - 7.41 int resman_init(struct resman *rman); 7.42 void resman_destroy(struct resman *rman); 7.43 7.44 /* The load callback will be called to load a data file. It may be called in the 7.45 * context of a different loading thread. 7.46 */ 7.47 -void resman_set_load_func(struct resman *rman, resman_load_func_t func, void *cls); 7.48 +/*void resman_set_load_func(struct resman *rman, resman_load_func_t func, void *cls);*/ 7.49 7.50 /* The "done" callback will be called in the context of the main thread, whenever a 7.51 * file was sucessfully loaded, or an error occured. 7.52 * It's first argument (status) is set to whatever the load function returned, and its 7.53 - * closure pointer is the closure 7.54 + * closure pointer is the closure ... 7.55 */ 7.56 -void resman_set_done_func(struct resman *rman, resman_done_func_t func); 7.57 +/*void resman_set_done_func(struct resman *rman, resman_done_func_t func);*/ 7.58 + 7.59 + 7.60 +int resman_lookup(struct resman *rman, const char *fname, void *cls); 7.61 +void resman_wait(struct resman *rman, int id); 7.62 + 7.63 +int resman_poll(struct resman *rman); 7.64 + 7.65 +void resman_set_res_data(struct resman *rman, int res_id, void *data); 7.66 +void *resman_get_res_data(struct resman *rman, int res_id); 7.67 + 7.68 7.69 #endif /* RESOURCE_MANAGER_H_ */