Mercurial > hg > wm
comparison Meerwald/wavelet.c @ 0:be303a3f5ea8
import
| author | Peter Meerwald <pmeerw@cosy.sbg.ac.at> |
|---|---|
| date | Sun, 12 Aug 2007 13:14:34 +0200 |
| parents | |
| children | f83ef905a63d |
comparison
equal
deleted
inserted
replaced
| -1:000000000000 | 0:be303a3f5ea8 |
|---|---|
| 1 #include <stdio.h> | |
| 2 #include <stdlib.h> | |
| 3 #include <string.h> | |
| 4 #include <math.h> | |
| 5 #include "wavelet.h" | |
| 6 #include <ctype.h> | |
| 7 | |
| 8 static int read_char(FILE *fp); | |
| 9 static int read_int(FILE *fp); | |
| 10 | |
| 11 IntImage new_intimage(int width, int height) | |
| 12 { | |
| 13 IntImage image; | |
| 14 | |
| 15 image = (IntImage) calloc(1,sizeof(struct IntImage_struct)); | |
| 16 if (image==NULL) goto error; | |
| 17 image->data = (IntPixel*) calloc(width*height,sizeof(IntPixel)); | |
| 18 if (image->data==NULL) goto error; | |
| 19 image->width = width; | |
| 20 image->height = height; | |
| 21 image->size = width*height; | |
| 22 image->bpp = 0; | |
| 23 image->min_val = (IntPixel) 0; | |
| 24 image->max_val = (IntPixel) 0; | |
| 25 | |
| 26 return image; | |
| 27 | |
| 28 error: | |
| 29 err_SimpleMessage(err_GetErrorMessage(Error_NotEnoughMemory)); | |
| 30 return NULL; | |
| 31 } | |
| 32 | |
| 33 Image new_image(int width, int height) | |
| 34 { | |
| 35 Image image; | |
| 36 | |
| 37 image = (Image) calloc(1,sizeof(struct Image_struct)); | |
| 38 if (image==NULL) goto error; | |
| 39 image->data = (Pixel*) calloc(width*height,sizeof(Pixel)); | |
| 40 if (image->data==NULL) goto error; | |
| 41 image->width = width; | |
| 42 image->height = height; | |
| 43 image->size = width*height; | |
| 44 image->bpp = 0; | |
| 45 image->min_val = (Pixel) 0; | |
| 46 image->max_val = (Pixel) 0; | |
| 47 | |
| 48 return image; | |
| 49 | |
| 50 error: | |
| 51 err_SimpleMessage(err_GetErrorMessage(Error_NotEnoughMemory)); | |
| 52 return NULL; | |
| 53 } | |
| 54 | |
| 55 | |
| 56 void free_intimage(IntImage img) | |
| 57 { | |
| 58 if (img) { | |
| 59 if (img->data) free(img->data); | |
| 60 free(img); | |
| 61 } | |
| 62 } | |
| 63 | |
| 64 void free_image(Image img) | |
| 65 { | |
| 66 if (img) { | |
| 67 if (img->data) free(img->data); | |
| 68 free(img); | |
| 69 } | |
| 70 } | |
| 71 | |
| 72 /************************************************************************ | |
| 73 * Functionname: load_intimage | |
| 74 * -------------------------------------------------------------------- | |
| 75 * PARAMETER: | |
| 76 * file: filename of image | |
| 77 * max_val: scaling of grey values to [0..max_val] | |
| 78 * | |
| 79 * RETURN: | |
| 80 * Image that shoud be loaded, if not possible return NULL | |
| 81 * -------------------------------------------------------------------- | |
| 82 * DESCRIPTION: | |
| 83 * This function loads an IntImage (PGM, ASCII or binary | |
| 84 * encoded (P5 or P3 format) ) from a file. | |
| 85 ************************************************************************/ | |
| 86 | |
| 87 IntImage load_intimage(char *file, int max_val) | |
| 88 { | |
| 89 IntImage img; | |
| 90 FILE *fp; | |
| 91 IntPixel *data; | |
| 92 int width, height, i, max, ch1, ch2; | |
| 93 | |
| 94 fp=fopen(file,"rb"); | |
| 95 if (fp==NULL) goto error; | |
| 96 | |
| 97 ch1=getc(fp); | |
| 98 ch2=getc(fp); | |
| 99 if (ch1!='P' || (ch2!='5' && ch2!='2')) goto error1; | |
| 100 | |
| 101 width=read_int(fp); | |
| 102 height=read_int(fp); | |
| 103 if ((width==0) || (height==0) ) goto error1; | |
| 104 max=read_int(fp); | |
| 105 | |
| 106 img=new_intimage(width,height); | |
| 107 | |
| 108 img->bpp=8; | |
| 109 | |
| 110 data=img->data; | |
| 111 for (i=0; i<img->size; i++) | |
| 112 { if (ch2=='5') | |
| 113 *data=getc(fp); | |
| 114 else | |
| 115 *data=read_int(fp); | |
| 116 data++; | |
| 117 } | |
| 118 fclose(fp); | |
| 119 return img; | |
| 120 | |
| 121 error1: | |
| 122 err_SimpleMessage(err_GetErrorMessage(Error_WrongFileFormat)); | |
| 123 return NULL; | |
| 124 error: | |
| 125 err_SimpleMessage(err_GetErrorMessage(Error_CantOpenFile)); | |
| 126 return NULL; | |
| 127 } | |
| 128 | |
| 129 /************************************************************************ | |
| 130 * Functionname: load_image | |
| 131 * -------------------------------------------------------------------- | |
| 132 * PARAMETER: | |
| 133 * file: filename of image | |
| 134 * max_val: scaling of grey values to [0..max_val] | |
| 135 * | |
| 136 * RETURN: | |
| 137 * Image that shoud be loaded, if not possible return NULL | |
| 138 * -------------------------------------------------------------------- | |
| 139 * DESCRIPTION: | |
| 140 * This function loads an IntImage with load_intimage | |
| 141 * and then converts to Image. | |
| 142 ************************************************************************/ | |
| 143 extern Image load_image(char *file, int max_val) | |
| 144 { | |
| 145 Image img; | |
| 146 IntImage intimg; | |
| 147 | |
| 148 intimg = load_intimage(file, max_val); | |
| 149 if (!intimg) return NULL; | |
| 150 img = intimage_to_image(intimg); | |
| 151 if (!intimg) return NULL; | |
| 152 | |
| 153 return img; | |
| 154 } | |
| 155 | |
| 156 /************************************************************************/ | |
| 157 /* Functionname: save_image_P5 */ | |
| 158 /* -------------------------------------------------------------------- */ | |
| 159 /* Parameter: */ | |
| 160 /* img: Image that shoud be saved */ | |
| 161 /* file: filename of image */ | |
| 162 /* -------------------------------------------------------------------- */ | |
| 163 /* Description: save an image as PGM (P5 binary decoded) file */ | |
| 164 /* */ | |
| 165 /************************************************************************/ | |
| 166 | |
| 167 extern int save_image_P5(char *file, Image img) | |
| 168 { FILE *fp; | |
| 169 Pixel *data; | |
| 170 long i; | |
| 171 int p; | |
| 172 | |
| 173 fp=fopen(file,"wb"); | |
| 174 if (fp==NULL) | |
| 175 goto error; | |
| 176 fprintf(fp,"P5\n"); | |
| 177 fprintf(fp,"%d %d\n%d ",img->width,img->height,255); | |
| 178 data=img->data; | |
| 179 for (i=0;i<img->size;i++) { | |
| 180 p=floor(*data+0.5); | |
| 181 if (p<0) p=0; | |
| 182 if (p>255) p=255; | |
| 183 /* putc(*data,fp); */ | |
| 184 putc(p,fp); | |
| 185 data++; | |
| 186 } | |
| 187 fclose(fp); | |
| 188 return 1; | |
| 189 | |
| 190 error: | |
| 191 err_SimpleMessage(err_GetErrorMessage(Error_CantOpenFile)); | |
| 192 return 0; | |
| 193 } | |
| 194 | |
| 195 void clear_image(Image img) | |
| 196 { | |
| 197 int i; | |
| 198 | |
| 199 PreCondition(img!=NULL,"image==NULL"); | |
| 200 | |
| 201 for (i=0;i<img->size;i++) | |
| 202 (img->data)[i]=(Pixel) 0; | |
| 203 } | |
| 204 | |
| 205 extern void copy_into_image(Image img1,Image img2,int x,int y) | |
| 206 /* copy img2 into img1 at position (x,y)*/ | |
| 207 { | |
| 208 int start,i,j,aim; | |
| 209 Pixel *temp; | |
| 210 | |
| 211 temp=img2->data; | |
| 212 start=img1->width*y+x; | |
| 213 for (i=0;i<img2->height;i++) { | |
| 214 for (j=0;j<img2->width;j++) { | |
| 215 aim=start+j+img1->width*i; | |
| 216 img1->data[aim]=*temp; | |
| 217 temp++; | |
| 218 } | |
| 219 } | |
| 220 } | |
| 221 | |
| 222 extern void copy_into_intimage(IntImage img1,IntImage img2,int x,int y) | |
| 223 {/* copy img2 into img1 at position (x,y)*/ | |
| 224 | |
| 225 int start,i,j,aim; | |
| 226 IntPixel *temp; | |
| 227 | |
| 228 temp=img2->data; | |
| 229 start=img1->width*y+x; | |
| 230 for (i=0;i<img2->height;i++) | |
| 231 { | |
| 232 for (j=0;j<img2->width;j++) | |
| 233 { | |
| 234 aim=start+j+img1->width*i; | |
| 235 img1->data[aim]=*temp; | |
| 236 temp++; | |
| 237 } | |
| 238 } | |
| 239 } | |
| 240 | |
| 241 void copy_part_of_image_into_image(Image dest_img, int dest_x, int dest_y, | |
| 242 Image src_img, int src_x, int src_y, | |
| 243 int width, int height) | |
| 244 { | |
| 245 Pixel *sp,*dp; | |
| 246 int y,siz; | |
| 247 | |
| 248 sp=get_pixel_adr(src_img,src_x,src_y); | |
| 249 dp=get_pixel_adr(dest_img,dest_x,dest_y); | |
| 250 | |
| 251 siz=width*sizeof(Pixel); | |
| 252 | |
| 253 for (y=0;y<height;y++) | |
| 254 { | |
| 255 memcpy(dp,sp,siz); | |
| 256 sp+=src_img->width; | |
| 257 dp+=dest_img->width; | |
| 258 } | |
| 259 } | |
| 260 | |
| 261 extern void copy_part_of_image(Image img1,Image img2,int x,int y) | |
| 262 /* copy part of img2 begining at position (x,y) into img1 */ | |
| 263 { int i,j,width,height,start,step; | |
| 264 Pixel *data; | |
| 265 | |
| 266 width=img1->width; | |
| 267 height=img1->height; | |
| 268 start=img2->width*y+x; | |
| 269 data=img1->data; | |
| 270 for (i=0;i<height;i++) { | |
| 271 step=i*img2->width; | |
| 272 for (j=0;j<width;j++){ | |
| 273 *data=img2->data[start+j+step]; | |
| 274 data++; | |
| 275 } | |
| 276 } | |
| 277 } | |
| 278 | |
| 279 | |
| 280 extern void scale_image(Image img,int maximum) | |
| 281 /* scale image to [0..maximum]*/ | |
| 282 { int i; | |
| 283 Pixel max,min,multi; | |
| 284 | |
| 285 for (i=0;i<img->size;i++) { | |
| 286 if (img->data[i]<min) min=img->data[i]; | |
| 287 else if (img->data[i]>max) max=img->data[i]; | |
| 288 } | |
| 289 | |
| 290 multi=(Pixel)maximum/(max-min); | |
| 291 for (i=0;i<img->size;i++) img->data[i]=multi*(img->data[i]-min); | |
| 292 img->min_val=0; | |
| 293 img->max_val=maximum; | |
| 294 } | |
| 295 | |
| 296 int string_to_pixel(char *str, Pixel *p) | |
| 297 { | |
| 298 float ppp; | |
| 299 if (sscanf(str,"%f",&ppp)==1) | |
| 300 { | |
| 301 *p=(Pixel) ppp; | |
| 302 return 1; | |
| 303 } | |
| 304 else | |
| 305 { | |
| 306 *p=0.0; | |
| 307 return 0; | |
| 308 } | |
| 309 } | |
| 310 | |
| 311 Image intimage_to_image(IntImage i) | |
| 312 { Image img; | |
| 313 int j; | |
| 314 | |
| 315 img=new_image(i->width,i->height); | |
| 316 if (img==NULL) goto error; | |
| 317 for (j=0;j<i->size;j++) | |
| 318 img->data[j]=(Pixel)i->data[j]; | |
| 319 img->bpp=i->bpp; | |
| 320 return img; | |
| 321 | |
| 322 error: | |
| 323 err_SimpleMessage(err_GetErrorMessage(Error_NotEnoughMemory)); | |
| 324 return NULL; | |
| 325 } | |
| 326 IntImage image_to_intimage(Image i) | |
| 327 { IntImage img; | |
| 328 int j,multi=1,max,min; | |
| 329 | |
| 330 img=(IntImage)calloc(1,sizeof(struct IntImage_struct)); | |
| 331 if (img==NULL) goto error; | |
| 332 img->data=(IntPixel *)calloc(i->size,sizeof(IntPixel)); | |
| 333 if (img->data==NULL) goto error; | |
| 334 img->width=i->width; | |
| 335 img->height=i->height; | |
| 336 img->size=i->size; | |
| 337 img->bpp=i->bpp; | |
| 338 | |
| 339 max=i->max_val; | |
| 340 min=i->min_val; | |
| 341 if ((max-min)!=0) | |
| 342 multi=255.0/(max-min); | |
| 343 | |
| 344 for (j=0;j<img->size;j++) | |
| 345 img->data[j]=(int)((i->data[j]-min)*multi+0.5); | |
| 346 return img; | |
| 347 | |
| 348 error: | |
| 349 err_SimpleMessage(err_GetErrorMessage(Error_NotEnoughMemory)); | |
| 350 return NULL; | |
| 351 | |
| 352 } | |
| 353 | |
| 354 static int read_char(FILE *fp) | |
| 355 /*read a character from file, but skip any comments*/ | |
| 356 { int ch; | |
| 357 | |
| 358 ch=getc(fp); | |
| 359 if (ch=='#'){ | |
| 360 do { | |
| 361 ch=getc(fp); | |
| 362 } while (ch!='\n' && ch!=EOF); | |
| 363 } | |
| 364 return ch; | |
| 365 } | |
| 366 | |
| 367 | |
| 368 static int read_int(FILE *fp) | |
| 369 /*read an ascii integer from file, and skip leading tabstops,new lines ...*/ | |
| 370 { int r,ch; | |
| 371 | |
| 372 do { | |
| 373 ch=read_char(fp); | |
| 374 } while (ch==' ' || ch=='\n' || ch=='\t'); | |
| 375 | |
| 376 if (ch<'0' || ch>'9') | |
| 377 goto error; | |
| 378 | |
| 379 r=ch-'0'; | |
| 380 while ( (ch=read_char(fp)) >='0' && (ch <= '9') ) { | |
| 381 r*=10; | |
| 382 r+=ch-'0'; | |
| 383 } | |
| 384 return r; | |
| 385 error: | |
| 386 return 0; | |
| 387 } | |
| 388 | |
| 389 Image_tree new_image_tree() | |
| 390 { | |
| 391 Image_tree t; | |
| 392 t=(Image_tree) calloc(1,sizeof(struct Image_tree_struct)); | |
| 393 t->entropy=0.0; | |
| 394 t->image=NULL; | |
| 395 t->coarse=t->horizontal=t->vertical=t->diagonal=t->doubletree=NULL; | |
| 396 t->level=0; | |
| 397 t->codec_data=NULL; | |
| 398 t->significance_map=NULL; | |
| 399 return t; | |
| 400 } | |
| 401 | |
| 402 void free_image_tree(Image_tree t) | |
| 403 { | |
| 404 if (t->coarse) free_image_tree(t->coarse); | |
| 405 if (t->horizontal) free_image_tree(t->horizontal); | |
| 406 if (t->vertical) free_image_tree(t->vertical); | |
| 407 if (t->diagonal) free_image_tree(t->diagonal); | |
| 408 if (t->doubletree) free_image_tree(t->doubletree); | |
| 409 if (t->image) free_image(t->image); | |
| 410 if (t->significance_map) free_intimage(t->significance_map); | |
| 411 if (t->codec_data) free(t->codec_data); | |
| 412 t->image=NULL; | |
| 413 free(t); | |
| 414 } | |
| 415 | |
| 416 /*********************************************************************** | |
| 417 * Functionname: get_image_infos | |
| 418 * -------------------------------------------------------------------- | |
| 419 * Parameter: | |
| 420 * Image image: input image | |
| 421 * Pixel *min,*max,*avg,*var: return minimum, maximum, | |
| 422 * average and variance of current image | |
| 423 * -------------------------------------------------------------------- | |
| 424 * Description: | |
| 425 * get statistical information of Image | |
| 426 ************************************************************************/ | |
| 427 | |
| 428 void get_image_infos(Image image, Image_info info) | |
| 429 { | |
| 430 int x,y; | |
| 431 Pixel p,sp,sp2; | |
| 432 | |
| 433 sp=sp2=(Pixel)0.0; | |
| 434 | |
| 435 p=get_pixel(image,0,0); | |
| 436 | |
| 437 info->min=info->max=p; | |
| 438 | |
| 439 for (y=0;y<image->height;y++) | |
| 440 for (x=0;x<image->width;x++) | |
| 441 { | |
| 442 p=get_pixel(image,x,y); | |
| 443 info->max=MAX(info->max,p); | |
| 444 info->min=MIN(info->min,p); | |
| 445 sp+=p; | |
| 446 sp2+=p*p; | |
| 447 } | |
| 448 sp=sp/image->width/image->height; | |
| 449 sp2=sp2/image->width/image->height; | |
| 450 | |
| 451 info->mean=sp; | |
| 452 info->var=sp2-sp*sp; | |
| 453 info->rms=sqrt(sp2); | |
| 454 } | |
| 455 | |
| 456 /*********************************************************************** | |
| 457 * Functionname: get_difference_image | |
| 458 * -------------------------------------------------------------------- | |
| 459 * Parameter: | |
| 460 * Image image1, image 2: input images | |
| 461 * | |
| 462 * Return: | |
| 463 * Image : difference of image1 and image 2, | |
| 464 * NULL if error occurs | |
| 465 ************************************************************************/ | |
| 466 | |
| 467 Image get_difference_image(Image image1, Image image2) | |
| 468 { | |
| 469 Image diff; | |
| 470 int i,max,w,h; | |
| 471 Pixel *d,*i1,*i2; | |
| 472 | |
| 473 if ((!image1) || (!image2)) return NULL; | |
| 474 | |
| 475 w=image1->width; | |
| 476 h=image1->height; | |
| 477 | |
| 478 if (image2->width != w || image2->height != h) return NULL; | |
| 479 | |
| 480 diff=new_image(w,h); | |
| 481 max=w*h; | |
| 482 | |
| 483 d=diff->data; | |
| 484 i1=image1->data; | |
| 485 i2=image2->data; | |
| 486 | |
| 487 for (i=0;i<max;i++) | |
| 488 d[i]=i2[i]-i1[i]; | |
| 489 | |
| 490 return diff; | |
| 491 } | |
| 492 | |
| 493 | |
| 494 /************************************************************************/ | |
| 495 /* Functionname: get_intimage_infos */ | |
| 496 /* -------------------------------------------------------------------- */ | |
| 497 /* Parameter: */ | |
| 498 /* IntImage image: input image */ | |
| 499 /* IntPixel *min,*max, return minimum, maximum */ | |
| 500 /* Pixel *avg,*var: average and variance of current image */ | |
| 501 /* average and variance of current image */ | |
| 502 /* -------------------------------------------------------------------- */ | |
| 503 /* Description: */ | |
| 504 /* get statistical information of Image */ | |
| 505 /************************************************************************/ | |
| 506 | |
| 507 void get_intimage_infos(IntImage image, IntPixel *min, IntPixel *max, Pixel *avg, Pixel *var) | |
| 508 { | |
| 509 int x,y; | |
| 510 Pixel p,sp,sp2; | |
| 511 | |
| 512 sp=sp2=(Pixel)0.0; | |
| 513 | |
| 514 p= (Pixel) get_intpixel(image,0,0); | |
| 515 *min=*max=p; | |
| 516 | |
| 517 for (y=0;y<image->height;y++) | |
| 518 for (x=0;x<image->width;x++) | |
| 519 { | |
| 520 p= (Pixel) get_intpixel(image,x,y); | |
| 521 *max=MAX(*max, (IntPixel) p); | |
| 522 *min=MIN(*min, (IntPixel) p); | |
| 523 sp+=p; | |
| 524 sp2+=p*p; | |
| 525 } | |
| 526 sp=sp/image->width/image->height; | |
| 527 sp2=sp2/image->width/image->height; | |
| 528 | |
| 529 *avg=sp; | |
| 530 *var=sp2-sp*sp; | |
| 531 } | |
| 532 | |
| 533 /************************************************************************/ | |
| 534 /* Functionname: init_zigzag */ | |
| 535 /* -------------------------------------------------------------------- */ | |
| 536 /* Parameter: */ | |
| 537 /* Zigzag_data_struct: */ | |
| 538 /* output: will be initialized, x/y hold coordinates of */ | |
| 539 /* the first pixel */ | |
| 540 /* int width,height: */ | |
| 541 /* input: width/height of image: */ | |
| 542 /* -------------------------------------------------------------------- */ | |
| 543 /* Description: */ | |
| 544 /* initializes Zigzag_data structure for use with next_zigzag */ | |
| 545 /************************************************************************/ | |
| 546 | |
| 547 void init_zigzag(Zigzag_data zz, int width, int height) | |
| 548 { | |
| 549 zz->x=0; | |
| 550 zz->y=0; | |
| 551 zz->dir=zigzag_up; | |
| 552 zz->w=width; | |
| 553 zz->h=height; | |
| 554 } | |
| 555 | |
| 556 /************************************************************************/ | |
| 557 /* Functionname: next_zigzag */ | |
| 558 /* -------------------------------------------------------------------- */ | |
| 559 /* Parameter: */ | |
| 560 /* Zigzag_data_struct: */ | |
| 561 /* int x,y: */ | |
| 562 /* input: current position of zigzag-scan */ | |
| 563 /* output: next position of zigzag-scan */ | |
| 564 /* int w,h: width and height of image */ | |
| 565 /* enum zigzag_direction *dir: i/o: */ | |
| 566 /* direction moving thru the image */ | |
| 567 /* -------------------------------------------------------------------- */ | |
| 568 /* Description: */ | |
| 569 /* calculates the next point (x',y') of the zigzag-scan */ | |
| 570 /* through the image with size (w,h) */ | |
| 571 /************************************************************************/ | |
| 572 | |
| 573 | |
| 574 void next_zigzag(Zigzag_data zz) | |
| 575 { | |
| 576 switch(zz->dir) | |
| 577 { | |
| 578 case zigzag_up: | |
| 579 if (zz->y==0) | |
| 580 { | |
| 581 if (zz->x==zz->w-1) | |
| 582 { | |
| 583 (zz->y)++; zz->dir=zigzag_down; | |
| 584 } | |
| 585 else | |
| 586 { | |
| 587 (zz->x)++; zz->dir=zigzag_down; | |
| 588 } | |
| 589 } | |
| 590 else | |
| 591 { | |
| 592 if (zz->x==zz->w-1) | |
| 593 { | |
| 594 (zz->y)++; zz->dir=zigzag_down; | |
| 595 } | |
| 596 else | |
| 597 { | |
| 598 (zz->x)++; (zz->y)--; | |
| 599 } | |
| 600 } | |
| 601 break; | |
| 602 | |
| 603 case zigzag_down: | |
| 604 | |
| 605 if (zz->x==0) | |
| 606 { | |
| 607 if (zz->y==zz->h-1) | |
| 608 { | |
| 609 (zz->x)++; zz->dir=zigzag_up; | |
| 610 } | |
| 611 else | |
| 612 { | |
| 613 (zz->y)++; zz->dir=zigzag_up; | |
| 614 } | |
| 615 } | |
| 616 else | |
| 617 { | |
| 618 if (zz->y==zz->h-1) | |
| 619 { | |
| 620 (zz->x)++; zz->dir=zigzag_up; | |
| 621 } | |
| 622 else | |
| 623 { | |
| 624 (zz->x)--;(zz->y)++; | |
| 625 } | |
| 626 } | |
| 627 break; | |
| 628 } | |
| 629 } | |
| 630 | |
| 631 Image get_absolute_image_scaled(Image img) | |
| 632 { | |
| 633 Image out; | |
| 634 | |
| 635 int x,y; | |
| 636 | |
| 637 struct Image_info_struct info; | |
| 638 Pixel scale,p; | |
| 639 | |
| 640 out=new_image(img->width,img->height); | |
| 641 | |
| 642 get_image_infos(img, &info); | |
| 643 | |
| 644 scale=255/MAX(fabs(info.min),fabs(info.max)); | |
| 645 | |
| 646 for(y=0;y<img->height;y++) | |
| 647 for(x=0;x<img->width;x++) | |
| 648 { | |
| 649 p=get_pixel(img,x,y)*scale; | |
| 650 set_pixel(out,x,y,p); | |
| 651 } | |
| 652 return out; | |
| 653 } | |
| 654 | |
| 655 #define FLOOR_HALF(x) ((x)&1 ? ((x)-1)/2 : (x)/2) | |
| 656 #define CEILING_HALF(x) ((x)&1 ? ((x)+1)/2 : (x)/2) | |
| 657 | |
| 658 #define MOD(a,b) ( (a)<0 ? ((b)-((-(a))%(b))) : (a)%(b) ) | |
| 659 | |
| 660 Filter new_filter(int size) | |
| 661 { | |
| 662 Filter f; | |
| 663 | |
| 664 Entering; | |
| 665 f=(Filter) calloc(1,sizeof(struct FilterStruct)); | |
| 666 f->data=(Pixel *)calloc(size,sizeof(Pixel)); | |
| 667 f->len=size; | |
| 668 f->hipass=0; | |
| 669 | |
| 670 Leaving; | |
| 671 return f; | |
| 672 } | |
| 673 | |
| 674 Pixel get_filter_center(Filter f) | |
| 675 { | |
| 676 int i; | |
| 677 Pixel p, sum, norm; | |
| 678 | |
| 679 if (f==NULL) return 0; | |
| 680 | |
| 681 sum=norm=0; | |
| 682 | |
| 683 for (i=0;i<f->len;i++) | |
| 684 { | |
| 685 p=f->data[i]; | |
| 686 p=p*p; | |
| 687 norm += p; | |
| 688 sum += (i+f->start)*p; | |
| 689 } | |
| 690 p=sum/norm; | |
| 691 | |
| 692 return p; | |
| 693 } | |
| 694 int filter_cutoff(Image in, int in_start, int in_len, int in_step, | |
| 695 Image out, int out_start, int out_len, int out_step, | |
| 696 Filter f) | |
| 697 { | |
| 698 int i,i2,j; | |
| 699 Pixel *out_pix, *in_pix, *f_data; | |
| 700 int fstart,fend; /* Source interval */ | |
| 701 | |
| 702 Entering; | |
| 703 | |
| 704 PreCondition(out_len == in_len/2,"out_len != in_len/2 !!!"); | |
| 705 | |
| 706 /* convolution: out[i]=sum_{j=start}^{end} (in[2*i-j]*f[j]) | |
| 707 | |
| 708 boundaries: image in [in_start ... in_start + in_len-1] | |
| 709 image out [out_start ... out_start + out_len-1] | |
| 710 filter f [0..f->len-1] = [f->start .. f->end] | |
| 711 cutoff at: | |
| 712 */ | |
| 713 | |
| 714 for (i=0;i<out_len;i++) | |
| 715 { | |
| 716 i2=2*i; | |
| 717 | |
| 718 fstart=i2-(in_len-1); | |
| 719 fstart=MAX(fstart,f->start); | |
| 720 fend=MIN(i2,f->end); | |
| 721 | |
| 722 #ifdef TRACE | |
| 723 sprintf(dbgstr,"i=%d fstart=%d fend=%d\n",i,fstart,fend); | |
| 724 Trace(dbgstr); | |
| 725 #endif | |
| 726 | |
| 727 out_pix=out->data+out_start+i*out_step; | |
| 728 | |
| 729 in_pix=in->data+in_start+(i2-fstart)*in_step; | |
| 730 | |
| 731 f_data=f->data-f->start+fstart; | |
| 732 | |
| 733 for (j=fstart;j<=fend;j++,in_pix-=in_step,f_data++) | |
| 734 { | |
| 735 *out_pix += (*f_data) * (*in_pix); | |
| 736 #ifdef TRACE | |
| 737 | |
| 738 sprintf(dbgstr," j=%2d in: %4.2f filter: %4.2f [%4d] [%4d] opt : %4.2f %4.2f\n", | |
| 739 j, | |
| 740 in->data[in_start+in_step*(i2-j)], | |
| 741 f->data[j-f->start], | |
| 742 in_start+in_step*(i2-j), | |
| 743 j-f->start, | |
| 744 *in_pix, *f_data); | |
| 745 Trace(dbgstr); | |
| 746 #endif | |
| 747 } | |
| 748 } | |
| 749 | |
| 750 Leaving; | |
| 751 return 1; | |
| 752 } | |
| 753 | |
| 754 | |
| 755 int filter_inv_cutoff(Image in, int in_start, int in_len, int in_step, | |
| 756 Image out, int out_start, int out_len, int out_step, | |
| 757 Filter f) | |
| 758 { | |
| 759 int i,j; | |
| 760 Pixel *out_pix, *in_pix, *f_data; | |
| 761 int fstart,fend; /* Source interval */ | |
| 762 Entering; | |
| 763 PreCondition(out_len == in_len*2,"out_len != in_len*2 !!!"); | |
| 764 | |
| 765 /* convolution: out[i]=sum_{j=start}^{end} (f[2*j-i]*in[j]) | |
| 766 | |
| 767 boundaries: image in [in_start ... in_start + in_len-1] | |
| 768 image out [out_start ... out_start + out_len-1] | |
| 769 filter f [0..f->len-1] = [f->start .. f->end] | |
| 770 cutoff at: | |
| 771 */ | |
| 772 | |
| 773 for (i=0;i<out_len;i++) | |
| 774 { | |
| 775 fstart=CEILING_HALF(f->start+i); | |
| 776 fend=FLOOR_HALF(f->end+i); | |
| 777 fstart=MAX(fstart,0); | |
| 778 fend=MIN(fend,in_len-1); | |
| 779 | |
| 780 #ifdef TRACE | |
| 781 sprintf(dbgstr,"i=%d fstart=%d fend=%d\n",i,fstart,fend); | |
| 782 Trace(dbgstr); | |
| 783 #endif | |
| 784 out_pix=out->data+out_start+i*out_step; | |
| 785 | |
| 786 in_pix=in->data+in_start+fstart*in_step; | |
| 787 | |
| 788 f_data=f->data-f->start+2*fstart-i; | |
| 789 | |
| 790 for (j=fstart;j<=fend;j++,in_pix+=in_step,f_data+=2) | |
| 791 { | |
| 792 *out_pix += (*f_data) * (*in_pix); | |
| 793 #ifdef TRACE | |
| 794 sprintf(dbgstr," j=%2d in: %4.2f filter: %4.2f [%4d] [%4d] opt : %4.2f %4.2f\n", | |
| 795 j, | |
| 796 in->data[in_start+j*in_step], | |
| 797 f->data[2*j-i-f->start], | |
| 798 in_start+j*in_step, | |
| 799 2*j-i-f->start, | |
| 800 *in_pix, *f_data); | |
| 801 Trace(dbgstr); | |
| 802 #endif | |
| 803 } | |
| 804 } | |
| 805 | |
| 806 Leaving; | |
| 807 return 1; | |
| 808 } | |
| 809 | |
| 810 int filter_periodical(Image in, int in_start, int in_len, int in_step, | |
| 811 Image out, int out_start, int out_len, int out_step, | |
| 812 Filter f) | |
| 813 { | |
| 814 int i,i2,j; | |
| 815 Pixel *out_pix, *in_pix, *f_data; | |
| 816 int fstart,fend; | |
| 817 int istart; | |
| 818 int ipix_len; | |
| 819 | |
| 820 Entering; | |
| 821 PreCondition(out_len == in_len/2,"out_len != in_len/2 !!!"); | |
| 822 | |
| 823 /* convolution: out[i]=sum_{j=start}^{end} (in[2*i-j]*f[j]) | |
| 824 | |
| 825 boundaries: image in [in_start ... in_start + in_len-1] | |
| 826 image out [out_start ... out_start + out_len-1] | |
| 827 filter f [0..f->len-1] = [f->start .. f->end] | |
| 828 */ | |
| 829 | |
| 830 ipix_len=in_len*in_step; | |
| 831 | |
| 832 for (i=0;i<out_len;i++) | |
| 833 { | |
| 834 i2=2*i; | |
| 835 | |
| 836 fstart=f->start; | |
| 837 fend=f->end; | |
| 838 | |
| 839 istart=(i2-fstart); | |
| 840 istart=MOD(istart,in_len); | |
| 841 | |
| 842 #ifdef TRACE | |
| 843 sprintf(dbgstr,"i=%d istart=%d\n",i,istart); | |
| 844 Trace(dbgstr); | |
| 845 #endif | |
| 846 | |
| 847 out_pix=out->data+out_start+i*out_step; | |
| 848 | |
| 849 in_pix=in->data+in_start+istart*in_step; | |
| 850 | |
| 851 f_data=f->data; | |
| 852 | |
| 853 for (j=fstart;j<=fend;j++,f_data++) | |
| 854 { | |
| 855 *out_pix += (*f_data) * (*in_pix); | |
| 856 #ifdef TRACE | |
| 857 | |
| 858 sprintf(dbgstr," j=%2d in: %4.2f filter: %4.2f [%4d] [%4d] opt : %4.2f %4.2f\n", | |
| 859 j, | |
| 860 in->data[in_start+in_step*((i2-j+in_len)%in_len)], | |
| 861 f->data[j-f->start], | |
| 862 in_start+in_step*((i2-j+in_len)%in_len), | |
| 863 j-f->start, | |
| 864 *in_pix, *f_data); | |
| 865 Trace(dbgstr); | |
| 866 #endif | |
| 867 in_pix-=in_step; | |
| 868 istart--; | |
| 869 if (istart<0) | |
| 870 { | |
| 871 istart+=in_len; | |
| 872 in_pix+=ipix_len; | |
| 873 } | |
| 874 } | |
| 875 } | |
| 876 | |
| 877 Leaving; | |
| 878 return 1; | |
| 879 } | |
| 880 | |
| 881 int filter_inv_periodical(Image in, int in_start, int in_len, int in_step, | |
| 882 Image out, int out_start, int out_len, int out_step, | |
| 883 Filter f) | |
| 884 { | |
| 885 int i,j; | |
| 886 Pixel *out_pix, *in_pix, *f_data; | |
| 887 int fstart,fend; /* Source interval */ | |
| 888 int istart; | |
| 889 int ipix_len; | |
| 890 Entering; | |
| 891 PreCondition(out_len == in_len*2,"out_len != in_len*2 !!!"); | |
| 892 | |
| 893 /* convolution: out[i]=sum_{j=start}^{end} (f[2*j-i]*in[j]) | |
| 894 | |
| 895 boundaries: image in [in_start ... in_start + in_len-1] | |
| 896 image out [out_start ... out_start + out_len-1] | |
| 897 filter f [0..f->len-1] = [f->start .. f->end] | |
| 898 */ | |
| 899 | |
| 900 ipix_len=in_len*in_step; | |
| 901 | |
| 902 for (i=0;i<out_len;i++) | |
| 903 { | |
| 904 fstart=CEILING_HALF(f->start+i); | |
| 905 fend=FLOOR_HALF(f->end+i); | |
| 906 | |
| 907 istart=MOD(fstart,in_len); | |
| 908 #ifdef TRACE | |
| 909 sprintf(dbgstr,"i=%d fstart=%d fend=%d istart=%d\n",i,fstart,fend,istart); | |
| 910 Trace(dbgstr); | |
| 911 #endif | |
| 912 out_pix=out->data+out_start+i*out_step; | |
| 913 | |
| 914 in_pix=in->data+in_start+istart*in_step; | |
| 915 | |
| 916 f_data=f->data-f->start+2*fstart-i; | |
| 917 | |
| 918 for (j=fstart;j<=fend;j++,f_data+=2) | |
| 919 { | |
| 920 *out_pix += (*f_data) * (*in_pix); | |
| 921 #ifdef TRACE | |
| 922 sprintf(dbgstr," j=%2d in: %4.2f filter: %4.2f [%4d] [%4d] opt : %4.2f %4.2f\n", | |
| 923 j, | |
| 924 in->data[in_start+(j % in_len)*in_step], | |
| 925 f->data[2*j-i-f->start], | |
| 926 in_start+(j%in_len)*in_step, | |
| 927 2*j-i-f->start, | |
| 928 *in_pix, *f_data); | |
| 929 Trace(dbgstr); | |
| 930 #endif | |
| 931 in_pix+=in_step; | |
| 932 istart++; | |
| 933 if (istart>=in_len) | |
| 934 { | |
| 935 istart-=in_len; | |
| 936 in_pix-=ipix_len; | |
| 937 } | |
| 938 } | |
| 939 } | |
| 940 | |
| 941 Leaving; | |
| 942 return 1; | |
| 943 } | |
| 944 | |
| 945 int filter_mirror(Image in, int in_start, int in_len, int in_step, | |
| 946 Image out, int out_start, int out_len, int out_step, | |
| 947 Filter f) | |
| 948 { | |
| 949 int i,i2,j; | |
| 950 Pixel *out_pix, *in_pix, *f_data; | |
| 951 int fstart,fend; | |
| 952 int in_pos; | |
| 953 | |
| 954 int in_dir,in_div,in_mod; | |
| 955 | |
| 956 Entering; | |
| 957 PreCondition(out_len == in_len/2,"out_len != in_len/2 !!!"); | |
| 958 | |
| 959 /* convolution: out[i]=sum_{j=start}^{end} (in[2*i-j]*f[j]) | |
| 960 | |
| 961 boundaries: image in [in_start ... in_start + in_len-1] | |
| 962 image out [out_start ... out_start + out_len-1] | |
| 963 filter f [0..f->len-1] = [f->start .. f->end] | |
| 964 */ | |
| 965 | |
| 966 in_pix=in->data+in_start; | |
| 967 | |
| 968 for (i=0;i<out_len;i++) | |
| 969 { | |
| 970 i2=2*i; | |
| 971 | |
| 972 fstart=f->start; | |
| 973 fend=f->end; | |
| 974 | |
| 975 out_pix=out->data+out_start+i*out_step; | |
| 976 | |
| 977 f_data=f->data; | |
| 978 | |
| 979 for (j=fstart;j<=fend;j++) | |
| 980 { | |
| 981 in_pos=(i2-j); | |
| 982 if (in_pos<0) | |
| 983 { | |
| 984 in_pos=-in_pos; | |
| 985 if (in_pos>=in_len) continue; | |
| 986 } | |
| 987 if (in_pos>=in_len) | |
| 988 { | |
| 989 in_pos=2*in_len-2-in_pos; | |
| 990 if (in_pos<0) continue; | |
| 991 } | |
| 992 *out_pix += (f_data[j-fstart]) * (in_pix[in_pos*in_step]); | |
| 993 } | |
| 994 } | |
| 995 | |
| 996 Leaving; | |
| 997 return 1; | |
| 998 } | |
| 999 | |
| 1000 int filter_inv_mirror(Image in, int in_start, int in_len, int in_step, | |
| 1001 Image out, int out_start, int out_len, int out_step, | |
| 1002 Filter f) | |
| 1003 { | |
| 1004 int i,j; | |
| 1005 Pixel *out_pix, *in_pix, *f_data; | |
| 1006 int fstart,fend; /* Source interval */ | |
| 1007 int in_pos,in_dir,in_div,in_mod; | |
| 1008 | |
| 1009 Entering; | |
| 1010 PreCondition(out_len == in_len*2,"out_len != in_len*2 !!!"); | |
| 1011 | |
| 1012 /* convolution: out[i]=sum_{j=start}^{end} (f[2*j-i]*in[j]) | |
| 1013 | |
| 1014 boundaries: image in [in_start ... in_start + in_len-1] | |
| 1015 image out [out_start ... out_start + out_len-1] | |
| 1016 filter f [0..f->len-1] = [f->start .. f->end] | |
| 1017 */ | |
| 1018 | |
| 1019 /*fprintf(stderr,"inv started\n");*/ | |
| 1020 for (i=0;i<out_len;i++) | |
| 1021 { | |
| 1022 fstart=CEILING_HALF(f->start+i); | |
| 1023 fend=FLOOR_HALF(f->end+i); | |
| 1024 | |
| 1025 out_pix=out->data+out_start+i*out_step; | |
| 1026 | |
| 1027 in_pix=in->data+in_start; | |
| 1028 | |
| 1029 /* | |
| 1030 printf("in: %4d - %4d flt: %4d - %4d [%s]\n",fstart,fend,2*fstart-i,2*fend-i, | |
| 1031 (2*fstart-i<f->start || 2*fend-i>f->end) ? "error":"ok"); | |
| 1032 */ | |
| 1033 /*fprintf(stderr,"inv[%d]\n",i);*/ | |
| 1034 for (j=fstart;j<=fend;j++) | |
| 1035 { | |
| 1036 in_pos=j; | |
| 1037 if (in_pos<0) | |
| 1038 { | |
| 1039 if (f->hipass) | |
| 1040 in_pos=-in_pos-1; | |
| 1041 else | |
| 1042 in_pos=-in_pos; | |
| 1043 if (in_pos>=in_len) continue; | |
| 1044 } | |
| 1045 if (in_pos>=in_len) | |
| 1046 { | |
| 1047 if (f->hipass) | |
| 1048 in_pos=2*in_len-2-in_pos; | |
| 1049 else | |
| 1050 in_pos=2*in_len-1-in_pos; | |
| 1051 if (in_pos<0) continue; | |
| 1052 } | |
| 1053 /*fprintf(stderr,"out+= %7.2f * %7.2f = %7.2f\n",f->data[2*j-i-f->start],in_pix[in_pos*in_step],f->data[2*j-i-f->start]*in_pix[in_pos*in_step]);*/ | |
| 1054 *out_pix += f->data[2*j-i-f->start] * (in_pix[in_pos*in_step]); | |
| 1055 } | |
| 1056 } | |
| 1057 | |
| 1058 Leaving; | |
| 1059 return 1; | |
| 1060 } | |
| 1061 | |
| 1062 #define MAX_LINE 256 | |
| 1063 | |
| 1064 #define skip_blank(str) { while(isspace(*(str))) (str)++; } | |
| 1065 | |
| 1066 static int get_next_line(FILE *f, char *c) | |
| 1067 { | |
| 1068 char *str,string[200]; | |
| 1069 int len; | |
| 1070 do | |
| 1071 { | |
| 1072 str=string; | |
| 1073 if (!fgets(str,200,f)) | |
| 1074 { | |
| 1075 Trace("get_next_line: eof\n"); | |
| 1076 goto error; | |
| 1077 } | |
| 1078 len=strlen(str); | |
| 1079 while (len>=1 && isspace(str[len-1])) str[--len]=0; | |
| 1080 while (isspace(*str)) str++; | |
| 1081 } | |
| 1082 while (strlen(str)==0 || *str=='#'); | |
| 1083 strcpy(c,str); | |
| 1084 return 1; | |
| 1085 error: | |
| 1086 return 0; | |
| 1087 } | |
| 1088 | |
| 1089 static int next_line_str(FILE *f, char *tag, char *out) | |
| 1090 { | |
| 1091 char str[MAX_LINE],*t_str; | |
| 1092 | |
| 1093 if (!get_next_line(f,str)) goto error; | |
| 1094 t_str=strtok(str," "); | |
| 1095 if (!t_str || strcmp(t_str,tag)) goto error; | |
| 1096 t_str=strtok(NULL,"\n"); | |
| 1097 if (!t_str) goto error; | |
| 1098 skip_blank(t_str); | |
| 1099 | |
| 1100 strcpy(out,t_str); | |
| 1101 return 1; | |
| 1102 error: | |
| 1103 return 0; | |
| 1104 } | |
| 1105 | |
| 1106 static int next_line_str_alloc(FILE *f, char *tag, char **out) | |
| 1107 { | |
| 1108 char str[MAX_LINE]; | |
| 1109 if (!next_line_str(f,tag,str)) goto error; | |
| 1110 | |
| 1111 *out=malloc(strlen(str)+1); | |
| 1112 strcpy(*out,str); | |
| 1113 | |
| 1114 return 1; | |
| 1115 error: | |
| 1116 return 0; | |
| 1117 } | |
| 1118 | |
| 1119 static int next_line_int(FILE *f, char *tag, int *out) | |
| 1120 { | |
| 1121 char str[MAX_LINE]; | |
| 1122 if (next_line_str(f,tag,str) && sscanf(str,"%d",out)==1) | |
| 1123 return 1; | |
| 1124 else | |
| 1125 return 0; | |
| 1126 } | |
| 1127 | |
| 1128 | |
| 1129 static Filter read_filter(FILE *f) | |
| 1130 { | |
| 1131 char str[MAX_LINE]; | |
| 1132 Filter filter; | |
| 1133 int i; | |
| 1134 | |
| 1135 Entering; | |
| 1136 | |
| 1137 filter=calloc(1,sizeof(struct FilterStruct)); | |
| 1138 | |
| 1139 if (!next_line_str(f,"Type",str)) goto error1; | |
| 1140 | |
| 1141 if (!strcmp(str,"nosymm")) | |
| 1142 { | |
| 1143 filter->type=FTNoSymm; | |
| 1144 } | |
| 1145 else if (!strcmp(str,"symm")) | |
| 1146 { | |
| 1147 filter->type=FTSymm; | |
| 1148 } | |
| 1149 else if (!strcmp(str,"antisymm")) | |
| 1150 { | |
| 1151 filter->type=FTAntiSymm; | |
| 1152 } | |
| 1153 else | |
| 1154 goto error1; | |
| 1155 | |
| 1156 if (!next_line_int(f,"Length",&(filter->len))) goto error1; | |
| 1157 if (!next_line_int(f,"Start",&(filter->start))) goto error1; | |
| 1158 if (!next_line_int(f,"End",&(filter->end))) goto error1; | |
| 1159 | |
| 1160 if ((filter->end-filter->start+1!=filter->len)) | |
| 1161 { | |
| 1162 Trace("error: len != end-start+1\n"); | |
| 1163 goto error1; | |
| 1164 } | |
| 1165 | |
| 1166 filter->data=calloc(filter->len,sizeof(Pixel)); | |
| 1167 | |
| 1168 for (i=0;i<filter->len;i++) | |
| 1169 { | |
| 1170 if (!get_next_line(f,str)) goto error2; | |
| 1171 if (!string_to_pixel(str,filter->data+i)) | |
| 1172 { | |
| 1173 Trace("error: invalid filter-value\n"); | |
| 1174 goto error2; | |
| 1175 } | |
| 1176 } | |
| 1177 if (!get_next_line(f,str)) goto error2; | |
| 1178 if (*str!='}') | |
| 1179 { | |
| 1180 Trace("error: '}' not found\n"); | |
| 1181 goto error2; | |
| 1182 } | |
| 1183 | |
| 1184 Leaving; | |
| 1185 return filter; | |
| 1186 | |
| 1187 error2: | |
| 1188 free(filter->data); | |
| 1189 | |
| 1190 error1: | |
| 1191 free(filter); | |
| 1192 | |
| 1193 LeavingErr; | |
| 1194 return NULL; | |
| 1195 | |
| 1196 } | |
| 1197 | |
| 1198 static FilterGH read_filter_gh(FILE *f) | |
| 1199 { | |
| 1200 char str[MAX_LINE]; | |
| 1201 FilterGH fgh; | |
| 1202 Filter filter; | |
| 1203 int i,max; | |
| 1204 | |
| 1205 Entering; | |
| 1206 | |
| 1207 fgh=calloc(1,sizeof(struct FilterGHStruct)); | |
| 1208 | |
| 1209 if (!next_line_str_alloc(f,"Name",&(fgh->name))) | |
| 1210 { | |
| 1211 Trace("error: 'Name' tag not found\n"); | |
| 1212 goto error1; | |
| 1213 } | |
| 1214 | |
| 1215 if (!next_line_str(f,"Type",str)) | |
| 1216 { | |
| 1217 Trace("error: 'Type' tag not found\n"); | |
| 1218 goto error1; | |
| 1219 } | |
| 1220 | |
| 1221 if (!strcmp(str,"orthogonal")) | |
| 1222 { | |
| 1223 fgh->type=FTOrtho; | |
| 1224 max=2; | |
| 1225 } | |
| 1226 else if (!strcmp(str,"biorthogonal")) | |
| 1227 { | |
| 1228 fgh->type=FTBiOrtho; | |
| 1229 max=4; | |
| 1230 } | |
| 1231 else if (!strcmp(str,"other")) | |
| 1232 { | |
| 1233 fgh->type=FTOther; | |
| 1234 max=4; | |
| 1235 } | |
| 1236 else | |
| 1237 { | |
| 1238 Trace("error: expecting 'orthogonal', 'biorthogonal' or 'other' type-tag\n"); | |
| 1239 goto error1; | |
| 1240 } | |
| 1241 | |
| 1242 for (i=0;i<max;i++) | |
| 1243 { | |
| 1244 if (!get_next_line(f,str)) goto error2; | |
| 1245 if (*str!='{') | |
| 1246 { | |
| 1247 Trace("error: '{' not found\n"); | |
| 1248 goto error2; | |
| 1249 } | |
| 1250 if (!(filter=read_filter(f))) | |
| 1251 { | |
| 1252 Trace("error: read_filter failed\n"); | |
| 1253 goto error2; | |
| 1254 } | |
| 1255 filter->hipass = !(i&1); | |
| 1256 switch(i) | |
| 1257 { | |
| 1258 case 0: fgh->g=filter; break; | |
| 1259 case 1: fgh->h=filter; break; | |
| 1260 case 2: fgh->gi=filter; break; | |
| 1261 case 3: fgh->hi=filter; break; | |
| 1262 } | |
| 1263 } | |
| 1264 if (!get_next_line(f,str)) goto error2; | |
| 1265 if (*str!='}') | |
| 1266 { | |
| 1267 Trace("error: '}' not found\n"); | |
| 1268 goto error2; | |
| 1269 } | |
| 1270 | |
| 1271 Leaving; | |
| 1272 return fgh; | |
| 1273 | |
| 1274 error2: | |
| 1275 if (fgh->g) free(fgh->g); | |
| 1276 if (fgh->h) free(fgh->h); | |
| 1277 if (fgh->gi) free(fgh->gi); | |
| 1278 if (fgh->hi) free(fgh->hi); | |
| 1279 | |
| 1280 error1: | |
| 1281 free(fgh); | |
| 1282 | |
| 1283 LeavingErr; | |
| 1284 return NULL; | |
| 1285 } | |
| 1286 | |
| 1287 | |
| 1288 AllFilters load_filters(char *name) | |
| 1289 { | |
| 1290 FILE *f; | |
| 1291 char str[MAX_LINE]; | |
| 1292 AllFilters a; | |
| 1293 FilterGH fgh; | |
| 1294 | |
| 1295 Entering; | |
| 1296 | |
| 1297 PreCondition(name!=NULL,"name=NULL!"); | |
| 1298 | |
| 1299 f=fopen(name,"rt"); | |
| 1300 if (!f) | |
| 1301 { | |
| 1302 Trace("error: fopen failed\n"); | |
| 1303 goto error1; | |
| 1304 } | |
| 1305 | |
| 1306 a=calloc(1,sizeof(struct AllFilterStruct)); | |
| 1307 a->count=0; | |
| 1308 | |
| 1309 while (get_next_line(f,str)) | |
| 1310 { | |
| 1311 if (*str=='{') | |
| 1312 { | |
| 1313 fgh=read_filter_gh(f); | |
| 1314 if (!fgh) | |
| 1315 { | |
| 1316 Trace("error: read_filter returned NULL\n"); | |
| 1317 goto error2; | |
| 1318 } | |
| 1319 if (a->count) | |
| 1320 a->filter=realloc(a->filter,(a->count+1)*sizeof(FilterGH)); | |
| 1321 else | |
| 1322 a->filter=malloc(sizeof(FilterGH)); | |
| 1323 (a->filter)[a->count]=fgh; | |
| 1324 a->count++; | |
| 1325 } | |
| 1326 else | |
| 1327 { | |
| 1328 Trace("error: '{' not found\n"); | |
| 1329 goto error2; | |
| 1330 } | |
| 1331 } | |
| 1332 | |
| 1333 fclose(f); | |
| 1334 | |
| 1335 Leaving; | |
| 1336 return a; | |
| 1337 | |
| 1338 error2: | |
| 1339 fclose(f); | |
| 1340 error1: | |
| 1341 | |
| 1342 LeavingErr; | |
| 1343 return 0; | |
| 1344 } | |
| 1345 | |
| 1346 #define doubletree_min 32 | |
| 1347 #define best_basis_min 8 | |
| 1348 | |
| 1349 static int convolute_lines(Image output,Image input,Filter flt,enum FilterMethod method); | |
| 1350 static int convolute_rows(Image output,Image input,Filter flt,enum FilterMethod method); | |
| 1351 static int decomposition(Image t_img,Image coarse,Image horizontal,Image vertical, | |
| 1352 Image diagonal,Filter g,Filter h,enum FilterMethod method); | |
| 1353 static int compute_best(Image_tree tree,int level,int max_level,FilterGH *flt, | |
| 1354 enum FilterMethod method,enum Information_Cost cost,double epsilon); | |
| 1355 static double compute_entropy(Image img,enum Information_Cost cost,double epsilon); | |
| 1356 static compute_levels(Image_tree tree,double *entropies,enum Information_Cost cost,double epsilon); | |
| 1357 static free_levels(Image_tree tree,int best); | |
| 1358 | |
| 1359 static Pixel sumationq(Image img); | |
| 1360 static Pixel normq(Image_tree tree); | |
| 1361 static Pixel sumation_down(Image_tree tree, Pixel normq); | |
| 1362 static Pixel compute_non_additive(Image_tree tree,int size,enum Information_Cost cost,double | |
| 1363 epsilon,int down); | |
| 1364 | |
| 1365 /************************************************************************/ | |
| 1366 /* Functionname: wavelettransform */ | |
| 1367 /* -------------------------------------------------------------------- */ | |
| 1368 /* Parameter: */ | |
| 1369 /* original: Image that should be transformed */ | |
| 1370 /* level: transform down to level */ | |
| 1371 /* flt: transform with filters flt[0..level] */ | |
| 1372 /* method: method of filtering */ | |
| 1373 /* -------------------------------------------------------------------- */ | |
| 1374 /* Description: Carries out the wavelettransform */ | |
| 1375 /* */ | |
| 1376 /************************************************************************/ | |
| 1377 extern Image_tree wavelettransform(Image original,int level,FilterGH *flt,enum FilterMethod method) | |
| 1378 { int i,width,height,min,max_level,e; | |
| 1379 Image coarsei,horizontali,verticali,diagonali,tempi; | |
| 1380 Image_tree ret_tree,temp_tree; | |
| 1381 | |
| 1382 width=original->width; | |
| 1383 height=original->height; | |
| 1384 | |
| 1385 tempi=new_image(width,height); | |
| 1386 if(!tempi) goto error; | |
| 1387 | |
| 1388 copy_into_image(tempi,original,0,0); | |
| 1389 | |
| 1390 ret_tree=new_image_tree(); | |
| 1391 if(!ret_tree) goto error; | |
| 1392 | |
| 1393 temp_tree=ret_tree; | |
| 1394 ret_tree->level=0; | |
| 1395 | |
| 1396 min=original->width; | |
| 1397 if (original->height<min) min=original->height; | |
| 1398 max_level=log(min)/log(2)-2; | |
| 1399 if (max_level<level) level=max_level; | |
| 1400 | |
| 1401 if (level<1) /* do not transform */ | |
| 1402 { | |
| 1403 ret_tree->image=tempi; | |
| 1404 return ret_tree; | |
| 1405 } | |
| 1406 | |
| 1407 /* decomposition */ | |
| 1408 | |
| 1409 for (i=0;i<level;i++) | |
| 1410 { | |
| 1411 | |
| 1412 width=(width+1)/2; | |
| 1413 height=(height+1)/2; | |
| 1414 | |
| 1415 coarsei=new_image(width,height); | |
| 1416 horizontali=new_image(width,height); | |
| 1417 verticali=new_image(width,height); | |
| 1418 diagonali=new_image(width,height); | |
| 1419 if(!coarsei||!horizontali||!verticali||!diagonali) goto error; | |
| 1420 | |
| 1421 e=decomposition(tempi,coarsei,horizontali,verticali,diagonali, | |
| 1422 flt[i]->g,flt[i]->h,method); | |
| 1423 if (!e) return NULL; | |
| 1424 | |
| 1425 temp_tree->coarse=new_image_tree(); | |
| 1426 temp_tree->horizontal=new_image_tree(); | |
| 1427 temp_tree->vertical=new_image_tree(); | |
| 1428 temp_tree->diagonal=new_image_tree(); | |
| 1429 | |
| 1430 temp_tree->coarse->level=i+1; | |
| 1431 temp_tree->horizontal->level=i+1; | |
| 1432 temp_tree->vertical->level=i+1; | |
| 1433 temp_tree->diagonal->level=i+1; | |
| 1434 | |
| 1435 temp_tree->horizontal->image=horizontali; | |
| 1436 temp_tree->vertical->image=verticali; | |
| 1437 temp_tree->diagonal->image=diagonali; | |
| 1438 free_image(tempi); | |
| 1439 | |
| 1440 if (i!=(level-1)) | |
| 1441 { | |
| 1442 tempi=new_image(width,height); | |
| 1443 copy_into_image(tempi,coarsei,0,0); | |
| 1444 free_image(coarsei); | |
| 1445 /*if i=level coarsei is inserted into the image tree | |
| 1446 so we should not free coarsei on level-1*/ | |
| 1447 } | |
| 1448 | |
| 1449 temp_tree=temp_tree->coarse; | |
| 1450 | |
| 1451 } | |
| 1452 | |
| 1453 temp_tree->image=coarsei; | |
| 1454 return ret_tree; | |
| 1455 | |
| 1456 error: | |
| 1457 err_SimpleMessage(err_GetErrorMessage(Error_NotEnoughMemory)); | |
| 1458 return NULL; | |
| 1459 } | |
| 1460 | |
| 1461 static Image_tree wavelettransform__wp(Image original, int current_level, int level, FilterGH *flt, enum FilterMethod method) | |
| 1462 { | |
| 1463 int i, width, height, min, max_level, e; | |
| 1464 Image coarse_image,horizontal_image,vertical_image,diagonal_image,temp_image; | |
| 1465 Image_tree return_tree, temp_tree; | |
| 1466 | |
| 1467 width = original->width; | |
| 1468 height = original->height; | |
| 1469 | |
| 1470 temp_image = new_image(width, height); | |
| 1471 if (!temp_image) goto error; | |
| 1472 | |
| 1473 copy_into_image(temp_image, original, 0, 0); | |
| 1474 | |
| 1475 temp_tree = return_tree = new_image_tree(); | |
| 1476 if (!return_tree) goto error; | |
| 1477 | |
| 1478 temp_tree->level = current_level; | |
| 1479 | |
| 1480 min = original->width; | |
| 1481 if (original->height < min) min = original->height; | |
| 1482 max_level = log(min) / log(2) - 2; | |
| 1483 if (max_level < level) level = max_level; | |
| 1484 | |
| 1485 if (current_level >= level) { | |
| 1486 return_tree->image = temp_image; | |
| 1487 return return_tree; | |
| 1488 } | |
| 1489 | |
| 1490 for (i = current_level; i < level; i++) { | |
| 1491 width = (width + 1) / 2; | |
| 1492 height = (height + 1) / 2; | |
| 1493 | |
| 1494 coarse_image = new_image(width, height); | |
| 1495 horizontal_image = new_image(width, height); | |
| 1496 vertical_image = new_image(width, height); | |
| 1497 diagonal_image = new_image(width, height); | |
| 1498 | |
| 1499 if (!coarse_image || !horizontal_image || | |
| 1500 !vertical_image || !diagonal_image) goto error; | |
| 1501 | |
| 1502 e = decomposition(temp_image, coarse_image, horizontal_image, | |
| 1503 vertical_image, diagonal_image, | |
| 1504 flt[i]->g, flt[i]->h, method); | |
| 1505 if (!e) return NULL; | |
| 1506 | |
| 1507 temp_tree->coarse = new_image_tree(); | |
| 1508 temp_tree->coarse->level = i+1; | |
| 1509 temp_tree->horizontal = wavelettransform__wp(horizontal_image, i+1, level, flt, method); | |
| 1510 temp_tree->vertical = wavelettransform__wp(vertical_image, i+1, level, flt, method); | |
| 1511 temp_tree->diagonal = wavelettransform__wp(diagonal_image, i+1, level, flt, method); | |
| 1512 | |
| 1513 free_image(horizontal_image); | |
| 1514 free_image(vertical_image); | |
| 1515 free_image(diagonal_image); | |
| 1516 free_image(temp_image); | |
| 1517 | |
| 1518 if (i != (level - 1)) { | |
| 1519 temp_image = new_image(width, height); | |
| 1520 copy_into_image(temp_image, coarse_image, 0, 0); | |
| 1521 free_image(coarse_image); | |
| 1522 } | |
| 1523 | |
| 1524 temp_tree = temp_tree->coarse; | |
| 1525 } | |
| 1526 | |
| 1527 temp_tree->image = coarse_image; | |
| 1528 return return_tree; | |
| 1529 | |
| 1530 error: | |
| 1531 err_SimpleMessage(err_GetErrorMessage(Error_NotEnoughMemory)); | |
| 1532 return NULL; | |
| 1533 } | |
| 1534 | |
| 1535 extern Image_tree wavelettransform_wp(Image original, int level, FilterGH *flt, enum FilterMethod method) { | |
| 1536 wavelettransform__wp(original, 0, level, flt, method); | |
| 1537 } | |
| 1538 | |
| 1539 | |
| 1540 /************************************************************************/ | |
| 1541 /* Functionname: best_basis */ | |
| 1542 /* -------------------------------------------------------------------- */ | |
| 1543 /* Parameter: */ | |
| 1544 /* original: Image to be transformed */ | |
| 1545 /* level: best basis selection down to this level */ | |
| 1546 /* flt: transform with filters flt[0..level] */ | |
| 1547 /* method: transform with filter method */ | |
| 1548 /* cost: carry best basis selection out with this costfunc */ | |
| 1549 /* epsilon: limit for threshold method */ | |
| 1550 /* -------------------------------------------------------------------- */ | |
| 1551 /* Description: carries best basis and near best basis selection */ | |
| 1552 /* out */ | |
| 1553 /************************************************************************/ | |
| 1554 extern Image_tree best_basis(Image original,int level,FilterGH *flt, | |
| 1555 enum FilterMethod method,enum Information_Cost cost,double epsilon) | |
| 1556 | |
| 1557 { Image_tree tree; | |
| 1558 Image img; | |
| 1559 int min,max_level,e; | |
| 1560 | |
| 1561 tree=new_image_tree(); | |
| 1562 if(!tree) goto error; | |
| 1563 | |
| 1564 img=new_image(original->width,original->height); | |
| 1565 if(!img) goto error; | |
| 1566 | |
| 1567 copy_into_image(img,original,0,0); | |
| 1568 | |
| 1569 tree->image=img; | |
| 1570 | |
| 1571 min=original->width; | |
| 1572 if (original->height<min) min=original->height; | |
| 1573 max_level=log10((float) min/best_basis_min)/log10(2); | |
| 1574 if (max_level>level) max_level=level; | |
| 1575 | |
| 1576 e=compute_best(tree,0,max_level,flt,method,cost,epsilon); | |
| 1577 | |
| 1578 if (!tree->image) free(img); | |
| 1579 | |
| 1580 return tree; | |
| 1581 | |
| 1582 error: | |
| 1583 err_SimpleMessage(err_GetErrorMessage(Error_NotEnoughMemory)); | |
| 1584 return NULL; | |
| 1585 | |
| 1586 } | |
| 1587 /************************************************************************/ | |
| 1588 /* Functionname: best_level_selection */ | |
| 1589 /* -------------------------------------------------------------------- */ | |
| 1590 /* Parameter: */ | |
| 1591 /* original: Image that should be transformed */ | |
| 1592 /* maxlevel: transform down to level */ | |
| 1593 /* flt: transform with filters flt[0..level] */ | |
| 1594 /* method: transform with filter method */ | |
| 1595 /* cost: carry best basis selection out with this costfunc */ | |
| 1596 /* epsilon: limit for threshold method */ | |
| 1597 /* -------------------------------------------------------------------- */ | |
| 1598 /* Description: Carries out the best level selection */ | |
| 1599 /* */ | |
| 1600 /************************************************************************/ | |
| 1601 extern Image_tree best_level(Image original,int maxlevel,int *bestlevel,FilterGH *flt,enum FilterMethod method, | |
| 1602 enum Information_Cost cost,double epsilon) | |
| 1603 { Image_tree tree; | |
| 1604 Image img; | |
| 1605 double *entropies,min; | |
| 1606 int best=0,i,e; | |
| 1607 | |
| 1608 img=new_image(original->width,original->height); | |
| 1609 copy_into_image(img,original,0,0); | |
| 1610 | |
| 1611 tree=new_image_tree(); | |
| 1612 tree->image=img; | |
| 1613 | |
| 1614 entropies=(double *)calloc(maxlevel+1,sizeof(double)); | |
| 1615 if(!entropies) goto error; | |
| 1616 | |
| 1617 /* decompose down to maxlevel */ | |
| 1618 e=decompose_all(tree,maxlevel,flt,method,cost,epsilon); | |
| 1619 if (!e) return NULL; | |
| 1620 | |
| 1621 /* compute costs of each level and store it in entropies array*/ | |
| 1622 compute_levels(tree,entropies,cost,epsilon); | |
| 1623 | |
| 1624 min=entropies[0]; | |
| 1625 for (i=1;i<=maxlevel;i++) | |
| 1626 { | |
| 1627 if (entropies[i]<min) | |
| 1628 { | |
| 1629 min=entropies[i]; | |
| 1630 best=i; | |
| 1631 } | |
| 1632 } | |
| 1633 | |
| 1634 /* free all other levels */ | |
| 1635 free_levels(tree,best); | |
| 1636 | |
| 1637 *bestlevel=best; | |
| 1638 | |
| 1639 return tree; | |
| 1640 | |
| 1641 error: | |
| 1642 err_SimpleMessage(err_GetErrorMessage(Error_NotEnoughMemory)); | |
| 1643 return NULL; | |
| 1644 } | |
| 1645 | |
| 1646 /************************************************************************/ | |
| 1647 /* Functionname: compute_best */ | |
| 1648 /* -------------------------------------------------------------------- */ | |
| 1649 /* Parameter: */ | |
| 1650 /* img: Image that should be transformed */ | |
| 1651 /* level: transform level */ | |
| 1652 /* max_level: transform to maximum level */ | |
| 1653 /* flt: transform with filters flt[0..level] */ | |
| 1654 /* method: transform with filter method */ | |
| 1655 /* cost: carry best basis selection out with this costfunc */ | |
| 1656 /* epsilon: limit for threshold method */ | |
| 1657 /* -------------------------------------------------------------------- */ | |
| 1658 /* Description: Carries out the best basis selection (recursivly) */ | |
| 1659 /* (is needed by the waveletpacket procedure) */ | |
| 1660 /************************************************************************/ | |
| 1661 static int compute_best(Image_tree tree,int level,int max_level,FilterGH *flt, | |
| 1662 enum FilterMethod method,enum Information_Cost cost,double epsilon) | |
| 1663 | |
| 1664 { Image coarse,horizontal,vertical,diagonal; | |
| 1665 int e,width,height; | |
| 1666 double sum; | |
| 1667 | |
| 1668 tree->level=level; | |
| 1669 | |
| 1670 /* non additive cost function*/ | |
| 1671 if (cost>=shanon) | |
| 1672 { | |
| 1673 tree->entropy=compute_non_additive(tree,tree->image->size,cost,epsilon,0); | |
| 1674 } | |
| 1675 /*additive cost function*/ | |
| 1676 else tree->entropy=compute_entropy(tree->image,cost,epsilon); | |
| 1677 | |
| 1678 if (level<max_level) { | |
| 1679 width=(tree->image->width+1)/2; | |
| 1680 height=(tree->image->height+1)/2; | |
| 1681 | |
| 1682 tree->coarse=new_image_tree(); | |
| 1683 tree->horizontal=new_image_tree(); | |
| 1684 tree->vertical=new_image_tree(); | |
| 1685 tree->diagonal=new_image_tree(); | |
| 1686 | |
| 1687 coarse=new_image(width,height); | |
| 1688 horizontal=new_image(width,height); | |
| 1689 vertical=new_image(width,height); | |
| 1690 diagonal=new_image(width,height); | |
| 1691 if(!coarse||!vertical||!horizontal||!diagonal) goto error; | |
| 1692 | |
| 1693 e=decomposition(tree->image,coarse,horizontal,vertical,diagonal,flt[0]->g,flt[0]->h,method); | |
| 1694 if (!e) return 0; | |
| 1695 | |
| 1696 tree->coarse->image=coarse; | |
| 1697 tree->horizontal->image=horizontal; | |
| 1698 tree->vertical->image=vertical; | |
| 1699 tree->diagonal->image=diagonal; | |
| 1700 | |
| 1701 e=compute_best(tree->coarse,level+1,max_level,flt+1,method,cost,epsilon); | |
| 1702 e=compute_best(tree->horizontal,level+1,max_level,flt+1,method,cost,epsilon); | |
| 1703 e=compute_best(tree->vertical,level+1,max_level,flt+1,method,cost,epsilon); | |
| 1704 e=compute_best(tree->diagonal,level+1,max_level,flt+1,method,cost,epsilon); | |
| 1705 if (!e) return 0; | |
| 1706 | |
| 1707 /*going back in recursion*/ | |
| 1708 | |
| 1709 if (cost>=shanon) { | |
| 1710 sum=compute_non_additive(tree,tree->image->size,cost,epsilon,1); | |
| 1711 } | |
| 1712 else sum=(tree->coarse->entropy)+(tree->horizontal->entropy) | |
| 1713 +(tree->vertical->entropy)+(tree->diagonal->entropy); | |
| 1714 | |
| 1715 if (tree->entropy>sum) | |
| 1716 { | |
| 1717 tree->entropy=sum; | |
| 1718 free_image(tree->image); /* take down tree */ | |
| 1719 tree->image=NULL; | |
| 1720 | |
| 1721 } | |
| 1722 else | |
| 1723 { /* delete the tree downwards */ | |
| 1724 free_image_tree(tree->coarse); | |
| 1725 free_image_tree(tree->horizontal); | |
| 1726 free_image_tree(tree->vertical); | |
| 1727 free_image_tree(tree->diagonal); | |
| 1728 | |
| 1729 tree->coarse=tree->vertical=tree->horizontal=tree->diagonal=NULL; | |
| 1730 } | |
| 1731 } | |
| 1732 | |
| 1733 return 1; | |
| 1734 | |
| 1735 error: | |
| 1736 err_SimpleMessage(err_GetErrorMessage(Error_NotEnoughMemory)); | |
| 1737 return 0; | |
| 1738 | |
| 1739 } | |
| 1740 | |
| 1741 /************************************************************************/ | |
| 1742 /* Functionname: decompose_all */ | |
| 1743 /* -------------------------------------------------------------------- */ | |
| 1744 /* Parameter: */ | |
| 1745 /* tree: Image tree to be decomposed */ | |
| 1746 /* maxlevel: decompose down to level */ | |
| 1747 /* flt: transform with filters flt[0..maxlevel] */ | |
| 1748 /* method: transform with filter method */ | |
| 1749 /* cost: cost function for entropy computing */ | |
| 1750 /* epsilon: limit for threshold method */ | |
| 1751 /* -------------------------------------------------------------------- */ | |
| 1752 /* Description: whole decompositing down to maxlevel */ | |
| 1753 /* The original image must be in tree->image */ | |
| 1754 /************************************************************************/ | |
| 1755 extern int decompose_all(Image_tree tree,int maxlevel,FilterGH *flt,enum FilterMethod method, | |
| 1756 enum Information_Cost cost,double epsilon) | |
| 1757 { | |
| 1758 Image original,coarse,horizontal,vertical,diagonal; | |
| 1759 int e,width,height,level; | |
| 1760 | |
| 1761 if (tree->level<maxlevel) | |
| 1762 { | |
| 1763 tree->coarse=new_image_tree(); | |
| 1764 tree->horizontal=new_image_tree(); | |
| 1765 tree->vertical=new_image_tree(); | |
| 1766 tree->diagonal=new_image_tree(); | |
| 1767 | |
| 1768 original=tree->image; | |
| 1769 width=(original->width+1)/2; | |
| 1770 height=(original->height+1)/2; | |
| 1771 level=tree->level; | |
| 1772 | |
| 1773 coarse=new_image(width,height); | |
| 1774 horizontal=new_image(width,height); | |
| 1775 vertical=new_image(width,height); | |
| 1776 diagonal=new_image(width,height); | |
| 1777 if(!coarse||!vertical||!horizontal||!diagonal) goto error; | |
| 1778 | |
| 1779 | |
| 1780 e=decomposition(tree->image,coarse,horizontal,vertical,diagonal,flt[0]->g,flt[0]->h,method); | |
| 1781 if (!e) return 0; | |
| 1782 | |
| 1783 tree->coarse->image=coarse; | |
| 1784 tree->horizontal->image=horizontal; | |
| 1785 tree->vertical->image=vertical; | |
| 1786 tree->diagonal->image=diagonal; | |
| 1787 | |
| 1788 tree->coarse->entropy=compute_entropy(coarse,cost,epsilon); | |
| 1789 tree->horizontal->entropy=compute_entropy(horizontal,cost,epsilon); | |
| 1790 tree->vertical->entropy=compute_entropy(vertical,cost,epsilon); | |
| 1791 tree->diagonal->entropy=compute_entropy(diagonal,cost,epsilon); | |
| 1792 | |
| 1793 tree->coarse->level=tree->horizontal->level= | |
| 1794 tree->vertical->level=tree->diagonal->level=level+1; | |
| 1795 | |
| 1796 e=decompose_all(tree->coarse,maxlevel,flt+1,method,cost,epsilon); | |
| 1797 e=decompose_all(tree->horizontal,maxlevel,flt+1,method,cost,epsilon); | |
| 1798 e=decompose_all(tree->vertical,maxlevel,flt+1,method,cost,epsilon); | |
| 1799 e=decompose_all(tree->diagonal,maxlevel,flt+1,method,cost,epsilon); | |
| 1800 if (!e) return 0; | |
| 1801 | |
| 1802 } | |
| 1803 | |
| 1804 return 1; | |
| 1805 | |
| 1806 error: | |
| 1807 err_SimpleMessage(err_GetErrorMessage(Error_NotEnoughMemory)); | |
| 1808 return 0; | |
| 1809 } | |
| 1810 | |
| 1811 /************************************************************************/ | |
| 1812 /* Functionname: compute_levels */ | |
| 1813 /* -------------------------------------------------------------------- */ | |
| 1814 /* Parameter: */ | |
| 1815 /* tree: Image tree where the entropy should be computed */ | |
| 1816 /* entropies : array for entropy */ | |
| 1817 /* cost: carry best basis selection out with this costfunc */ | |
| 1818 /* epsilon: limit for threshold method */ | |
| 1819 /* -------------------------------------------------------------------- */ | |
| 1820 /* Description: Compute the entropies of all decomposition levels */ | |
| 1821 /************************************************************************/ | |
| 1822 static compute_levels(Image_tree tree,double *entropies,enum Information_Cost cost,double epsilon) | |
| 1823 { | |
| 1824 if (tree->image){ | |
| 1825 entropies[tree->level]+=compute_entropy(tree->image,cost,epsilon); | |
| 1826 } | |
| 1827 if (tree->coarse) compute_levels(tree->coarse,entropies,cost,epsilon); | |
| 1828 if (tree->horizontal) compute_levels(tree->horizontal,entropies,cost,epsilon); | |
| 1829 if (tree->vertical) compute_levels(tree->vertical,entropies,cost,epsilon); | |
| 1830 if (tree->diagonal) compute_levels(tree->diagonal,entropies,cost,epsilon); | |
| 1831 | |
| 1832 } | |
| 1833 | |
| 1834 /************************************************************************/ | |
| 1835 /* Functionname: free_levels */ | |
| 1836 /* -------------------------------------------------------------------- */ | |
| 1837 /* Parameter: */ | |
| 1838 /* tree: Image tree which should be cleaned */ | |
| 1839 /* best: best level */ | |
| 1840 /* -------------------------------------------------------------------- */ | |
| 1841 /* Description: clean the image tree except the best level */ | |
| 1842 /************************************************************************/ | |
| 1843 static free_levels(Image_tree tree,int best) | |
| 1844 { | |
| 1845 if (tree->level<best) | |
| 1846 { | |
| 1847 free_image(tree->image); | |
| 1848 tree->image=NULL; | |
| 1849 free_levels(tree->coarse,best); | |
| 1850 free_levels(tree->horizontal,best); | |
| 1851 free_levels(tree->vertical,best); | |
| 1852 free_levels(tree->diagonal,best); | |
| 1853 } | |
| 1854 else | |
| 1855 { | |
| 1856 if (tree->coarse) | |
| 1857 { | |
| 1858 free_image_tree(tree->coarse); | |
| 1859 free_image_tree(tree->horizontal); | |
| 1860 free_image_tree(tree->vertical); | |
| 1861 free_image_tree(tree->diagonal); | |
| 1862 tree->coarse=tree->horizontal=tree->vertical=tree->diagonal=NULL; | |
| 1863 } | |
| 1864 } | |
| 1865 } | |
| 1866 | |
| 1867 /************************************************************************/ | |
| 1868 /* Functionname: decompose_to_level */ | |
| 1869 /* -------------------------------------------------------------------- */ | |
| 1870 /* Parameter: */ | |
| 1871 /* original: original image */ | |
| 1872 /* level: decompose to level */ | |
| 1873 /* flt: decompos with filters[0..level] */ | |
| 1874 /* method: transform with filter method */ | |
| 1875 /* -------------------------------------------------------------------- */ | |
| 1876 /* Description: Decomposes an image to an certain level and stores */ | |
| 1877 /* only this level in the returned quadtree */ | |
| 1878 /************************************************************************/ | |
| 1879 extern Image_tree decompose_to_level(Image original,int level,FilterGH *flt,enum FilterMethod method) | |
| 1880 { Image_tree tree; | |
| 1881 int e; | |
| 1882 | |
| 1883 tree=new_image_tree(); | |
| 1884 tree->image=original; | |
| 1885 | |
| 1886 e=decompose_all(tree,level,flt,method,entropy,1); | |
| 1887 if (!e) return NULL; | |
| 1888 | |
| 1889 free_levels(tree,level); | |
| 1890 | |
| 1891 return tree; | |
| 1892 | |
| 1893 } | |
| 1894 | |
| 1895 /************************************************************************/ | |
| 1896 /* Functionname: decomposition */ | |
| 1897 /* -------------------------------------------------------------------- */ | |
| 1898 /* Parameter: */ | |
| 1899 /* t_img: Image which should be decomposed */ | |
| 1900 /* coarse,horizontal,vertical,diagonal: */ | |
| 1901 /* decomposed images */ | |
| 1902 /* method: transform with filter method */ | |
| 1903 /* g,h: the transformation is carried out with these filters*/ | |
| 1904 /* -------------------------------------------------------------------- */ | |
| 1905 /* Description: This carries out one wavelettransformation */ | |
| 1906 /* using waveletfilters. */ | |
| 1907 /************************************************************************/ | |
| 1908 | |
| 1909 static int decomposition(Image t_img,Image coarse,Image horizontal,Image vertical, | |
| 1910 Image diagonal,Filter g,Filter h,enum FilterMethod method) | |
| 1911 { Image temp1; | |
| 1912 | |
| 1913 /*coarse*/ | |
| 1914 temp1=new_image(coarse->width,t_img->height); | |
| 1915 if(!temp1) goto error; | |
| 1916 convolute_lines(temp1,t_img,h,method); | |
| 1917 convolute_rows(coarse,temp1,h,method); | |
| 1918 | |
| 1919 /*horizontal*/ | |
| 1920 convolute_rows(horizontal,temp1,g,method); | |
| 1921 free_image(temp1); | |
| 1922 | |
| 1923 /*vertical*/ | |
| 1924 temp1=new_image(vertical->width,t_img->height); | |
| 1925 if(!temp1) goto error; | |
| 1926 convolute_lines(temp1,t_img,g,method); | |
| 1927 convolute_rows(vertical,temp1,h,method); | |
| 1928 | |
| 1929 /*diagonal*/ | |
| 1930 convolute_rows(diagonal,temp1,g,method); | |
| 1931 free_image(temp1); | |
| 1932 | |
| 1933 return 1; | |
| 1934 | |
| 1935 error: | |
| 1936 err_SimpleMessage(err_GetErrorMessage(Error_NotEnoughMemory)); | |
| 1937 return 0; | |
| 1938 | |
| 1939 } | |
| 1940 | |
| 1941 /************************************************************************/ | |
| 1942 /* Functionname: inv_decomposition */ | |
| 1943 /* -------------------------------------------------------------------- */ | |
| 1944 /* Parameter: */ | |
| 1945 /* sum: reconstructed image */ | |
| 1946 /* coarse,horizontal,vertical,diagonal: images to carry out*/ | |
| 1947 /* the inverse transformation */ | |
| 1948 /* flt_gh: transform with filters g and h */ | |
| 1949 /* method: transform with filter method */ | |
| 1950 /* -------------------------------------------------------------------- */ | |
| 1951 /* Description: Carries out the wavelettransform */ | |
| 1952 /* */ | |
| 1953 /************************************************************************/ | |
| 1954 static int inv_decomposition(Image sum,Image coarse,Image horizontal,Image vertical, | |
| 1955 Image diagonal,FilterGH flt_gh,enum FilterMethod method) | |
| 1956 { Image temp1; | |
| 1957 Filter g,h; | |
| 1958 | |
| 1959 if (flt_gh->type==FTOrtho) { | |
| 1960 g=flt_gh->g; | |
| 1961 h=flt_gh->h; | |
| 1962 } | |
| 1963 else { | |
| 1964 g=flt_gh->gi; | |
| 1965 h=flt_gh->hi; | |
| 1966 } | |
| 1967 | |
| 1968 /*coarse*/ | |
| 1969 temp1=new_image(coarse->width,sum->height); | |
| 1970 if(!temp1) goto error; | |
| 1971 convolute_rows(temp1,coarse,h,method); | |
| 1972 | |
| 1973 /*horizontal*/ | |
| 1974 convolute_rows(temp1,horizontal,g,method); | |
| 1975 convolute_lines(sum,temp1,h,method); | |
| 1976 free_image(temp1); | |
| 1977 | |
| 1978 /*vertical*/ | |
| 1979 temp1=new_image(vertical->width,sum->height); | |
| 1980 if(!temp1) goto error; | |
| 1981 convolute_rows(temp1,vertical,h,method); | |
| 1982 | |
| 1983 /*diagonal*/ | |
| 1984 convolute_rows(temp1,diagonal,g,method); | |
| 1985 convolute_lines(sum,temp1,g,method); | |
| 1986 | |
| 1987 free_image(temp1); | |
| 1988 | |
| 1989 return 1; | |
| 1990 | |
| 1991 error: | |
| 1992 err_SimpleMessage(err_GetErrorMessage(Error_NotEnoughMemory)); | |
| 1993 return 0; | |
| 1994 } | |
| 1995 | |
| 1996 /************************************************************************/ | |
| 1997 /* Functionname: build_image */ | |
| 1998 /* -------------------------------------------------------------------- */ | |
| 1999 /* Parameter: */ | |
| 2000 /* quadtree: quadtree with decomposition information */ | |
| 2001 /* width,height: image width and height */ | |
| 2002 /* RETURN: returns the build up image */ | |
| 2003 /* -------------------------------------------------------------------- */ | |
| 2004 /* Description: builds up an image out of an Image_tree */ | |
| 2005 /* */ | |
| 2006 /************************************************************************/ | |
| 2007 extern Image build_image(Image_tree quadtree,int width,int height) | |
| 2008 { Image ret_img,coarse,horizontal,vertical,diagonal; | |
| 2009 | |
| 2010 | |
| 2011 ret_img=new_image(width,height); | |
| 2012 if(!ret_img) goto error; | |
| 2013 | |
| 2014 width=(width+1)/2; | |
| 2015 height=(height+1)/2; | |
| 2016 | |
| 2017 if (!(quadtree->image)) { | |
| 2018 coarse=build_image(quadtree->coarse,width,height); | |
| 2019 horizontal=build_image(quadtree->horizontal,width,height); | |
| 2020 vertical=build_image(quadtree->vertical,width,height); | |
| 2021 diagonal=build_image(quadtree->diagonal,width,height); | |
| 2022 if (!coarse||!horizontal||!vertical||!diagonal) return NULL; | |
| 2023 | |
| 2024 copy_into_image(ret_img,coarse,0,0); | |
| 2025 copy_into_image(ret_img,horizontal,width,0); | |
| 2026 copy_into_image(ret_img,vertical,0,height); | |
| 2027 copy_into_image(ret_img,diagonal,width,height); | |
| 2028 | |
| 2029 if (!quadtree->coarse->image) free_image(coarse); | |
| 2030 if (!quadtree->horizontal->image) free_image(horizontal); | |
| 2031 if (!quadtree->vertical->image) free_image(vertical); | |
| 2032 if (!quadtree->diagonal->image) free_image(diagonal); | |
| 2033 | |
| 2034 return ret_img; | |
| 2035 } | |
| 2036 else return quadtree->image; | |
| 2037 | |
| 2038 error: | |
| 2039 err_SimpleMessage(err_GetErrorMessage(Error_NotEnoughMemory)); | |
| 2040 return NULL; | |
| 2041 } | |
| 2042 | |
| 2043 /************************************************************************/ | |
| 2044 /* Functionname: inv_transform */ | |
| 2045 /* -------------------------------------------------------------------- */ | |
| 2046 /* Parameter: */ | |
| 2047 /* tree: tree with decomposition information */ | |
| 2048 /* flt_gh: transform with filters g and h */ | |
| 2049 /* method: transform with filter method */ | |
| 2050 /* -------------------------------------------------------------------- */ | |
| 2051 /* Description: Inverts the wavelettransform,best_basis,best_level */ | |
| 2052 /* */ | |
| 2053 /************************************************************************/ | |
| 2054 extern Image inv_transform(Image_tree tree,FilterGH *flt, | |
| 2055 enum FilterMethod method) | |
| 2056 | |
| 2057 { int er,width,height; | |
| 2058 Image ret_img,coarse,vertical,horizontal,diagonal; | |
| 2059 | |
| 2060 if (!tree->image) { | |
| 2061 | |
| 2062 coarse=inv_transform(tree->coarse,flt,method); | |
| 2063 horizontal=inv_transform(tree->horizontal,flt,method); | |
| 2064 vertical=inv_transform(tree->vertical,flt,method); | |
| 2065 diagonal=inv_transform(tree->diagonal,flt,method); | |
| 2066 if (!coarse||!horizontal||!vertical||!diagonal) return NULL; | |
| 2067 | |
| 2068 width=coarse->width+horizontal->width; | |
| 2069 height=coarse->height+vertical->height; | |
| 2070 | |
| 2071 ret_img=new_image(width,height); | |
| 2072 if(!ret_img) goto error; | |
| 2073 | |
| 2074 | |
| 2075 if (tree->flag==0) /*if flag is set it is a doubletree tiling*/ | |
| 2076 { | |
| 2077 // er=inv_decomposition(ret_img,coarse,horizontal,vertical,diagonal,flt[1],method); | |
| 2078 er=inv_decomposition(ret_img,coarse,horizontal,vertical,diagonal,flt[tree->level],method); | |
| 2079 if (!er) return NULL; | |
| 2080 } | |
| 2081 else | |
| 2082 { | |
| 2083 copy_into_image(ret_img,coarse,0,0); | |
| 2084 copy_into_image(ret_img,horizontal,coarse->width,0); | |
| 2085 copy_into_image(ret_img,vertical,0,coarse->height); | |
| 2086 copy_into_image(ret_img,diagonal,coarse->width,coarse->height); | |
| 2087 } | |
| 2088 | |
| 2089 if (!tree->coarse->image) free_image(coarse); | |
| 2090 if (!tree->horizontal->image) free_image(horizontal); | |
| 2091 if (!tree->vertical->image) free_image(vertical); | |
| 2092 if (!tree->diagonal->image) free_image(diagonal); | |
| 2093 | |
| 2094 return ret_img; | |
| 2095 } | |
| 2096 | |
| 2097 else return tree->image; | |
| 2098 | |
| 2099 error: | |
| 2100 err_SimpleMessage(err_GetErrorMessage(Error_NotEnoughMemory)); | |
| 2101 return NULL; | |
| 2102 } | |
| 2103 | |
| 2104 /************************************************************************/ | |
| 2105 /* Functionname: find_deepest_level */ | |
| 2106 /* -------------------------------------------------------------------- */ | |
| 2107 /* Parameter: */ | |
| 2108 /* -------------------------------------------------------------------- */ | |
| 2109 /* Description: Finds the deepest possible level where width and */ | |
| 2110 /* height can divided by two exactly. */ | |
| 2111 /************************************************************************/ | |
| 2112 extern int find_deepest_level(int width,int height) | |
| 2113 { | |
| 2114 int level=0,w=width,h=height; | |
| 2115 | |
| 2116 while ( !((w%2)||(h%2))) | |
| 2117 { | |
| 2118 w=w/2; | |
| 2119 h=h/2; | |
| 2120 level++; | |
| 2121 } | |
| 2122 | |
| 2123 return level-1; | |
| 2124 | |
| 2125 } | |
| 2126 | |
| 2127 /************************************************************************/ | |
| 2128 /* Functionname: convolute_lines */ | |
| 2129 /* -------------------------------------------------------------------- */ | |
| 2130 /* Parameter: */ | |
| 2131 /* output: output image of wavelettransformation */ | |
| 2132 /* input: input image for decomposition */ | |
| 2133 /* flt: transform with filter flt */ | |
| 2134 /* method: transform with filter method */ | |
| 2135 /* -------------------------------------------------------------------- */ | |
| 2136 /* Description: Carries out the wavelettransform for all lines of */ | |
| 2137 /* the input image */ | |
| 2138 /************************************************************************/ | |
| 2139 static int convolute_lines(Image output,Image input,Filter flt,enum FilterMethod method) | |
| 2140 /*Convolute the lines with filter*/ | |
| 2141 { int i; | |
| 2142 | |
| 2143 for (i=0;i<input->height;i++) { | |
| 2144 switch(method) { | |
| 2145 case cutoff: | |
| 2146 filter_cutoff(input,input->width*i,input->width,1, | |
| 2147 output,output->width*i,output->width,1,flt); | |
| 2148 break; | |
| 2149 case inv_cutoff: | |
| 2150 filter_inv_cutoff(input,input->width*i,input->width,1, | |
| 2151 output,output->width*i,output->width,1,flt); | |
| 2152 break; | |
| 2153 case periodical: | |
| 2154 filter_periodical(input,input->width*i,input->width,1, | |
| 2155 output,output->width*i,output->width,1,flt); | |
| 2156 break; | |
| 2157 case inv_periodical: | |
| 2158 filter_inv_periodical(input,input->width*i,input->width,1, | |
| 2159 output,output->width*i,output->width,1,flt); | |
| 2160 break; | |
| 2161 case mirror: | |
| 2162 filter_mirror(input,input->width*i,input->width,1, | |
| 2163 output,output->width*i,output->width,1,flt); | |
| 2164 break; | |
| 2165 case inv_mirror: | |
| 2166 filter_inv_mirror(input,input->width*i,input->width,1, | |
| 2167 output,output->width*i,output->width,1,flt); | |
| 2168 break; | |
| 2169 | |
| 2170 | |
| 2171 } | |
| 2172 } | |
| 2173 | |
| 2174 return 1; | |
| 2175 } | |
| 2176 | |
| 2177 /************************************************************************/ | |
| 2178 /* Functionname: convolute_rows */ | |
| 2179 /* -------------------------------------------------------------------- */ | |
| 2180 /* Parameter: */ | |
| 2181 /* output: output image of wavelettransformation */ | |
| 2182 /* input: input image for decomposition */ | |
| 2183 /* flt: transform with filter flt */ | |
| 2184 /* method: transform with filter method */ | |
| 2185 /* -------------------------------------------------------------------- */ | |
| 2186 /* Description: Carries out the wavelettransform for all rows of */ | |
| 2187 /* the input image */ | |
| 2188 /************************************************************************/ | |
| 2189 static int convolute_rows(Image output,Image input,Filter flt,enum FilterMethod method) | |
| 2190 /*Convolute the rows with filter*/ | |
| 2191 { int i; | |
| 2192 | |
| 2193 for (i=0;i<input->width;i++) | |
| 2194 { | |
| 2195 switch (method) | |
| 2196 { | |
| 2197 case cutoff: | |
| 2198 filter_cutoff(input,i,input->height,input->width, | |
| 2199 output,i,output->height,output->width,flt); | |
| 2200 break; | |
| 2201 case inv_cutoff: | |
| 2202 filter_inv_cutoff(input,i,input->height,input->width, | |
| 2203 output,i,output->height,output->width,flt); | |
| 2204 break; | |
| 2205 case periodical: | |
| 2206 filter_periodical(input,i,input->height,input->width, | |
| 2207 output,i,output->height,output->width,flt); | |
| 2208 break; | |
| 2209 case inv_periodical: | |
| 2210 filter_inv_periodical(input,i,input->height,input->width, | |
| 2211 output,i,output->height,output->width,flt); | |
| 2212 break; | |
| 2213 case mirror: | |
| 2214 filter_mirror(input,i,input->height,input->width, | |
| 2215 output,i,output->height,output->width,flt); | |
| 2216 break; | |
| 2217 case inv_mirror: | |
| 2218 filter_inv_mirror(input,i,input->height,input->width, | |
| 2219 output,i,output->height,output->width,flt); | |
| 2220 break; | |
| 2221 | |
| 2222 } | |
| 2223 } | |
| 2224 return 1; | |
| 2225 } | |
| 2226 | |
| 2227 /************************************************************************/ | |
| 2228 /* Functionname: sumationq */ | |
| 2229 /* -------------------------------------------------------------------- */ | |
| 2230 /* Parameter: */ | |
| 2231 /* img: image to compute */ | |
| 2232 /* -------------------------------------------------------------------- */ | |
| 2233 /* Description: compute the sum of quadrats of all elements of */ | |
| 2234 /* the input image */ | |
| 2235 /************************************************************************/ | |
| 2236 static Pixel sumationq(Image img) | |
| 2237 { Pixel sum=0; | |
| 2238 int i; | |
| 2239 | |
| 2240 for (i=0;i<img->size;i++) { | |
| 2241 sum+=(*img->data+i)*(*img->data+i); | |
| 2242 } | |
| 2243 return sum; | |
| 2244 } | |
| 2245 | |
| 2246 /************************************************************************/ | |
| 2247 /* Functionname: normq */ | |
| 2248 /* -------------------------------------------------------------------- */ | |
| 2249 /* Parameter: */ | |
| 2250 /* tree: tree to compute */ | |
| 2251 /* -------------------------------------------------------------------- */ | |
| 2252 /* Description: computes the quadratic norm over all images in */ | |
| 2253 /* the input tree */ | |
| 2254 /************************************************************************/ | |
| 2255 static Pixel normq(Image_tree tree) | |
| 2256 { Pixel sum=0; | |
| 2257 | |
| 2258 if (tree->image) | |
| 2259 { | |
| 2260 sum=sumationq(tree->image); | |
| 2261 } | |
| 2262 else | |
| 2263 { | |
| 2264 if (tree->coarse) sum+=normq(tree->coarse); | |
| 2265 if (tree->horizontal) sum+=normq(tree->horizontal); | |
| 2266 if (tree->vertical) sum+=normq(tree->vertical); | |
| 2267 if (tree->diagonal) sum+=normq(tree->diagonal); | |
| 2268 } | |
| 2269 | |
| 2270 return sum; | |
| 2271 } | |
| 2272 | |
| 2273 /************************************************************************/ | |
| 2274 /* Functionname: sumation_down */ | |
| 2275 /* -------------------------------------------------------------------- */ | |
| 2276 /* Parameter: */ | |
| 2277 /* tree: tree to compute */ | |
| 2278 /* normq: norm of the images in the tree */ | |
| 2279 /* -------------------------------------------------------------------- */ | |
| 2280 /* Description: computes the Entropy over all (string aded) images */ | |
| 2281 /* in the input tree */ | |
| 2282 /************************************************************************/ | |
| 2283 static Pixel sumation_down(Image_tree tree, Pixel normq) | |
| 2284 { Pixel sum=0,p; | |
| 2285 int i; | |
| 2286 Image img; | |
| 2287 Pixel *data; | |
| 2288 | |
| 2289 if (tree->image) | |
| 2290 { | |
| 2291 img=tree->image; | |
| 2292 data=img->data; | |
| 2293 for (i=0;i<img->size;i++,data++) | |
| 2294 { | |
| 2295 if (*data!=0) | |
| 2296 { | |
| 2297 p=(*data)*(*data)/normq; | |
| 2298 sum+=p*log(1/p); | |
| 2299 } | |
| 2300 } | |
| 2301 } | |
| 2302 else | |
| 2303 { | |
| 2304 if (tree->coarse) sum+=sumation_down(tree->coarse,normq); | |
| 2305 if (tree->horizontal) sum+=sumation_down(tree->horizontal,normq); | |
| 2306 if (tree->vertical) sum+=sumation_down(tree->vertical,normq); | |
| 2307 if (tree->diagonal) sum+=sumation_down(tree->diagonal,normq); | |
| 2308 } | |
| 2309 | |
| 2310 return sum; | |
| 2311 } | |
| 2312 | |
| 2313 /************************************************************************/ | |
| 2314 /* Functionname: comp */ | |
| 2315 /* -------------------------------------------------------------------- */ | |
| 2316 /* Description: used for quicksort for decreasing order */ | |
| 2317 /************************************************************************/ | |
| 2318 int comp(const Pixel *x,const Pixel *y) | |
| 2319 { | |
| 2320 if (*x<*y) return 1; | |
| 2321 else if (*x==*y) return 0; | |
| 2322 else return -1; | |
| 2323 } | |
| 2324 | |
| 2325 /************************************************************************/ | |
| 2326 /* Functionname: recarea */ | |
| 2327 /* tree: Image tree to compute */ | |
| 2328 /* list: target list */ | |
| 2329 /* list_size: actual size of the list */ | |
| 2330 /* -------------------------------------------------------------------- */ | |
| 2331 /* Description: copies all elements within the tree into an list */ | |
| 2332 /************************************************************************/ | |
| 2333 static void recarea(Image_tree tree,Pixel *list,int *list_size) | |
| 2334 { Image img; | |
| 2335 | |
| 2336 if (tree->image) | |
| 2337 { | |
| 2338 img=tree->image; | |
| 2339 memcpy(list+(*list_size),img->data,img->size*sizeof(Pixel)); | |
| 2340 *list_size+=img->size; | |
| 2341 } | |
| 2342 else | |
| 2343 { | |
| 2344 if (tree->coarse) recarea(tree->coarse,list,list_size); | |
| 2345 if (tree->horizontal) recarea(tree->horizontal,list,list_size); | |
| 2346 if (tree->vertical) recarea(tree->vertical,list,list_size); | |
| 2347 if (tree->diagonal) recarea(tree->diagonal,list,list_size); | |
| 2348 } | |
| 2349 | |
| 2350 } | |
| 2351 | |
| 2352 static void abs_list(Pixel *list,int list_size) | |
| 2353 { | |
| 2354 int i; | |
| 2355 | |
| 2356 for (i=0;i<list_size;i++) list[i]=fabs(list[i]); | |
| 2357 } | |
| 2358 | |
| 2359 /************************************************************************/ | |
| 2360 /* Functionname: sum_list */ | |
| 2361 /* -------------------------------------------------------------------- */ | |
| 2362 /* Description: computes the sum of all poweres list elements */ | |
| 2363 /************************************************************************/ | |
| 2364 static Pixel sum_list(Pixel *list,int p,int size) | |
| 2365 { Pixel sum=0; | |
| 2366 int i; | |
| 2367 | |
| 2368 for (i=0;i<size;i++) | |
| 2369 { | |
| 2370 if (p!=1) sum+=pow(list[i],p); | |
| 2371 else sum+=list[i]; | |
| 2372 } | |
| 2373 return sum; | |
| 2374 } | |
| 2375 | |
| 2376 static Pixel weak_lp(Image_tree tree,int size,int p,double epsilon) | |
| 2377 { Pixel wlp,*list,max=0; | |
| 2378 int *list_size,k; | |
| 2379 | |
| 2380 list_size=(int *)malloc(sizeof(int)); | |
| 2381 if (!list_size) goto error; | |
| 2382 | |
| 2383 *list_size=0; | |
| 2384 | |
| 2385 list=(Pixel *)calloc(size,sizeof(Pixel)); | |
| 2386 if (!list) goto error; | |
| 2387 | |
| 2388 recarea(tree,list,list_size); | |
| 2389 abs_list(list,*list_size); | |
| 2390 | |
| 2391 qsort(list,*list_size, sizeof(Pixel), &comp); | |
| 2392 | |
| 2393 for (k=0;k<size;k++) | |
| 2394 { | |
| 2395 if (k!=0) wlp=pow(k,1/p)*list[k]; | |
| 2396 else wlp=0; | |
| 2397 if (wlp>max) max=wlp; | |
| 2398 } | |
| 2399 | |
| 2400 free(list); | |
| 2401 | |
| 2402 return max; | |
| 2403 | |
| 2404 error: | |
| 2405 err_SimpleMessage(err_GetErrorMessage(Error_NotEnoughMemory)); | |
| 2406 return 0; | |
| 2407 } | |
| 2408 | |
| 2409 static Pixel comp_number(Image_tree tree,int size,int p,double f) | |
| 2410 { Pixel sum=0,*list,min,norm,npf,normf; | |
| 2411 int *list_size=0,k; | |
| 2412 | |
| 2413 list_size=(int *)malloc(sizeof(int)); | |
| 2414 if (!list_size) goto error; | |
| 2415 *list_size=0; | |
| 2416 | |
| 2417 list=(Pixel *)calloc(size,sizeof(Pixel)); | |
| 2418 if (!list) goto error; | |
| 2419 recarea(tree,list,list_size); | |
| 2420 abs_list(list,*list_size); | |
| 2421 | |
| 2422 qsort(list,*list_size, sizeof(Pixel), &comp); | |
| 2423 | |
| 2424 norm=sum_list(list,p,size); | |
| 2425 normf=norm*f; | |
| 2426 | |
| 2427 for (k=0;k<size;k++) | |
| 2428 { | |
| 2429 if (list[k]!=0) | |
| 2430 { | |
| 2431 sum+=pow(list[k],p); | |
| 2432 npf=fabs(sum-normf); | |
| 2433 if (npf<min) min=npf; | |
| 2434 } | |
| 2435 } | |
| 2436 min=min/norm; | |
| 2437 | |
| 2438 free(list); | |
| 2439 | |
| 2440 return min; | |
| 2441 | |
| 2442 error: | |
| 2443 err_SimpleMessage(err_GetErrorMessage(Error_NotEnoughMemory)); | |
| 2444 return 0; | |
| 2445 } | |
| 2446 | |
| 2447 static Pixel comp_area(Image_tree tree,int size,int p,double f) | |
| 2448 { Pixel sum=0,*list,norm,vk=0; | |
| 2449 int *list_size=0,k; | |
| 2450 | |
| 2451 list_size=(int *)malloc(sizeof(int)); | |
| 2452 if (!list_size) goto error; | |
| 2453 *list_size=0; | |
| 2454 | |
| 2455 list=(Pixel *)calloc(size,sizeof(Pixel)); | |
| 2456 if (!list) goto error; | |
| 2457 | |
| 2458 recarea(tree,list,list_size); | |
| 2459 abs_list(list,*list_size); | |
| 2460 | |
| 2461 qsort(list,*list_size, sizeof(Pixel), &comp); | |
| 2462 | |
| 2463 norm=sum_list(list,p,size); | |
| 2464 | |
| 2465 for (k=0;k<size;k++) | |
| 2466 { | |
| 2467 if (list[k]!=0) | |
| 2468 { | |
| 2469 vk+=pow(list[k],p); | |
| 2470 sum+=vk; | |
| 2471 | |
| 2472 } | |
| 2473 } | |
| 2474 | |
| 2475 free(list); | |
| 2476 | |
| 2477 return (size-sum/norm); | |
| 2478 | |
| 2479 error: | |
| 2480 err_SimpleMessage(err_GetErrorMessage(Error_NotEnoughMemory)); | |
| 2481 return 0; | |
| 2482 } | |
| 2483 | |
| 2484 static Pixel compute_sdiscrepancy(Image_tree tree,int size) | |
| 2485 { Pixel *list,min,max,factor,maximum=0,x; | |
| 2486 int *list_size=0,k; | |
| 2487 | |
| 2488 list_size=(int *)malloc(sizeof(int)); | |
| 2489 if (!list_size) goto error; | |
| 2490 *list_size=0; | |
| 2491 | |
| 2492 list=(Pixel *)calloc(size,sizeof(Pixel)); | |
| 2493 if (!list) goto error; | |
| 2494 | |
| 2495 recarea(tree,list,list_size); | |
| 2496 | |
| 2497 qsort(list,*list_size, sizeof(Pixel), &comp); | |
| 2498 | |
| 2499 min=list[0]; | |
| 2500 max=list[size-1]; | |
| 2501 factor=1/(max-min); | |
| 2502 | |
| 2503 /*scaling to [0,1]*/ | |
| 2504 for (k=0;k<size;k++) | |
| 2505 { | |
| 2506 list[k]=factor*(list[k]-min); | |
| 2507 } | |
| 2508 | |
| 2509 for (k=0;k<size;k++) | |
| 2510 { | |
| 2511 x=fabs(list[k]-(2*k-1)/(2*size)); | |
| 2512 if (x>maximum) maximum=x; | |
| 2513 } | |
| 2514 | |
| 2515 free(list); | |
| 2516 | |
| 2517 return (1/(2*size)+maximum); | |
| 2518 | |
| 2519 error: | |
| 2520 err_SimpleMessage(err_GetErrorMessage(Error_NotEnoughMemory)); | |
| 2521 return 0; | |
| 2522 } | |
| 2523 | |
| 2524 static Pixel compute_discrepancy(Image_tree tree,int size) | |
| 2525 { Pixel *list,min,max,factor,maximum=0,minimum=0,x; | |
| 2526 int *list_size=0,k; | |
| 2527 | |
| 2528 list_size=(int *)malloc(sizeof(int)); | |
| 2529 if (!list_size) goto error; | |
| 2530 *list_size=0; | |
| 2531 | |
| 2532 list=(Pixel *)calloc(size,sizeof(Pixel)); | |
| 2533 if (!list) goto error; | |
| 2534 | |
| 2535 recarea(tree,list,list_size); | |
| 2536 | |
| 2537 qsort(list,*list_size, sizeof(Pixel), &comp); | |
| 2538 | |
| 2539 min=list[0]; | |
| 2540 max=list[size-1]; | |
| 2541 factor=1/(max-min); | |
| 2542 | |
| 2543 /*scaling to [0,1]*/ | |
| 2544 for (k=0;k<size;k++) | |
| 2545 { | |
| 2546 list[k]=factor*(list[k]-min); | |
| 2547 } | |
| 2548 | |
| 2549 for (k=0;k<size;k++) | |
| 2550 { | |
| 2551 x=((Pixel)k/size-list[k]); | |
| 2552 if (x>maximum) maximum=x; | |
| 2553 else if (x<minimum) minimum=x; | |
| 2554 | |
| 2555 } | |
| 2556 | |
| 2557 free(list); | |
| 2558 | |
| 2559 return (1/size+maximum-minimum); | |
| 2560 | |
| 2561 error: | |
| 2562 err_SimpleMessage(err_GetErrorMessage(Error_NotEnoughMemory)); | |
| 2563 return 0; | |
| 2564 } | |
| 2565 | |
| 2566 static Pixel compute_concentration(Image_tree tree,int size) | |
| 2567 { Pixel *list,min,max,factor,lkm=0,length,sum=0,value,norm; | |
| 2568 int *list_size=0,k,next=0,last=0,i=0; | |
| 2569 | |
| 2570 list_size=(int *)malloc(sizeof(int)); | |
| 2571 if (!list_size) goto error; | |
| 2572 *list_size=0; | |
| 2573 | |
| 2574 list=(Pixel *)calloc(size+1,sizeof(Pixel)); | |
| 2575 if (!list) goto error; | |
| 2576 | |
| 2577 recarea(tree,list,list_size); | |
| 2578 | |
| 2579 qsort(list,*list_size, sizeof(Pixel), &comp); | |
| 2580 | |
| 2581 min=list[0]; | |
| 2582 max=list[size-1]; | |
| 2583 length=(max-min)/100; | |
| 2584 | |
| 2585 factor=1/(max-min); | |
| 2586 for (k=0;k<size;k++) | |
| 2587 { | |
| 2588 list[k]=factor*(list[k]-min); | |
| 2589 } | |
| 2590 | |
| 2591 norm=size*sum_list(list,1,size); | |
| 2592 length=0.01; | |
| 2593 value=length; | |
| 2594 | |
| 2595 list[size]=max+value; | |
| 2596 | |
| 2597 for (k=0;k<100;k++) | |
| 2598 { | |
| 2599 while ((list[i]<value)&(i<size)) | |
| 2600 { | |
| 2601 sum+=list[i]; | |
| 2602 next++; | |
| 2603 i++; | |
| 2604 } | |
| 2605 lkm+=(next-last)*sum/norm; | |
| 2606 value+=length; | |
| 2607 last=next; | |
| 2608 sum=0; | |
| 2609 } | |
| 2610 | |
| 2611 return -lkm; | |
| 2612 | |
| 2613 error: | |
| 2614 err_SimpleMessage(err_GetErrorMessage(Error_NotEnoughMemory)); | |
| 2615 return 0; | |
| 2616 } | |
| 2617 /************************************************************************/ | |
| 2618 /* Functionname: compute_entropy */ | |
| 2619 /* -------------------------------------------------------------------- */ | |
| 2620 /* Parameter: */ | |
| 2621 /* img: Image from which the entropy should be computed */ | |
| 2622 /* cost: choosen costfunction */ | |
| 2623 /* epsilon: limit for threshold method */ | |
| 2624 /* -------------------------------------------------------------------- */ | |
| 2625 /* Description: computes entropy of an image */ | |
| 2626 /************************************************************************/ | |
| 2627 static double compute_entropy(Image img,enum Information_Cost cost,double epsilon) | |
| 2628 { double sum=0,x=0; | |
| 2629 int i; | |
| 2630 Pixel *data; | |
| 2631 | |
| 2632 data=img->data; | |
| 2633 | |
| 2634 switch(cost) { | |
| 2635 | |
| 2636 case threshold: | |
| 2637 for(i=0;i<img->size;i++) | |
| 2638 if (fabs(img->data[i])>epsilon) sum++; | |
| 2639 break; | |
| 2640 | |
| 2641 case log_energy: | |
| 2642 for(i=0;i<img->size;i++,data++) { | |
| 2643 x=(*data) * (*data); | |
| 2644 if (x!=0) sum+=(x*log(1/x)); | |
| 2645 } | |
| 2646 break; | |
| 2647 | |
| 2648 case norml: | |
| 2649 for(i=0;i<img->size;i++,data++) { | |
| 2650 x=fabs(*data); | |
| 2651 sum+=x; | |
| 2652 } | |
| 2653 break; | |
| 2654 | |
| 2655 case norml2: | |
| 2656 for(i=0;i<img->size;i++,data++) { | |
| 2657 x=(*data) * (*data); | |
| 2658 sum+=x; | |
| 2659 } | |
| 2660 sum=pow(sum,0.5); | |
| 2661 break; | |
| 2662 | |
| 2663 case entropy: | |
| 2664 for(i=0;i<img->size;i++,data++) { | |
| 2665 x=(*data)*(*data); | |
| 2666 if (x!=0) sum-=(x*log(x)); | |
| 2667 } | |
| 2668 break; | |
| 2669 | |
| 2670 case gauss_markov: | |
| 2671 for(i=0;i<img->size;i++) { | |
| 2672 x=(img->data[i])*(img->data[i]); | |
| 2673 if (x!=0) sum+=log(x*x); | |
| 2674 } | |
| 2675 break; | |
| 2676 | |
| 2677 } | |
| 2678 | |
| 2679 return sum; | |
| 2680 } | |
| 2681 | |
| 2682 /************************************************************************/ | |
| 2683 /* Functionname: compute_non_additive */ | |
| 2684 /* -------------------------------------------------------------------- */ | |
| 2685 /* Parameter: */ | |
| 2686 /* tree: Image tree from which the entropy should be */ | |
| 2687 /* computed */ | |
| 2688 /* size : size of the image */ | |
| 2689 /* cost: choosen costfunction */ | |
| 2690 /* epsilon: limit for threshold method */ | |
| 2691 /* down: decides if only the first image should be computed*/ | |
| 2692 /* -------------------------------------------------------------------- */ | |
| 2693 /* Description: computes entropy of an image */ | |
| 2694 /************************************************************************/ | |
| 2695 static Pixel compute_non_additive(Image_tree tree,int size,enum Information_Cost cost,double epsilon,int down) | |
| 2696 { Pixel sum=0,normx; | |
| 2697 Image img; | |
| 2698 | |
| 2699 if (down) | |
| 2700 { | |
| 2701 img=tree->image; | |
| 2702 tree->image=NULL; | |
| 2703 } | |
| 2704 switch (cost) | |
| 2705 { | |
| 2706 case shanon: | |
| 2707 normx=normq(tree); | |
| 2708 sum=-sumation_down(tree,normx); | |
| 2709 | |
| 2710 break; | |
| 2711 case weak_l: | |
| 2712 sum=weak_lp(tree,size,1,epsilon); | |
| 2713 break; | |
| 2714 case weak_lq: | |
| 2715 sum=weak_lp(tree,size,2,epsilon); | |
| 2716 break; | |
| 2717 case compression_number: | |
| 2718 sum=comp_number(tree,size,1,epsilon); | |
| 2719 break; | |
| 2720 case compression_numberq: | |
| 2721 sum=comp_number(tree,size,2,epsilon); | |
| 2722 break; | |
| 2723 case compression_area: | |
| 2724 sum=comp_area(tree,size,1,epsilon); | |
| 2725 break; | |
| 2726 case compression_areaq: | |
| 2727 sum=comp_area(tree,size,2,epsilon); | |
| 2728 break; | |
| 2729 case discrepancy: | |
| 2730 sum=compute_discrepancy(tree,size); | |
| 2731 break; | |
| 2732 case sdiscrepancy: | |
| 2733 sum=compute_sdiscrepancy(tree,size); | |
| 2734 break; | |
| 2735 case concentration: | |
| 2736 sum=compute_concentration(tree,size); | |
| 2737 break; | |
| 2738 | |
| 2739 | |
| 2740 } | |
| 2741 | |
| 2742 if (down) tree->image=img; | |
| 2743 | |
| 2744 return sum; | |
| 2745 } | |
| 2746 | |
| 2747 extern int rec_double(Image_tree dtree,int level,FilterGH *flt,enum FilterMethod method,enum Information_Cost cost,double epsilon) | |
| 2748 | |
| 2749 { int min,width,height; | |
| 2750 double sum=0; | |
| 2751 Image c,h,v,d; | |
| 2752 | |
| 2753 dtree->level=0; | |
| 2754 | |
| 2755 if (cost>=shanon) | |
| 2756 { | |
| 2757 dtree->entropy=compute_non_additive(dtree,dtree->image->size,cost,epsilon,0); | |
| 2758 } | |
| 2759 else dtree->entropy=compute_entropy(dtree->image,cost,epsilon); | |
| 2760 | |
| 2761 dtree->doubletree=best_basis(dtree->image,level,flt,method,cost,epsilon); | |
| 2762 | |
| 2763 min=dtree->image->width; | |
| 2764 if (dtree->image->height<min) min=dtree->image->height; | |
| 2765 | |
| 2766 if (doubletree_min<min) | |
| 2767 { | |
| 2768 width=(dtree->image->width+1)/2; | |
| 2769 height=(dtree->image->height+1)/2; | |
| 2770 | |
| 2771 dtree->coarse=new_image_tree(); | |
| 2772 dtree->horizontal=new_image_tree(); | |
| 2773 dtree->vertical=new_image_tree(); | |
| 2774 dtree->diagonal=new_image_tree(); | |
| 2775 | |
| 2776 c=new_image(width,height); | |
| 2777 h=new_image(width,height); | |
| 2778 v=new_image(width,height); | |
| 2779 d=new_image(width,height); | |
| 2780 if(!c||!h||!v||!d) goto error; | |
| 2781 | |
| 2782 | |
| 2783 copy_part_of_image(c,dtree->image,0,0); | |
| 2784 copy_part_of_image(h,dtree->image,width,0); | |
| 2785 copy_part_of_image(v,dtree->image,0,height); | |
| 2786 copy_part_of_image(d,dtree->image,width,height); | |
| 2787 | |
| 2788 dtree->coarse->image=c; | |
| 2789 dtree->horizontal->image=h; | |
| 2790 dtree->vertical->image=v; | |
| 2791 dtree->diagonal->image=d; | |
| 2792 | |
| 2793 rec_double(dtree->coarse,level,flt,method,cost,epsilon); | |
| 2794 rec_double(dtree->horizontal,level,flt,method,cost,epsilon); | |
| 2795 rec_double(dtree->vertical,level,flt,method,cost,epsilon); | |
| 2796 rec_double(dtree->diagonal,level,flt,method,cost,epsilon); | |
| 2797 | |
| 2798 /* going back in recursion*/ | |
| 2799 | |
| 2800 sum=dtree->coarse->entropy+dtree->horizontal->entropy+ | |
| 2801 dtree->vertical->entropy+dtree->diagonal->entropy; | |
| 2802 | |
| 2803 if (sum>dtree->entropy) | |
| 2804 { | |
| 2805 /*take image*/ | |
| 2806 | |
| 2807 free_image_tree(dtree->coarse); | |
| 2808 free_image_tree(dtree->horizontal); | |
| 2809 free_image_tree(dtree->vertical); | |
| 2810 free_image_tree(dtree->diagonal); | |
| 2811 dtree->coarse=dtree->horizontal=dtree->vertical=dtree->diagonal=NULL; | |
| 2812 } | |
| 2813 else | |
| 2814 { /*take tiling*/ | |
| 2815 dtree->entropy=sum; | |
| 2816 free_image(dtree->image); | |
| 2817 dtree->image=NULL; | |
| 2818 } | |
| 2819 | |
| 2820 if (dtree->entropy>dtree->doubletree->entropy) | |
| 2821 { | |
| 2822 /*take best basis tree*/ | |
| 2823 | |
| 2824 dtree->entropy=dtree->doubletree->entropy; | |
| 2825 | |
| 2826 if(dtree->coarse) free_image_tree(dtree->coarse); | |
| 2827 if(dtree->horizontal) free_image_tree(dtree->horizontal); | |
| 2828 if(dtree->vertical) free_image_tree(dtree->vertical); | |
| 2829 if(dtree->diagonal) free_image_tree(dtree->diagonal); | |
| 2830 | |
| 2831 dtree->coarse=dtree->doubletree->coarse; | |
| 2832 dtree->horizontal=dtree->doubletree->horizontal; | |
| 2833 dtree->vertical=dtree->doubletree->vertical; | |
| 2834 dtree->diagonal=dtree->doubletree->diagonal; | |
| 2835 | |
| 2836 free_image(dtree->image); | |
| 2837 dtree->image=NULL; | |
| 2838 free(dtree->doubletree); | |
| 2839 dtree->doubletree=NULL; | |
| 2840 | |
| 2841 } | |
| 2842 else | |
| 2843 { | |
| 2844 dtree->flag=1; | |
| 2845 if(dtree->doubletree) free_image_tree(dtree->doubletree); | |
| 2846 dtree->doubletree=NULL; | |
| 2847 } | |
| 2848 } | |
| 2849 | |
| 2850 return 1; | |
| 2851 | |
| 2852 error: | |
| 2853 err_SimpleMessage(err_GetErrorMessage(Error_NotEnoughMemory)); | |
| 2854 return 0; | |
| 2855 } | |
| 2856 | |
| 2857 static save_structur(Image_tree tree,FILE *fp,int pos) | |
| 2858 { | |
| 2859 int shift,next_pos,max; | |
| 2860 | |
| 2861 if (tree->flag) | |
| 2862 { | |
| 2863 fprintf(fp,"%d ",pos); | |
| 2864 | |
| 2865 shift=pos-(pow(4,tree->level-1)-1)*4/3-1; | |
| 2866 max=(int) ((pow(4,tree->level)-1)*4/3); | |
| 2867 next_pos=max+4*shift+1; | |
| 2868 if (tree->coarse) save_structur(tree->coarse,fp,next_pos); | |
| 2869 if (tree->horizontal) save_structur(tree->horizontal,fp,next_pos+1); | |
| 2870 if (tree->vertical) save_structur(tree->vertical,fp,next_pos+2); | |
| 2871 if (tree->diagonal) save_structur(tree->diagonal,fp,next_pos+3); | |
| 2872 } | |
| 2873 | |
| 2874 } | |
| 2875 | |
| 2876 static int is_in_list(int *list,int len, int x) | |
| 2877 { | |
| 2878 int i,found=0; | |
| 2879 | |
| 2880 for (i=0;i<len;i++) | |
| 2881 { | |
| 2882 if (list[i]==x) | |
| 2883 { | |
| 2884 found=1; | |
| 2885 i=len; | |
| 2886 } | |
| 2887 } | |
| 2888 | |
| 2889 return found; | |
| 2890 } | |
| 2891 | |
| 2892 static write_flags(Image_tree tree,int *list,int len,int pos) | |
| 2893 { | |
| 2894 int shift,next_pos,max; | |
| 2895 | |
| 2896 if (is_in_list(list,len,pos)) | |
| 2897 { | |
| 2898 tree->flag=1; | |
| 2899 | |
| 2900 shift=pos-(pow(4,tree->level-1)-1)*4/3-1; | |
| 2901 max=(int) ((pow(4,tree->level)-1)*4/3); | |
| 2902 next_pos=max+4*shift+1; | |
| 2903 | |
| 2904 write_flags(tree->coarse,list,len,next_pos); | |
| 2905 write_flags(tree->horizontal,list,len,next_pos+1); | |
| 2906 write_flags(tree->vertical,list,len,next_pos+2); | |
| 2907 write_flags(tree->diagonal,list,len,next_pos+3); | |
| 2908 } | |
| 2909 } | |
| 2910 | |
| 2911 static read_structur(Image_tree tree,FILE *fp) | |
| 2912 { | |
| 2913 int e, flags[1000],len=0,i=0; | |
| 2914 | |
| 2915 do | |
| 2916 { | |
| 2917 e=fscanf(fp,"%d ",&flags[i++]); | |
| 2918 if (e!=-1) len++; | |
| 2919 } | |
| 2920 while (e!=-1); | |
| 2921 | |
| 2922 write_flags(tree,flags,len,0); | |
| 2923 | |
| 2924 } | |
| 2925 | |
| 2926 /************************************************************************/ | |
| 2927 /* Functionname: err_simple_message */ | |
| 2928 /* -------------------------------------------------------------------- */ | |
| 2929 /* Parameter: */ | |
| 2930 /* char *: string that contains information about an */ | |
| 2931 /* error the user should know. */ | |
| 2932 /* -------------------------------------------------------------------- */ | |
| 2933 /* Description: */ | |
| 2934 /* Prints error messages for the user. */ | |
| 2935 /************************************************************************/ | |
| 2936 | |
| 2937 void err_SimpleMessage(char *message) | |
| 2938 { | |
| 2939 fprintf(stderr,"%s\n",message); | |
| 2940 } | |
| 2941 | |
| 2942 /************************************************************************/ | |
| 2943 /* Functionname: err_get_message */ | |
| 2944 /* -------------------------------------------------------------------- */ | |
| 2945 /* Return value: Errormessage for this specific error. */ | |
| 2946 /* Parameter: */ | |
| 2947 /* Error err: Error whose errormessage should be returned */ | |
| 2948 /* -------------------------------------------------------------------- */ | |
| 2949 /* Description: */ | |
| 2950 /************************************************************************/ | |
| 2951 char * err_GetErrorMessage(Error err) | |
| 2952 { | |
| 2953 | |
| 2954 switch (err) | |
| 2955 { | |
| 2956 case Error_NotImplemented: | |
| 2957 return "Sorry, this is not implemented yet. "; | |
| 2958 break; | |
| 2959 | |
| 2960 case Error_AssertionFailed: | |
| 2961 return "Sorry, an internal assertion was violated.\n" | |
| 2962 "This action can not be completed. :-("; | |
| 2963 break; | |
| 2964 | |
| 2965 case Error_NotEnoughMemory: | |
| 2966 return "Sorry, there is not enough memory"; | |
| 2967 break; | |
| 2968 | |
| 2969 case Error_Limitation: | |
| 2970 return "Some limitation of the program exceeded"; | |
| 2971 break; | |
| 2972 | |
| 2973 /* - FILES - */ | |
| 2974 | |
| 2975 case Error_CantOpenFile: | |
| 2976 return "Could not open file"; | |
| 2977 break; | |
| 2978 | |
| 2979 case Error_CantCreateFile: | |
| 2980 return "Could not create file"; | |
| 2981 break; | |
| 2982 | |
| 2983 case Error_CantCloseFile: | |
| 2984 return "Could not close file"; | |
| 2985 break; | |
| 2986 | |
| 2987 case Error_InternalError: | |
| 2988 return "Sorry, an internal error occured.\n" | |
| 2989 "This action can not be completed. :-("; | |
| 2990 break; | |
| 2991 | |
| 2992 default: | |
| 2993 return "Sorry, but an unknown error ocurred.\n" | |
| 2994 "This action can not be completed. :-("; | |
| 2995 break; | |
| 2996 | |
| 2997 | |
| 2998 } | |
| 2999 } |
