nuclear@1: #include nuclear@1: #include nuclear@1: #include nuclear@1: #include nuclear@1: #include nuclear@1: #include nuclear@1: #include "opengl.h" nuclear@1: #include "thumbs.h" nuclear@1: nuclear@6: #ifndef GL_COMPRESSED_RGB nuclear@6: #define GL_COMPRESSED_RGB 0x84ed nuclear@6: #endif nuclear@6: nuclear@1: struct thumbnail *create_thumbs(const char *dirpath) nuclear@1: { nuclear@1: DIR *dir; nuclear@1: struct dirent *dent; nuclear@1: struct thumbnail *list = 0; nuclear@1: nuclear@2: unsigned int intfmt = GL_COMPRESSED_RGB; nuclear@6: if(!strstr(glGetString(GL_EXTENSIONS), "GL_ARB_texture_compression")) { nuclear@2: printf("warning, no texture compression available.\n"); nuclear@2: intfmt = GL_RGB; nuclear@2: } nuclear@2: nuclear@1: if(!(dir = opendir(dirpath))) { nuclear@1: fprintf(stderr, "failed to open directory: %s: %s\n", dirpath, strerror(errno)); nuclear@1: return 0; nuclear@1: } nuclear@1: nuclear@1: while((dent = readdir(dir))) { nuclear@1: int xsz, ysz; nuclear@1: unsigned char *pixels; nuclear@1: struct thumbnail *node; nuclear@1: nuclear@1: if(!(node = malloc(sizeof *node))) { nuclear@1: perror("failed to allocate thumbnail list node"); nuclear@1: continue; nuclear@1: } nuclear@1: nuclear@1: if(!(node->fname = malloc(strlen(dirpath) + strlen(dent->d_name) + 2))) { nuclear@1: free(node); nuclear@1: continue; nuclear@1: } nuclear@1: strcpy(node->fname, dirpath); nuclear@1: if(dirpath[strlen(dirpath) - 1] != '/') { nuclear@1: strcat(node->fname, "/"); nuclear@1: } nuclear@1: strcat(node->fname, dent->d_name); nuclear@1: nuclear@1: if(!(pixels = img_load_pixels(node->fname, &xsz, &ysz, IMG_FMT_RGBA32))) { nuclear@1: free(node->fname); nuclear@1: free(node); nuclear@1: continue; nuclear@1: } nuclear@1: nuclear@1: printf("loaded image: %s\n", node->fname); nuclear@1: nuclear@1: glGenTextures(1, &node->tex); nuclear@1: glBindTexture(GL_TEXTURE_2D, node->tex); nuclear@1: glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); nuclear@1: glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); nuclear@2: glTexImage2D(GL_TEXTURE_2D, 0, intfmt, xsz, ysz, 0, GL_RGBA, GL_UNSIGNED_BYTE, pixels); nuclear@1: img_free_pixels(pixels); nuclear@1: nuclear@1: node->aspect = (float)xsz / (float)ysz; nuclear@1: nuclear@1: node->next = list; nuclear@1: list = node; nuclear@1: } nuclear@1: closedir(dir); nuclear@1: nuclear@1: return list; nuclear@1: } nuclear@1: nuclear@1: void free_thumbs(struct thumbnail *thumbs) nuclear@1: { nuclear@1: if(!thumbs) return; nuclear@1: nuclear@1: while(thumbs) { nuclear@1: struct thumbnail *tmp = thumbs; nuclear@1: thumbs = thumbs->next; nuclear@1: nuclear@1: free(tmp->fname); nuclear@1: free(tmp); nuclear@1: } nuclear@1: } nuclear@1: nuclear@1: nuclear@1: void draw_thumbs(struct thumbnail *thumbs, float thumb_sz, float start_y) nuclear@1: { nuclear@1: int vp[4]; nuclear@1: float gap = thumb_sz / 4.0; nuclear@1: float x = gap; nuclear@1: float y = gap + start_y; nuclear@1: float view_aspect; nuclear@1: nuclear@1: glGetIntegerv(GL_VIEWPORT, vp); nuclear@1: view_aspect = (float)(vp[2] - vp[0]) / (vp[3] - vp[1]); nuclear@1: nuclear@1: glMatrixMode(GL_PROJECTION); nuclear@1: glPushMatrix(); nuclear@1: glLoadIdentity(); nuclear@1: glOrtho(0, 1, 1.0 / view_aspect, 0, -1, 1); nuclear@1: nuclear@1: glMatrixMode(GL_MODELVIEW); nuclear@1: nuclear@1: while(thumbs) { nuclear@1: nuclear@1: glPushMatrix(); nuclear@1: glTranslatef(x, y, 0); nuclear@1: nuclear@1: glScalef(thumb_sz, thumb_sz, 1); nuclear@1: nuclear@1: glBegin(GL_QUADS); nuclear@1: glColor3f(0.25, 0.25, 0.25); nuclear@1: glTexCoord2f(0, 0); glVertex2f(0, 0); nuclear@1: glTexCoord2f(1, 0); glVertex2f(1, 0); nuclear@1: glTexCoord2f(1, 1); glVertex2f(1, 1); nuclear@1: glTexCoord2f(0, 1); glVertex2f(0, 1); nuclear@1: glEnd(); nuclear@1: nuclear@1: if(thumbs->aspect >= 1.0) { nuclear@1: glTranslatef(0, 0.5 - 0.5 / thumbs->aspect, 0); nuclear@1: glScalef(1, 1.0 / thumbs->aspect, 1); nuclear@1: } else { nuclear@1: glTranslatef(0.5 - thumbs->aspect / 2.0, 0, 0); nuclear@1: glScalef(thumbs->aspect, 1, 1); nuclear@1: } nuclear@1: nuclear@1: glEnable(GL_TEXTURE_2D); nuclear@1: glBindTexture(GL_TEXTURE_2D, thumbs->tex); nuclear@1: nuclear@1: glBegin(GL_QUADS); nuclear@1: glColor3f(1, 1, 1); nuclear@1: glTexCoord2f(0, 0); glVertex2f(0, 0); nuclear@1: glTexCoord2f(1, 0); glVertex2f(1, 0); nuclear@1: glTexCoord2f(1, 1); glVertex2f(1, 1); nuclear@1: glTexCoord2f(0, 1); glVertex2f(0, 1); nuclear@1: glEnd(); nuclear@1: nuclear@1: glPopMatrix(); nuclear@1: glDisable(GL_TEXTURE_2D); nuclear@1: nuclear@1: thumbs->layout_pos[0] = x; nuclear@1: thumbs->layout_pos[1] = y; nuclear@1: thumbs->layout_size[0] = thumb_sz; nuclear@1: thumbs->layout_size[1] = thumb_sz; nuclear@1: nuclear@1: x += thumb_sz + gap; nuclear@1: if(x >= 1.0 - thumb_sz) { nuclear@1: x = gap; nuclear@1: y += thumb_sz + gap; nuclear@1: } nuclear@1: nuclear@1: thumbs = thumbs->next; nuclear@1: } nuclear@1: nuclear@1: glMatrixMode(GL_PROJECTION); nuclear@1: glPopMatrix(); nuclear@1: glMatrixMode(GL_MODELVIEW); nuclear@1: }