| 1 |
#include "pictool.h"
|
| 2 |
#include "g3sphere.h"
|
| 3 |
#include <math.h>
|
| 4 |
#include <string.h>
|
| 5 |
|
| 6 |
#define index strchr
|
| 7 |
|
| 8 |
|
| 9 |
|
| 10 |
int pict_init(pict* p)
|
| 11 |
{
|
| 12 |
p->pic = NULL;
|
| 13 |
p->use_lut = 0;
|
| 14 |
p->lut = NULL;
|
| 15 |
p->pjitter = 0;
|
| 16 |
p->comment[0] = '\0';
|
| 17 |
#ifdef PICT_GLARE
|
| 18 |
p->pinfo = NULL;
|
| 19 |
p->glareinfo = g3fl_create(PICT_GLSIZE);
|
| 20 |
#endif
|
| 21 |
p->valid_view = 1;
|
| 22 |
p->view = stdview;
|
| 23 |
if (!pict_update_view(p))
|
| 24 |
return 0;
|
| 25 |
p->resol.rt = PIXSTANDARD;
|
| 26 |
return pict_resize(p,512,512);
|
| 27 |
}
|
| 28 |
|
| 29 |
void pict_new_gli(pict* p)
|
| 30 |
{
|
| 31 |
int i;
|
| 32 |
|
| 33 |
g3Float* gli;
|
| 34 |
gli = g3fl_append_new(p->glareinfo);
|
| 35 |
for(i=0;i<PICT_GLSIZE;i++)
|
| 36 |
gli[i] = 0.0;
|
| 37 |
}
|
| 38 |
|
| 39 |
void pict_set_comment(pict* p,const char* c)
|
| 40 |
{
|
| 41 |
strcpy(p->comment,c);
|
| 42 |
}
|
| 43 |
|
| 44 |
pict* pict_get_copy(pict* p)
|
| 45 |
{
|
| 46 |
pict* res;
|
| 47 |
|
| 48 |
if (p->use_lut) {
|
| 49 |
fprintf(stderr,"pict_get_copy: can't copy in lut mode");
|
| 50 |
return NULL;
|
| 51 |
}
|
| 52 |
res = pict_create();
|
| 53 |
pict_resize(res,pict_get_xsize(p),pict_get_ysize(p));
|
| 54 |
res->view = p->view;
|
| 55 |
res->resol = p->resol;
|
| 56 |
res->pjitter = p->pjitter;
|
| 57 |
return res;
|
| 58 |
}
|
| 59 |
|
| 60 |
pict* pict_create()
|
| 61 |
{
|
| 62 |
pict* p = (pict*) malloc(sizeof(pict));
|
| 63 |
|
| 64 |
if (!pict_init(p)) {
|
| 65 |
pict_free(p);
|
| 66 |
return NULL;
|
| 67 |
}
|
| 68 |
return p;
|
| 69 |
}
|
| 70 |
|
| 71 |
void pict_free(pict* p)
|
| 72 |
{
|
| 73 |
if (p->pic)
|
| 74 |
free(p->pic);
|
| 75 |
#ifdef PICT_GLARE
|
| 76 |
if (p->pinfo)
|
| 77 |
free(p->pinfo);
|
| 78 |
g3fl_free(p->glareinfo);
|
| 79 |
p->pinfo = NULL;
|
| 80 |
#endif
|
| 81 |
p->pic = NULL;
|
| 82 |
p->lut = NULL;
|
| 83 |
free(p);
|
| 84 |
}
|
| 85 |
static int exp_headline(char* s,void* exparg) {
|
| 86 |
double* exposure;
|
| 87 |
|
| 88 |
exposure = (double*) exparg;
|
| 89 |
if (isexpos(s)) {
|
| 90 |
(*exposure) *= exposval(s);
|
| 91 |
}
|
| 92 |
return 0;
|
| 93 |
}
|
| 94 |
|
| 95 |
static double read_exposure(FILE* fp)
|
| 96 |
{
|
| 97 |
double exposure = 1;
|
| 98 |
|
| 99 |
|
| 100 |
if ((getheader(fp, exp_headline, &exposure)) < 0) {
|
| 101 |
fprintf(stderr,"error reading header\n");
|
| 102 |
return 0;
|
| 103 |
}
|
| 104 |
return exposure;
|
| 105 |
}
|
| 106 |
|
| 107 |
int pict_update_view(pict* p)
|
| 108 |
{
|
| 109 |
char* ret;
|
| 110 |
if ((ret = setview(&(p->view)))) {
|
| 111 |
fprintf(stderr,"pict_update_view: %s\n",ret);
|
| 112 |
return 0;
|
| 113 |
}
|
| 114 |
return 1;
|
| 115 |
}
|
| 116 |
|
| 117 |
int pict_set_pj(pict* p,double pj)
|
| 118 |
{
|
| 119 |
if ((pj < 0) || (pj > 1))
|
| 120 |
fprintf(stderr,"pict_set_pj: warning jitter factor out of range\n");
|
| 121 |
p->pjitter = pj;
|
| 122 |
return 1;
|
| 123 |
}
|
| 124 |
|
| 125 |
int pict_setvup(pict* p,FVECT vup)
|
| 126 |
{
|
| 127 |
VCOPY(p->view.vup,vup);
|
| 128 |
return pict_update_view(p);
|
| 129 |
}
|
| 130 |
|
| 131 |
int pict_trans_cam(pict* p,g3ATrans t)
|
| 132 |
{
|
| 133 |
g3Vec o = g3v_create();
|
| 134 |
g3Vec d = g3v_create();
|
| 135 |
g3Vec u = g3v_create();
|
| 136 |
|
| 137 |
fprintf(stderr,"vdpre %f %f %f\n",p->view.vdir[0],p->view.vdir[1],p->view.vdir[2]);
|
| 138 |
fprintf(stderr,"vupre %f %f %f\n",p->view.vup[0],p->view.vup[1],p->view.vup[2]);
|
| 139 |
g3v_fromrad(o,p->view.vp);
|
| 140 |
g3v_fromrad(d,p->view.vdir);
|
| 141 |
g3v_fromrad(u,p->view.vup);
|
| 142 |
|
| 143 |
g3v_add(d,d,o);
|
| 144 |
g3v_add(u,u,o);
|
| 145 |
g3at_apply(t,o);
|
| 146 |
g3at_apply(t,u);
|
| 147 |
g3at_apply(t,d);
|
| 148 |
g3v_sub(d,d,o);
|
| 149 |
g3v_sub(u,u,o);
|
| 150 |
g3v_torad(p->view.vp,o);
|
| 151 |
g3v_torad(p->view.vdir,d);
|
| 152 |
g3v_torad(p->view.vup,u);
|
| 153 |
fprintf(stderr,"vd %f %f %f\n",p->view.vdir[0],p->view.vdir[1],p->view.vdir[2]);
|
| 154 |
fprintf(stderr,"vu %f %f %f\n",p->view.vup[0],p->view.vup[1],p->view.vup[2]);
|
| 155 |
|
| 156 |
g3v_free(o);
|
| 157 |
g3v_free(d);
|
| 158 |
g3v_free(u);
|
| 159 |
return pict_update_view(p);
|
| 160 |
}
|
| 161 |
|
| 162 |
int pict_resize(pict* p,int x,int y)
|
| 163 |
{
|
| 164 |
p->resol.xr = x;
|
| 165 |
p->resol.yr = y;
|
| 166 |
|
| 167 |
if (!(p->pic = (COLOR*) realloc(p->pic,(p->resol.xr)*(p->resol.yr)*sizeof(COLOR)))) {
|
| 168 |
fprintf(stderr,"Can't alloc picture\n");
|
| 169 |
return 0;
|
| 170 |
}
|
| 171 |
if (pict_lut_used(p)) {
|
| 172 |
if (!(p->lut = (COLOR*) realloc(p->lut,(p->resol.xr)*(p->resol.yr)*sizeof(COLOR)))) {
|
| 173 |
fprintf(stderr,"Can't alloc LUT\n");
|
| 174 |
return 0;
|
| 175 |
}
|
| 176 |
}
|
| 177 |
#ifdef PICT_GLARE
|
| 178 |
if (!(p->pinfo = (pixinfo*)
|
| 179 |
realloc(p->pinfo,(p->resol.xr)*p->resol.yr*sizeof(pixinfo)))) {
|
| 180 |
fprintf(stderr,"Can't alloc picture info\n");
|
| 181 |
return 0;
|
| 182 |
}
|
| 183 |
/* fprintf(stderr,"resize %d %d %d\n",p->resol.xr,p->resol.yr,sizeof(pixinfo));*/
|
| 184 |
#endif
|
| 185 |
return 1;
|
| 186 |
}
|
| 187 |
|
| 188 |
|
| 189 |
int pict_zero(pict* p)
|
| 190 |
{
|
| 191 |
int x,y,i;
|
| 192 |
|
| 193 |
for(x=0;x<pict_get_xsize(p);x++)
|
| 194 |
for(y=0;y<pict_get_ysize(p);y++)
|
| 195 |
for(i=0;i<3;i++)
|
| 196 |
pict_get_color(p,x,y)[i] = 0;
|
| 197 |
return 1;
|
| 198 |
}
|
| 199 |
|
| 200 |
struct hinfo {
|
| 201 |
VIEW *hv;
|
| 202 |
int ok;
|
| 203 |
double exposure;
|
| 204 |
};
|
| 205 |
|
| 206 |
|
| 207 |
static int
|
| 208 |
gethinfo( /* get view from header */
|
| 209 |
char *s,
|
| 210 |
void *v
|
| 211 |
)
|
| 212 |
{
|
| 213 |
if (isview(s) && sscanview(((struct hinfo*)v)->hv, s) > 0) {
|
| 214 |
((struct hinfo*)v)->ok++;
|
| 215 |
} else if (isexpos(s)) {
|
| 216 |
/*fprintf(stderr,"readexp %f %f\n",((struct hinfo*)v)->exposure,exposval(s));*/
|
| 217 |
((struct hinfo*)v)->exposure *= exposval(s);
|
| 218 |
}
|
| 219 |
return(0);
|
| 220 |
}
|
| 221 |
|
| 222 |
int pict_read_fp(pict* p,FILE* fp)
|
| 223 |
{
|
| 224 |
struct hinfo hi;
|
| 225 |
int x,y,yy;
|
| 226 |
|
| 227 |
|
| 228 |
hi.hv = &(p->view);
|
| 229 |
hi.ok = 0;
|
| 230 |
hi.exposure = 1;
|
| 231 |
getheader(fp, gethinfo, &hi);
|
| 232 |
/*fprintf(stderr,"expscale %f\n",hi.exposure);*/
|
| 233 |
|
| 234 |
if (!(pict_update_view(p)) || !(hi.ok))
|
| 235 |
p->valid_view = 0;
|
| 236 |
/* printf("dir %f %f %f\n",p->view.vdir[0],p->view.vdir[1],p->view.vdir[2]); */
|
| 237 |
if (fgetsresolu(&(p->resol),fp) < 0) {
|
| 238 |
fprintf(stderr,"No resolution given\n");
|
| 239 |
return 0;
|
| 240 |
}
|
| 241 |
if (!(p->resol.rt & YMAJOR)) {
|
| 242 |
x = p->resol.xr;
|
| 243 |
p->resol.xr = p->resol.yr;
|
| 244 |
p->resol.yr = x;
|
| 245 |
p->resol.rt |= YMAJOR;
|
| 246 |
}
|
| 247 |
if (!pict_resize(p,p->resol.xr,p->resol.yr))
|
| 248 |
return 0;
|
| 249 |
for(yy=0;yy<p->resol.yr;yy++) {
|
| 250 |
y = (p->resol.rt & YDECR) ? p->resol.yr - 1 - yy : yy;
|
| 251 |
if (freadscan((p->pic + y*p->resol.xr),p->resol.xr,fp) < 0) {
|
| 252 |
fprintf(stderr,"error reading line %d\n",y);
|
| 253 |
return 0;
|
| 254 |
}
|
| 255 |
for(x=0;x<p->resol.xr;x++) {
|
| 256 |
scalecolor(pict_get_color(p,x,y),1.0/hi.exposure);
|
| 257 |
}
|
| 258 |
}
|
| 259 |
#ifdef PICT_GLARE
|
| 260 |
pict_update_evalglare_caches(p);
|
| 261 |
#endif
|
| 262 |
return 1;
|
| 263 |
}
|
| 264 |
|
| 265 |
#ifdef PICT_GLARE
|
| 266 |
void pict_update_evalglare_caches(pict* p)
|
| 267 |
{
|
| 268 |
int x,y,yy;
|
| 269 |
float lum;
|
| 270 |
for(yy=0;yy<p->resol.yr;yy++) {
|
| 271 |
y = (p->resol.rt & YDECR) ? p->resol.yr - 1 - yy : yy;
|
| 272 |
for(x=0;x<p->resol.xr;x++) {
|
| 273 |
pict_get_omega(p,x,y) = pict_get_sangle(p,x,y);
|
| 274 |
pict_get_dir(p,x,y,pict_get_cached_dir(p,x,y));
|
| 275 |
pict_get_gsn(p,x,y) = 0;
|
| 276 |
pict_get_pgs(p,x,y) = 0;
|
| 277 |
/* make picture grey */
|
| 278 |
lum=luminance(pict_get_color(p,x,y))/179.0;
|
| 279 |
pict_get_color(p,x,y)[RED]=lum;
|
| 280 |
pict_get_color(p,x,y)[GRN]=lum;
|
| 281 |
pict_get_color(p,x,y)[BLU]=lum;
|
| 282 |
}
|
| 283 |
}
|
| 284 |
}
|
| 285 |
|
| 286 |
#endif
|
| 287 |
|
| 288 |
int pict_read(pict* p,char* fn)
|
| 289 |
{
|
| 290 |
FILE* fp;
|
| 291 |
|
| 292 |
if (!(fp = fopen(fn,"rb"))) {
|
| 293 |
fprintf(stderr,"Can't open %s\n",fn);
|
| 294 |
return 0;
|
| 295 |
}
|
| 296 |
if (!(pict_read_fp(p,fp)))
|
| 297 |
return 0;
|
| 298 |
fclose(fp);
|
| 299 |
return 1;
|
| 300 |
}
|
| 301 |
|
| 302 |
static void ch_pct(char* line)
|
| 303 |
{
|
| 304 |
char* pct;
|
| 305 |
|
| 306 |
while ((pct = index(line,',')))
|
| 307 |
*pct = '.';
|
| 308 |
}
|
| 309 |
|
| 310 |
char* nextline(FILE* fp)
|
| 311 |
{
|
| 312 |
static char* line = NULL;
|
| 313 |
static int lsize = 500;
|
| 314 |
int done;
|
| 315 |
long fpos;
|
| 316 |
|
| 317 |
if (!line) {
|
| 318 |
if (!(line = (char*) malloc((lsize + 1)*sizeof(char)))) {
|
| 319 |
fprintf(stderr,"allocation problem in nextline\n");
|
| 320 |
return NULL;
|
| 321 |
}
|
| 322 |
}
|
| 323 |
done = 0;
|
| 324 |
fpos = ftell(fp);
|
| 325 |
while(!done) {
|
| 326 |
if (!fgets(line,lsize,fp))
|
| 327 |
return NULL;
|
| 328 |
if (!index(line,'\n')) {
|
| 329 |
lsize *= 2;
|
| 330 |
if (!(line = (char*) realloc(line,(lsize + 1)*sizeof(char)))) {
|
| 331 |
fprintf(stderr,"allocation problem in nextline\n");
|
| 332 |
return NULL;
|
| 333 |
}
|
| 334 |
fseek(fp,fpos,SEEK_SET);
|
| 335 |
} else {
|
| 336 |
done = 1;
|
| 337 |
}
|
| 338 |
}
|
| 339 |
return line;
|
| 340 |
}
|
| 341 |
|
| 342 |
static int read_tt_txt(pict* p,int bufsel,int channel,char* fn)
|
| 343 |
{
|
| 344 |
FILE* fp;
|
| 345 |
char* line = NULL;
|
| 346 |
int x,y,vsize,hsize;
|
| 347 |
float* col;
|
| 348 |
float c;
|
| 349 |
char* curr;
|
| 350 |
char** endp;
|
| 351 |
COLOR* picbuf;
|
| 352 |
|
| 353 |
if (!(fp = fopen(fn,"r"))) {
|
| 354 |
fprintf(stderr,"pict_read_tt_txt: Can't open file %s\n",fn);
|
| 355 |
return 0;
|
| 356 |
}
|
| 357 |
if (!(line = nextline(fp))) {
|
| 358 |
fprintf(stderr,"pict_read_tt_txt: reading from file failed\n");
|
| 359 |
return 0;
|
| 360 |
}
|
| 361 |
if (strncmp(line,"float",strlen("float"))) {
|
| 362 |
fprintf(stderr,"pict_read_tt_txt: Unexpected format\n");
|
| 363 |
return 0;
|
| 364 |
}
|
| 365 |
if (!(line = nextline(fp))) {
|
| 366 |
fprintf(stderr,"pict_read_tt_txt: reading from file failed\n");
|
| 367 |
return 0;
|
| 368 |
}
|
| 369 |
sscanf(line,"%d %d %d %d",&x,&vsize,&y,&hsize);
|
| 370 |
vsize = vsize - x;
|
| 371 |
hsize = hsize - y;
|
| 372 |
if (!pict_resize(p,vsize,hsize))
|
| 373 |
return 0;
|
| 374 |
endp = malloc(sizeof(char*));
|
| 375 |
picbuf = (bufsel == PICT_LUT) ? p->lut : p->pic;
|
| 376 |
for(x=0;x<vsize;x++) {
|
| 377 |
if (!(line = nextline(fp))) {
|
| 378 |
fprintf(stderr,"pict_read_tt_txt: too few lines %d of %d\n",x,vsize);
|
| 379 |
free(endp);
|
| 380 |
return 0;
|
| 381 |
}
|
| 382 |
ch_pct(line);
|
| 383 |
curr = line;
|
| 384 |
for(y=0;y<hsize;y++) {
|
| 385 |
col = pict_colbuf(p,picbuf,x,y);
|
| 386 |
c = strtod(curr,endp);
|
| 387 |
if (channel & PICT_CH1)
|
| 388 |
col[0] = c;
|
| 389 |
if (channel & PICT_CH2)
|
| 390 |
col[1] = c;
|
| 391 |
if (channel & PICT_CH3)
|
| 392 |
col[2] = c;
|
| 393 |
if (curr == (*endp)) {
|
| 394 |
fprintf(stderr,"pict_read_tt_txt: too few values in line %d\n",x);
|
| 395 |
free(endp);
|
| 396 |
return 0;
|
| 397 |
}
|
| 398 |
curr = (*endp);
|
| 399 |
}
|
| 400 |
}
|
| 401 |
free(endp);
|
| 402 |
return 1;
|
| 403 |
}
|
| 404 |
|
| 405 |
int pict_read_tt_txt(pict* p,char* fn)
|
| 406 |
{
|
| 407 |
return read_tt_txt(p,PICT_VIEW,PICT_ALLCH,fn);
|
| 408 |
}
|
| 409 |
|
| 410 |
int pict_setup_lut(pict* p,char* theta_fn,char* phi_fn,char* omega_fn)
|
| 411 |
{
|
| 412 |
int xs,ys;
|
| 413 |
|
| 414 |
p->use_lut = 1;
|
| 415 |
if (!read_tt_txt(p,PICT_LUT,PICT_CH1,theta_fn)) {
|
| 416 |
fprintf(stderr,"pict_setup_lut: error reading theta file\n");
|
| 417 |
p->use_lut = 0;
|
| 418 |
return 0;
|
| 419 |
}
|
| 420 |
xs = pict_get_xsize(p);
|
| 421 |
ys = pict_get_ysize(p);
|
| 422 |
if (!read_tt_txt(p,PICT_LUT,PICT_CH2,phi_fn)) {
|
| 423 |
fprintf(stderr,"pict_setup_lut: error reading phi file\n");
|
| 424 |
p->use_lut = 0;
|
| 425 |
return 0;
|
| 426 |
}
|
| 427 |
if ((xs != pict_get_xsize(p)) || (ys != pict_get_ysize(p))) {
|
| 428 |
fprintf(stderr,"pict_setup_lut: different resolutions for lut files\n");
|
| 429 |
p->use_lut = 0;
|
| 430 |
return 0;
|
| 431 |
}
|
| 432 |
if (!read_tt_txt(p,PICT_LUT,PICT_CH3,omega_fn)) {
|
| 433 |
fprintf(stderr,"pict_setup_lut: error reading omega file\n");
|
| 434 |
p->use_lut = 0;
|
| 435 |
return 0;
|
| 436 |
}
|
| 437 |
if ((xs != pict_get_xsize(p)) || (ys != pict_get_ysize(p))) {
|
| 438 |
fprintf(stderr,"pict_setup_lut: different resolutions for lut files\n");
|
| 439 |
p->use_lut = 0;
|
| 440 |
return 0;
|
| 441 |
}
|
| 442 |
return 1;
|
| 443 |
}
|
| 444 |
|
| 445 |
int pict_update_lut(pict* p)
|
| 446 |
{
|
| 447 |
g3ATrans transf;
|
| 448 |
g3Vec d;
|
| 449 |
g3Vec u;
|
| 450 |
int x,y;
|
| 451 |
|
| 452 |
d = g3v_fromrad(g3v_create(),p->view.vdir);
|
| 453 |
u = g3v_fromrad(g3v_create(),p->view.vup);
|
| 454 |
g3at_ctrans(transf,d,u);
|
| 455 |
for(x=0;x<p->resol.xr;x++) {
|
| 456 |
for(y=0;y<p->resol.yr;y++) {
|
| 457 |
d[G3S_RAD] = 1.0;
|
| 458 |
d[G3S_THETA] = DEG2RAD(pict_colbuf(p,p->lut,x,y)[0]);
|
| 459 |
d[G3S_PHI] = DEG2RAD(pict_colbuf(p,p->lut,x,y)[1]);
|
| 460 |
g3s_sphtocc(d,d);
|
| 461 |
g3at_apply(transf,d);
|
| 462 |
g3s_cctosph(d,d);
|
| 463 |
pict_colbuf(p,p->lut,x,y)[0] = RAD2DEG(d[G3S_THETA]);
|
| 464 |
pict_colbuf(p,p->lut,x,y)[1] = RAD2DEG(d[G3S_PHI]);
|
| 465 |
}
|
| 466 |
}
|
| 467 |
g3v_free(d);
|
| 468 |
g3v_free(u);
|
| 469 |
return 1;
|
| 470 |
}
|
| 471 |
|
| 472 |
|
| 473 |
int pict_write_dir(pict* p,FILE* fp)
|
| 474 |
{
|
| 475 |
int x,y;
|
| 476 |
FVECT dir,orig;
|
| 477 |
|
| 478 |
for(y=0;y<p->resol.yr;y++) {
|
| 479 |
for(x=0;x<p->resol.xr;x++) {
|
| 480 |
if (!(pict_get_ray(p,x,y,orig,dir))) {
|
| 481 |
fprintf(fp,"%f %f %f 0.0 0.0 0.0\n",orig[0],orig[1],orig[2]);
|
| 482 |
} else {
|
| 483 |
fprintf(fp,"%f %f %f %f %f %f\n",orig[0],orig[1],orig[2],dir[0],dir[1],dir[2]);
|
| 484 |
}
|
| 485 |
}
|
| 486 |
}
|
| 487 |
return 1;
|
| 488 |
}
|
| 489 |
|
| 490 |
int pict_read_from_list(pict* p,FILE* fp)
|
| 491 |
{
|
| 492 |
int x,y,sz;
|
| 493 |
char ln[1024];
|
| 494 |
double val;
|
| 495 |
|
| 496 |
sz = 0;
|
| 497 |
for(y=0;y<p->resol.yr;y++) {
|
| 498 |
for(x=0;x<p->resol.xr;x++) {
|
| 499 |
if (!(fgets(ln,1023,fp))) {
|
| 500 |
fprintf(stderr,"pict_read_from_list: Read only %d values\n",sz);
|
| 501 |
return 0;
|
| 502 |
}
|
| 503 |
if (sscanf(ln,"%lg",&val) != 1) {
|
| 504 |
fprintf(stderr,"pict_read_from_list: errline %d\n",sz);
|
| 505 |
} else {
|
| 506 |
sz++;
|
| 507 |
setcolor(pict_get_color(p,x,y),val,val,val);
|
| 508 |
}
|
| 509 |
}
|
| 510 |
}
|
| 511 |
return 1;
|
| 512 |
}
|
| 513 |
|
| 514 |
int pict_write(pict* p,char* fn)
|
| 515 |
{
|
| 516 |
FILE* fp;
|
| 517 |
|
| 518 |
if (!(fp = fopen(fn,"wb"))) {
|
| 519 |
fprintf(stderr,"Can't open %s for writing\n",fn);
|
| 520 |
return 0;
|
| 521 |
}
|
| 522 |
if (!(pict_write_fp(p,fp))) {
|
| 523 |
fclose(fp);
|
| 524 |
return 0;
|
| 525 |
}
|
| 526 |
fclose(fp);
|
| 527 |
return 1;
|
| 528 |
}
|
| 529 |
|
| 530 |
int pict_write_fp(pict* p,FILE* fp)
|
| 531 |
{
|
| 532 |
char res[100];
|
| 533 |
int y,yy;
|
| 534 |
newheader("RADIANCE",fp);
|
| 535 |
fputnow(fp);
|
| 536 |
if (strlen(p->comment) > 0)
|
| 537 |
fputs(p->comment,fp);
|
| 538 |
fputs(VIEWSTR, fp);
|
| 539 |
fprintview(&(p->view), fp);
|
| 540 |
fprintf(fp,"\n");
|
| 541 |
fputformat(COLRFMT,fp);
|
| 542 |
fprintf(fp,"\n");
|
| 543 |
|
| 544 |
resolu2str(res,&(p->resol));
|
| 545 |
fprintf(fp,"%s",res);
|
| 546 |
for(y=0;y<p->resol.yr;y++) {
|
| 547 |
yy = (p->resol.rt & YDECR) ? p->resol.yr - 1 - y : y;
|
| 548 |
if (fwritescan((p->pic + yy*p->resol.xr),p->resol.xr,fp) < 0) {
|
| 549 |
fprintf(stderr,"writing pic-file failed\n");
|
| 550 |
return 0;
|
| 551 |
}
|
| 552 |
}
|
| 553 |
return 1;
|
| 554 |
}
|
| 555 |
|
| 556 |
int pict_get_dir(pict* p,int x,int y,FVECT dir)
|
| 557 |
{
|
| 558 |
FVECT orig;
|
| 559 |
if (pict_lut_used(p)) {
|
| 560 |
if (!(p->lut)) {
|
| 561 |
fprintf(stderr,"pict_get_dir: no lut defined\n");
|
| 562 |
return 0;
|
| 563 |
}
|
| 564 |
dir[G3S_RAD] = 1.0;
|
| 565 |
dir[G3S_THETA] = DEG2RAD(pict_colbuf(p,p->lut,x,y)[0]);
|
| 566 |
dir[G3S_PHI] = DEG2RAD(pict_colbuf(p,p->lut,x,y)[1]);
|
| 567 |
g3s_sphtocc(dir,dir);
|
| 568 |
return 1;
|
| 569 |
}
|
| 570 |
return pict_get_ray(p,x,y,orig,dir);
|
| 571 |
}
|
| 572 |
|
| 573 |
int pict_get_dir_ic(pict* p,double x,double y,FVECT dir)
|
| 574 |
{
|
| 575 |
FVECT orig;
|
| 576 |
if (pict_lut_used(p)) {
|
| 577 |
int res[2];
|
| 578 |
loc2pix(res,&(p->resol),x,y);
|
| 579 |
return pict_get_dir(p,res[0],res[1],dir);
|
| 580 |
}
|
| 581 |
return pict_get_ray_ic(p,x,y,orig,dir);
|
| 582 |
}
|
| 583 |
|
| 584 |
int pict_get_ray(pict* p,int x,int y,FVECT orig,FVECT dir)
|
| 585 |
{
|
| 586 |
RREAL pc[2];
|
| 587 |
|
| 588 |
pix2loc(pc,&(p->resol),x,p->resol.yr - 1 - y);
|
| 589 |
if (pict_lut_used(p)) {
|
| 590 |
if (viewray(orig,dir,&(p->view),pc[0],pc[1]) <= 0)
|
| 591 |
return 0;
|
| 592 |
return pict_get_dir(p,x,y,dir);
|
| 593 |
}
|
| 594 |
return pict_get_ray_ic(p,pc[0],pc[1],orig,dir);
|
| 595 |
}
|
| 596 |
|
| 597 |
int pict_get_ray_ic(pict* p,double x,double y,FVECT orig,FVECT dir)
|
| 598 |
{
|
| 599 |
if (pict_lut_used(p)) {
|
| 600 |
int res[2];
|
| 601 |
loc2pix(res,&(p->resol),x,y);
|
| 602 |
return pict_get_ray(p,res[0],res[1],orig,dir);
|
| 603 |
}
|
| 604 |
x = (x + (0.5*p->pjitter)*(0.5-gb_random())/p->resol.xr);
|
| 605 |
y = (y + (0.5*p->pjitter)*(0.5-gb_random())/p->resol.yr);
|
| 606 |
if (viewray(orig,dir,&(p->view),x,y) < 0)
|
| 607 |
return 0;
|
| 608 |
return 1;
|
| 609 |
}
|
| 610 |
|
| 611 |
|
| 612 |
static int splane_normal(pict* p,double e1x,double e1y,
|
| 613 |
double e2x,double e2y,FVECT n)
|
| 614 |
{
|
| 615 |
FVECT e1 = {0,0,0};
|
| 616 |
FVECT e2 = {0,0,0};
|
| 617 |
|
| 618 |
pict_get_dir_ic(p,e1x,e1y,e1);
|
| 619 |
pict_get_dir_ic(p,e2x,e2y,n);
|
| 620 |
VSUB(e2,n,e1);
|
| 621 |
VCROSS(n,e1,e2);
|
| 622 |
if (normalize(n) == 0.0) {
|
| 623 |
return 0;
|
| 624 |
}
|
| 625 |
return 1;
|
| 626 |
}
|
| 627 |
|
| 628 |
double pict_get_sangle(pict* p,int x,int y)
|
| 629 |
{
|
| 630 |
int i;
|
| 631 |
double ang,a,hpx,hpy;
|
| 632 |
RREAL pc[2];
|
| 633 |
FVECT n[4] = {{0,0,0},{0,0,0},{0,0,0},{0,0,0}};
|
| 634 |
|
| 635 |
if (pict_lut_used(p)) {
|
| 636 |
return pict_colbuf(p,p->lut,x,y)[2];
|
| 637 |
}
|
| 638 |
pix2loc(pc,&(p->resol),x,y);
|
| 639 |
hpx = (0.5/p->resol.xr);
|
| 640 |
hpy = (0.5/p->resol.yr);
|
| 641 |
pc[0] -= hpx;
|
| 642 |
pc[1] -= hpy;
|
| 643 |
|
| 644 |
i = splane_normal(p,pc[0],pc[1],pc[0],(pc[1]+2.0*hpy),n[0]);
|
| 645 |
i &= splane_normal(p,pc[0],(pc[1]+2.0*hpy),(pc[0]+2.0*hpx),(pc[1]+2.0*hpy),n[1]);
|
| 646 |
i &= splane_normal(p,(pc[0]+2.0*hpx),(pc[1]+2.0*hpy),(pc[0]+2.0*hpx),pc[1],n[2]);
|
| 647 |
i &= splane_normal(p,(pc[0]+2.0*hpx),pc[1],pc[0],pc[1],n[3]);
|
| 648 |
|
| 649 |
if (!i) {
|
| 650 |
return 0;
|
| 651 |
}
|
| 652 |
ang = 0;
|
| 653 |
for(i=0;i<4;i++) {
|
| 654 |
a = DOT(n[i],n[(i+1)%4]);
|
| 655 |
a = acos(a);
|
| 656 |
a = fabs(a);
|
| 657 |
ang += M_PI - a;
|
| 658 |
}
|
| 659 |
ang = ang - 2.0*M_PI;
|
| 660 |
if ((ang > (2.0*M_PI)) || ang < 0) {
|
| 661 |
fprintf(stderr,"Normal error in pict_get_sangle %f %d %d\n",ang,x,y);
|
| 662 |
return -1.0;
|
| 663 |
}
|
| 664 |
return ang;
|
| 665 |
}
|
| 666 |
|
| 667 |
int pict_locate(pict* p,FVECT pt,int* x,int* y)
|
| 668 |
{
|
| 669 |
FVECT pp;
|
| 670 |
int res[2];
|
| 671 |
|
| 672 |
if (pict_lut_used(p)) {
|
| 673 |
fprintf(stderr,"pict_locate: Not implemented for lut mode\n");
|
| 674 |
return 0;
|
| 675 |
}
|
| 676 |
|
| 677 |
viewloc(pp,&(p->view),pt);
|
| 678 |
if (pp[2] < 0)
|
| 679 |
return 0;
|
| 680 |
loc2pix(res,&(p->resol),pp[0],pp[1]);
|
| 681 |
*x = res[0];
|
| 682 |
*y = res[1];
|
| 683 |
return 1;
|
| 684 |
}
|
| 685 |
|
| 686 |
int pict_get_sigma(pict* p,double x,double y,FVECT vdir,FVECT vup,double* s)
|
| 687 |
{
|
| 688 |
FVECT pvdir;
|
| 689 |
|
| 690 |
if (!pict_get_dir(p,x,y,pvdir))
|
| 691 |
return 0;
|
| 692 |
if (normalize(vdir) == 0.0) {
|
| 693 |
fprintf(stderr,"get_sigma: view dir is zero\n");
|
| 694 |
return 0;
|
| 695 |
}
|
| 696 |
if (normalize(vup) == 0.0) {
|
| 697 |
fprintf(stderr,"get_sigma: view up is zero\n");
|
| 698 |
return 0;
|
| 699 |
}
|
| 700 |
*s = acos(DOT(vdir,pvdir));
|
| 701 |
return 1;
|
| 702 |
}
|
| 703 |
|
| 704 |
int pict_get_tau(pict* p,double x,double y,FVECT vdir,FVECT vup,double* t)
|
| 705 |
{
|
| 706 |
FVECT hv,pvdir;
|
| 707 |
double s;
|
| 708 |
int i;
|
| 709 |
if (!pict_get_sigma(p,x,y,vdir,vup,&s))
|
| 710 |
return 0;
|
| 711 |
if (!pict_get_dir(p,x,y,pvdir))
|
| 712 |
return 0;
|
| 713 |
VCOPY(hv,pvdir);
|
| 714 |
normalize(hv);
|
| 715 |
for(i=0;i<3;i++){
|
| 716 |
hv[i] /= cos(s);
|
| 717 |
}
|
| 718 |
VSUB(hv,hv,vdir);
|
| 719 |
normalize(hv);
|
| 720 |
*t = acos(fdot(vup,hv));
|
| 721 |
return 1;
|
| 722 |
}
|
| 723 |
|
| 724 |
static int ortho_coord(FVECT vdir,FVECT vup,FVECT vv,FVECT hv)
|
| 725 |
{
|
| 726 |
if (normalize(vdir) == 0.0) {
|
| 727 |
fprintf(stderr,"ortho_coord: view direction is zero\n");
|
| 728 |
return 0;
|
| 729 |
}
|
| 730 |
if (normalize(vup) == 0.0) {
|
| 731 |
fprintf(stderr,"ortho_coord: view direction is zero\n");
|
| 732 |
return 0;
|
| 733 |
}
|
| 734 |
fcross(hv,vdir,vup);
|
| 735 |
fcross(vv,vdir,hv);
|
| 736 |
return 1;
|
| 737 |
}
|
| 738 |
|
| 739 |
int pict_get_vangle(pict* p,double x,double y,FVECT vdir,FVECT vup,double* a)
|
| 740 |
{
|
| 741 |
FVECT hv,vv,pvdir;
|
| 742 |
if (!ortho_coord(vdir,vup,vv,hv)) {
|
| 743 |
return 0;
|
| 744 |
}
|
| 745 |
if (!pict_get_dir(p,x,y,pvdir))
|
| 746 |
return 0;
|
| 747 |
*a = acos(fdot(vv,pvdir)) - (M_PI/2.0) ;
|
| 748 |
return 1;
|
| 749 |
}
|
| 750 |
|
| 751 |
int pict_get_hangle(pict* p,double x,double y,FVECT vdir,FVECT vup,double* a)
|
| 752 |
{
|
| 753 |
FVECT hv,vv,pvdir;
|
| 754 |
if (!ortho_coord(vdir,vup,vv,hv)) {
|
| 755 |
return 0;
|
| 756 |
}
|
| 757 |
if (!pict_get_dir(p,x,y,pvdir)) {
|
| 758 |
return 0;
|
| 759 |
}
|
| 760 |
*a = ((M_PI/2.0) - acos(fdot(hv,pvdir)));
|
| 761 |
return 1;
|
| 762 |
}
|
| 763 |
|
| 764 |
int pict_setorigin(pict* p,FVECT orig)
|
| 765 |
{
|
| 766 |
VCOPY(p->view.vp,orig);
|
| 767 |
return pict_update_view(p);
|
| 768 |
}
|
| 769 |
|
| 770 |
int pict_setdir(pict* p,FVECT dir)
|
| 771 |
{
|
| 772 |
VCOPY(p->view.vdir,dir);
|
| 773 |
return pict_update_view(p);
|
| 774 |
}
|
| 775 |
|
| 776 |
int pict_sethview(pict* p,double ha)
|
| 777 |
{
|
| 778 |
p->view.horiz = ha;
|
| 779 |
return pict_update_view(p);
|
| 780 |
}
|
| 781 |
|
| 782 |
int pict_setvview(pict* p,double va)
|
| 783 |
{
|
| 784 |
p->view.vert = va;
|
| 785 |
return pict_update_view(p);
|
| 786 |
}
|
| 787 |
|
| 788 |
int pict_setvtype(pict* p,char vt)
|
| 789 |
{
|
| 790 |
p->view.type = vt;
|
| 791 |
return pict_update_view(p);
|
| 792 |
}
|
| 793 |
|
| 794 |
#ifdef TEST_PICTTOOL
|
| 795 |
|
| 796 |
char* progname = "pictool";
|
| 797 |
|
| 798 |
int main(int argc,char** argv)
|
| 799 |
{
|
| 800 |
pict* p = pict_create();
|
| 801 |
FVECT dir = {0,-1,0};
|
| 802 |
FVECT vdir,edir;
|
| 803 |
FVECT up = {0,0,1};
|
| 804 |
int x,y,i;
|
| 805 |
double sang,h,v;
|
| 806 |
|
| 807 |
if (argc < 2) {
|
| 808 |
fprintf(stderr,"usage: %s <pic-file>\n",argv[0]);
|
| 809 |
return EXIT_FAILURE;
|
| 810 |
}
|
| 811 |
fprintf(stderr,"readdd\n");
|
| 812 |
pict_read(p,argv[1]);
|
| 813 |
pict_set_comment(p,"pictool test output\n");
|
| 814 |
/*
|
| 815 |
pict_get_dir(p,100,100,edir); // YDECR
|
| 816 |
for(y=0;y<p->resol.yr;y++) {
|
| 817 |
for(x=0;x<p->resol.xr;x++) {
|
| 818 |
pict_get_hangle(p,x,y,dir,up,&h);
|
| 819 |
pict_get_vangle(p,x,y,dir,up,&v);
|
| 820 |
pict_get_dir(p,x,y,vdir);
|
| 821 |
if (acos(DOT(vdir,edir)) < DEG2RAD(3))
|
| 822 |
setcolor(pict_get_color(p,x,y),h+M_PI/2,v+M_PI/2,1);
|
| 823 |
else
|
| 824 |
setcolor(pict_get_color(p,x,y),h+M_PI/2,v+M_PI/2,0);
|
| 825 |
}
|
| 826 |
}
|
| 827 |
*/
|
| 828 |
printf("resolution: %dx%d\n",pict_get_xsize(p),pict_get_ysize(p));
|
| 829 |
sang = 0.0;
|
| 830 |
|
| 831 |
pict_new_gli(p);
|
| 832 |
for(x=0;x<pict_get_xsize(p);x++)
|
| 833 |
for(y=0;y<pict_get_ysize(p);y++) {
|
| 834 |
pict_get_dir(p,x,y,dir);
|
| 835 |
if (DOT(dir,p->view.vdir) >= 0.0) {
|
| 836 |
pict_get_av_omega(p,0) += pict_get_omega(p,x,y);
|
| 837 |
}
|
| 838 |
sang = pict_get_sangle(p,x,y);
|
| 839 |
for(i=0;i<3;i++)
|
| 840 |
if (sang <= 0 && pict_is_validpixel(p,x,y)) {
|
| 841 |
pict_get_color(p,x,y)[i] = 1;
|
| 842 |
} else {
|
| 843 |
pict_get_color(p,x,y)[i] =0;
|
| 844 |
}
|
| 845 |
}
|
| 846 |
printf("s %f\n",pict_get_av_omega(p,0));
|
| 847 |
pict_write(p,"test.pic");
|
| 848 |
while(1) {
|
| 849 |
printf("pos\n");
|
| 850 |
if (scanf("%d %d",&x,&y) != 2)
|
| 851 |
continue;
|
| 852 |
pict_get_dir(p,x,y,dir);
|
| 853 |
printf("dir: \t\t %f %f %f\n",dir[0],dir[1],dir[2]);
|
| 854 |
printf("solid angle: \t %f \n",pict_get_sangle(p,x,y));
|
| 855 |
}
|
| 856 |
return EXIT_SUCCESS;
|
| 857 |
}
|
| 858 |
|
| 859 |
#endif
|