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 }

Repositories maintained by Peter Meerwald, pmeerw@pmeerw.net.