/* Copyright (C) 2000 Paul Wilkins This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /* render.c by Paul Wilkins 1/2/2000 */ #include #include #include #include #include #include "globals.h" #include "read_db.h" #include "display.h" #include "stats.h" #include "status.h" #include "find_match.h" #include "draw_image.h" #include "cursor.h" #include "render_image.h" #include "render.h" #define STATS_SIZE 6 struct PIX { int cnt; double r; double g; double b; }; #define PIX_VAL(ptr, x, y) (((ptr)->rgb_data) + (3*((x)+((y)*((ptr)->rgb_width)))) ) void average_image_area(struct PIX *avg, GdkImlibImage *im, int x, int y, int w, int h){ int i, j; unsigned char *p1; int r, g, b; int xx, yy; /* printf("average_image_area: x: %d y: %d w: %d h: %d\n", x, y, w, h); */ avg->r = 0.0; avg->g = 0.0; avg->b = 0.0; for(j=0; jr += r; avg->g += g; avg->b += b; } } avg->cnt = w * h; avg->r /= (double)(w*h); avg->g /= (double)(w*h); avg->b /= (double)(w*h); /* printf("average_image_area: r: %g g: %g b: %g\n", avg->r, avg->g, avg->b); */ } double calc_stddev(GdkImlibImage *im, int x, int y, int nPixW, int nPixH){ int w, h, n; int xx, yy, ww, hh; int pxx, pyy; double xoff, yoff; double meanR, stdR; double meanG, stdG; double meanB, stdB; struct PIX avg; double dataR[STATS_SIZE*STATS_SIZE]; double dataG[STATS_SIZE*STATS_SIZE]; double dataB[STATS_SIZE*STATS_SIZE]; /* printf("calc_stddev: x: %d y: %d\n", x, y); */ xoff = (double)x / (double)nPixW * (double)im->rgb_width; yoff = (double)y / (double)nPixH * (double)im->rgb_height; n = 0; pyy = (int)yoff; for(h=0; hrgb_height / (double)nPixH / (double)STATS_SIZE); hh = yy - pyy; pxx = (int)xoff; for(w=0; wrgb_width / (double)nPixW / (double)STATS_SIZE); ww = xx - pxx; average_image_area(&avg, im, pxx, pyy, ww, hh); dataR[n] = avg.r; dataG[n] = avg.g; dataB[n] = avg.b; n++; pxx = xx; } pyy = yy; } calc_mead_std(dataR, n, &meanR, &stdR); calc_mead_std(dataG, n, &meanG, &stdG); calc_mead_std(dataB, n, &meanB, &stdB); return (stdR + stdG + stdB) / 3.0; } int init_db(){ static int init = 0; if(init == 0){ /* read in the picture database */ if(NULL == (globals.head = read_database(&(globals.max_order)))){ fprintf(stderr, "Error reading database.\n"); exit(1); } init = 1; } return 1; } int *gen_master_data(GdkImlibImage *im, int x, int y, int nPixW, int nPixH, int order){ int w, h; int xx, yy, ww, hh; int pxx, pyy; int *p1; int *data; double xoff, yoff; struct PIX avg; /* this must be free'd outside this function */ if(NULL == (data=malloc(3*order*order*sizeof(int)))){ perror("malloc"); exit(1); } xoff = (double)x / (double)nPixW * (double)im->rgb_width; yoff = (double)y / (double)nPixH * (double)im->rgb_height; pyy = (int)yoff; p1 = data; for(h=0; hrgb_height / (double)nPixH / (double)order); hh = yy - pyy; pxx = (int)xoff; for(w=0; wrgb_width / (double)nPixW / (double)order); ww = xx - pxx; average_image_area(&avg, im, pxx, pyy, ww, hh); *p1++ = (int)avg.r; *p1++ = (int)avg.g; *p1++ = (int)avg.b; pxx = xx; } pyy = yy; } return data; } void free_image_data(){ int ww, hh; if(globals.image == NULL) return; /* free old image data */ for(hh=0; hh=maxy) continue; for(x=cx-n; x<=cx+n; x++){ if(x<0 || x>=maxx) continue; if(x==cx && y==cy) continue; if(image[y][x].db == match) return 1; } } return 0; } int guess_order(double val, int pixW, int pixH, int max_order){ int order; order = (int)(sqrt((double)(pixW*pixH))/9.0 + (val / 6.0)); if(order > max_order) order = max_order; return order; } int render(){ int i, j; int pixW, pixH; int nPixW, nPixH; int *match_data; int proximity; double percent; GdkImlibImage *im; GdkImlibImage *out_im; int order; int ww, hh; double stddev; struct IMAGE_INFO **image; struct PIC_DB **matches; if(globals.in_fname == NULL || globals.in_im == NULL){ fprintf(stderr, "Error: Open an Image first!\n"); return 0; } /* free the old data, if any */ free_image_data(); /* calculate the new images dimensions */ if(0 == calc_dimensions(&(globals.new_opt))){ fprintf(stderr, "Invalid option. Bye.\n"); return 0; } /* set the cursor */ cursor_busy(); /* copy the image rendering data from new_opt to cur_opt */ if(copy_opt_data()){ resize_window(); } /* update the mode display info */ refresh_mode_display(); /* set our local copies of some of the globals */ im = globals.in_im; pixW = globals.cur_opt.pixW; pixH = globals.cur_opt.pixH; nPixW = globals.cur_opt.nPixW; nPixH = globals.cur_opt.nPixH; /* malloc the array to store the image info */ if(NULL == (image=malloc(nPixH*sizeof(struct IMAGE_INFO *)))){ perror("Malloc"); exit(1); } for(hh=0; hh= nPixW){ ww = 0; hh++; if(hh >= nPixH) hh = 0; } } matches = image[hh][ww].matches; /* pick one of the (hopefully the best) matches to fill this spot */ proximity = globals.cur_opt.proximity; do { for(i=0; i=0 && i == MAX_MATCHES); /* probably only one file */ if(matches[i] == NULL) i = 0; /* store the image we picked */ image[hh][ww].match_no = i; image[hh][ww].db = matches[i]; image[hh][ww].db->refcnt++; image[hh][ww].db->done = 0; } /* render the image */ if(NULL == (out_im = render_image(image, nPixW, nPixH, pixW, pixH))){ fprintf(stderr, "Error: Can't render image.\n"); exit(1); } globals.out_im = out_im; /* display it */ draw_big_image(out_im); /* turn off the progress bar */ toggle_progress_indicator(ST_READY); /* set the cursor */ cursor_normal(); return 1; }