comparison Meerwald-dir/wavelet.c @ 24:9f20bce6184e v0.7

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

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