changeset 0:be303a3f5ea8

import
author Peter Meerwald <pmeerw@cosy.sbg.ac.at>
date Sun, 12 Aug 2007 13:14:34 +0200 (2007-08-12)
parents
children 647ab0f05aae
files .hgignore ANNOUNCEMENT Fotopoulos/CHANGES Fotopoulos/Makefile Fotopoulos/README Fotopoulos/README_VASSILIS Fotopoulos/cast-hart.c Fotopoulos/cast-pv.c Fotopoulos/cast-sub.c Fotopoulos/common.c Fotopoulos/common.h Fotopoulos/test-hart.c Fotopoulos/test-pv.c Fotopoulos/test-sub.c Makefile Meerwald/Makefile Meerwald/README Meerwald/bruyn_common.c Meerwald/bruyn_common.h Meerwald/cmp_bruyn_sig.c Meerwald/cmp_corvi_sig.c Meerwald/cmp_cox_sig.c Meerwald/cmp_dct.1 Meerwald/cmp_dct.c Meerwald/cmp_dct8x8.1 Meerwald/cmp_dct8x8.c Meerwald/cmp_dugad_sig.c Meerwald/cmp_dwt.c Meerwald/cmp_frid2_sig.c Meerwald/cmp_kim_sig.c Meerwald/cmp_koch_sig.c Meerwald/cmp_pgm.1 Meerwald/cmp_pgm.c Meerwald/cmp_ppm.1 Meerwald/cmp_wang_sig.c Meerwald/cmp_xia_sig.c Meerwald/cmp_xie_sig.c Meerwald/cmp_zhu_sig.c Meerwald/coeff.c Meerwald/coeff.h Meerwald/coord.c Meerwald/coord.h Meerwald/dct.c Meerwald/dct.h Meerwald/dwt.c Meerwald/dwt.h Meerwald/dwt_util.c Meerwald/dwt_util.h Meerwald/filter.dat Meerwald/frid2_common.c Meerwald/frid2_common.h Meerwald/gen_bruyn_sig.1 Meerwald/gen_bruyn_sig.c Meerwald/gen_corvi_sig.1 Meerwald/gen_corvi_sig.c Meerwald/gen_cox_sig.1 Meerwald/gen_cox_sig.c Meerwald/gen_dugad_sig.c Meerwald/gen_frid2_sig.c Meerwald/gen_kim_sig.c Meerwald/gen_koch_sig.1 Meerwald/gen_koch_sig.c Meerwald/gen_kutter_sig.1 Meerwald/gen_wang_sig.c Meerwald/gen_xia_sig.c Meerwald/gen_xie_sig.c Meerwald/gen_zhu_sig.c Meerwald/gray.c Meerwald/gray.h Meerwald/kim.wm Meerwald/kim_common.c Meerwald/kim_common.h Meerwald/signature.c Meerwald/signature.h Meerwald/sort.c Meerwald/sort.h Meerwald/wang_common.c Meerwald/wang_common.h Meerwald/wavelet.c Meerwald/wavelet.h Meerwald/wm.c Meerwald/wm.h Meerwald/wm_bruyn_d.c Meerwald/wm_bruyn_e.c Meerwald/wm_corvi_d.1 Meerwald/wm_corvi_d.c Meerwald/wm_corvi_e.1 Meerwald/wm_corvi_e.c Meerwald/wm_corvi_s.1 Meerwald/wm_corvi_s.c Meerwald/wm_cox_d.1 Meerwald/wm_cox_d.c Meerwald/wm_cox_e.1 Meerwald/wm_cox_e.c Meerwald/wm_dugad_d.c Meerwald/wm_dugad_e.c Meerwald/wm_frid2_d.c Meerwald/wm_frid2_e.c Meerwald/wm_kim_a.c Meerwald/wm_kim_d.c Meerwald/wm_kim_e.c Meerwald/wm_koch_d.1 Meerwald/wm_koch_d.c Meerwald/wm_koch_e.1 Meerwald/wm_koch_e.c Meerwald/wm_wang_d.c Meerwald/wm_wang_e.c Meerwald/wm_xia_d.c Meerwald/wm_xia_e.c Meerwald/wm_xie_d.c Meerwald/wm_xie_e.c Meerwald/wm_zhu_d.c Meerwald/wm_zhu_e.c README images/lena.pgm make/make.emx make/make.linux make/make.mingw manual.lyx
diffstat 119 files changed, 25189 insertions(+), 0 deletions(-) [+]
line wrap: on
line diff
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/.hgignore	Sun Aug 12 13:14:34 2007 +0200
@@ -0,0 +1,9 @@
+syntax: glob
+*.orig
+*.rej
+*~
+*.o
+.dummy
+
+syntax: regexp
+.*\#.*\#$
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/ANNOUNCEMENT	Sun Aug 12 13:14:34 2007 +0200
@@ -0,0 +1,132 @@
+Watermarking source
+
+version 0.4
+
+
+This package provides source code for some watermarking algorithms in
+portable C code. Currently it includes the following
+
+  watermarking algorithms
+
+    Bruyndonckx [bruyn]
+      refer to
+        O. Bruyndonckx, Jean-Jacques Quisquater, and Benoit M. Macq.
+        Spatial method for copyright labeling of digital images.
+        In IEEE Workshop on Nonlinear Signal and Image Processing '95,
+        Thessaloniki, Greece, pages 456 - 459, 1995.
+
+    Corvi
+      refer to
+        Marco Corvi and Gianluca Nicchiotti.
+        Wavelet-based image watermarking for copyright protection.
+        In Scandinavian Conference on Image Analysis SCIA '97, Lappeenranta,
+        Finland, June 1997.
+
+    Cox
+      refer to
+        Ingemar J. Cox, Joe Kilian, Tom Leighton, and Talal G. Shamoon.
+        Secure spread spectrum watermarking for multimedia.
+        In Proceedings of the IEEE ICIP '97,
+        volume 6, pages 1673 - 1687, Santa Barbara, California, USA, 1997.
+
+    Dugad
+      refer to
+        Rakesh Dugad, Krishna Ratakonda, and Narendra Ahuja. 
+        A new wavelet-based scheme for watermarking images. In Proceedings of 
+        the IEEE International Conference on Image Processing, ICIP '98, 
+        Chicago, IL, USA, October 1998. 
+
+    Fridrich (2. scheme)
+      refer to
+        Jiri Fridrich.
+        Combining low-frequency and spread spectrum watermarking. In Proceedings of 
+        the SPIE Symposium on Optical Science, Engineering and Instrumentation, 
+        San Diego, USA, July 1998. 
+
+    Koch
+      refer to
+        Eckhard Koch and Jian Zhao.
+        Towards robust and hidden image copyright labeling.
+        In Proceedings of the IEEE International Workshop on Nonlinear
+        Signal and Image Processing, pages 452 - 455, Halkidiki, Marmaras,
+        Greece, June 1995.
+
+    Kim
+      refer to
+        Jong Ryul Kim and Young Shik Moon.
+        A robust wavelet-based digital watermark using level-adaptive
+        thresholding. In Proceedings of the 6th IEEE International
+        Conference on Image Processing ICIP '99, page 202,
+        Kobe, Japan, October 1999.
+
+    Wang
+      refer to
+        Houng-Jyh Wang, Po-Chyi Su, and C.-C. Jay Kuo. 
+        Wavelet-based digital image watermarking. Optics Express, 3 
+        pp. 497, December 1998. 
+
+    Xia
+      refer to
+        Xiang-Gen Xia, Charles G. Boncelet, and Gonzalo R. Arce.
+        Wavelet transform based watermark for digital images. Optics Express, 3
+        pp. 497, December 1998.
+
+    Xie
+      refer to
+        Liehua Xie and Gonzalo R. Arce.
+        Joint wavelet compression and authentication watermarking. In 
+        Proceedings of the IEEE International Conference on Image Processing,   
+        ICIP '98, Chicago, IL, USA, 1998.
+
+    Zhu
+      refer to
+       Wenwu Zhu, Zixiang Xiong, and Ya-Qin Zhang. 
+       Multiresolution watermarking for images and video: a unified approach. 
+       In Proceedings of the IEEE International Conference on Image Processing, 
+       ICIP '98, Chicago, IL, USA, October 1998. 
+
+   Piva/Fotopoulos [cast|test-pv,hart,sub]
+     contribution by Vassilis Fotopoulos
+     refer to
+
+        M.Barni, F. Bartolini, V. Cappellini, A. Piva. A DCT-Domain
+        System for Robust Image Watermarking,
+        Signal Processing, vol. 66, pp 357 - 372, 1998.
+
+        V. Fotopoulos, A. N. Skodras, A Subband DCT approach to
+        image watermarking, X European Signal Processing Conference,
+        September 4 - 8, 2000, Tampere, Finland
+
+    many more algorithms to come!
+    see what is in stock: http://www.cosy.sbg.ac.at/~pmeerw/Watermarking
+
+  and utility programs
+
+    cmp_pgm     - compute difference image, PSNR, ...
+    cmp_dct     - compute full-frame DCT domain difference image
+    cmp_dct8x8  - compute 8x8 block-based DCT difference image
+    cmp_dwt     - compute DWT domain difference image
+
+
+
+Contact: Comments are welcome!
+
+More algorithms will be added over time, I have implemented about 13
+watermarking algorithms in the spatial-, DCT-, and wavelet domain so far.
+
+Please report what problems you have, suggestions, ...
+
+Peter Meerwald
+
+Dept. of Scientific Computing
+University of Salzburg
+Jakob-Haringer-Str. 2
+A-5020 Salzburg
+AUSTRIA
+
+pmeerw@cosy.sbg.ac.at
+http://www.cosy.sbg.ac.at/~pmeerw/Watermarking
+
++43-662-8044-6327
+
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Fotopoulos/CHANGES	Sun Aug 12 13:14:34 2007 +0200
@@ -0,0 +1,2 @@
+removed #include <values.h> - it is not needed and MS VC++ does not have 
+it (Sarat Atluri)
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Fotopoulos/Makefile	Sun Aug 12 13:14:34 2007 +0200
@@ -0,0 +1,44 @@
+# Makefile
+
+include ../make/make.config
+
+all: cast-pv$(EXE) cast-hart$(EXE) cast-sub$(EXE) test-pv$(EXE) test-hart$(EXE) test-sub$(EXE)
+
+.SUFFIXES: .c .o
+
+.c$(O):
+	$(CC) $(CFLAGS) $(INCLUDES) -o $@ -c $<
+
+cast-pv$(EXE):  cast-pv$(O) common$(O)
+	$(CC) $(LDFLAGS) -o $@ cast-pv$(O) common$(O) $(PGMLIBS)
+
+cast-hart$(EXE):  cast-hart$(O) common$(O)
+	$(CC) $(LDFLAGS) -o $@ cast-hart$(O) common$(O) $(PGMLIBS)
+
+cast-sub$(EXE):  cast-sub$(O) common$(O)
+	$(CC) $(LDFLAGS) -o $@ cast-sub$(O) common$(O) $(PGMLIBS)
+
+test-pv$(EXE):  test-pv$(O) common$(O)
+	$(CC) $(LDFLAGS) -o $@ test-pv$(O) common$(O) $(PGMLIBS)
+
+test-hart$(EXE):  test-hart$(O) common$(O)
+	$(CC) $(LDFLAGS) -o $@ test-hart$(O) common$(O) $(PGMLIBS)
+
+test-sub$(EXE):  test-sub$(O) common$(O)
+	$(CC) $(LDFLAGS) -o $@ test-sub$(O) common$(O) $(PGMLIBS)
+
+test: cast-pv$(EXE) cast-hart$(EXE) cast-sub$(EXE) test-pv$(EXE) test-hart$(EXE) test-sub$(EXE)
+	cast-pv < ../images/lena.pgm > ../watermarked/foto-pv_lena.pgm
+	cast-hart  < ../images/lena.pgm > ../watermarked/foto-hart_lena.pgm
+	cast-sub  < ../images/lena.pgm > ../watermarked/foto-sub_lena.pgm
+
+	test-pv < ../watermarked/foto-pv_lena.pgm > ../wms/foto-pv.wm
+	test-hart < ../watermarked/foto-hart_lena.pgm > ../wms/foto-hart.wm
+	test-sub < ../watermarked/foto-sub_lena.pgm > ../wms/foto-sub.wm
+
+install: cast-pv$(EXE) cast-hart$(EXE) cast-sub$(EXE) test-pv$(EXE) test-hart$(EXE) test-sub$(EXE)
+	$(CP) cast-pv$(EXE) cast-hart$(EXE) cast-sub$(EXE) test-pv$(EXE) test-hart$(EXE) test-sub$(EXE) $(INSTALLDIR)
+
+clean:
+	$(RM) *$(O) cast-pv$(EXE) cast-hart$(EXE) cast-sub$(EXE) test-pv$(EXE) test-hart$(EXE) test-sub$(EXE)
+	$(RM) ../watermarked/* ../wms/*
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Fotopoulos/README	Sun Aug 12 13:14:34 2007 +0200
@@ -0,0 +1,21 @@
+M.Barni, F. Bartolini, V. Cappellini, A. Piva. "A DCT-Domain
+System for Robust Image Watermarking",
+Signal Processing, vol.66, pp 357-372, 1998.
+
+V. Fotopoulos, A.N. Skodras, "A Subband DCT approach to
+image watermarking", X European Signal Processing Conference,
+September 4-8, 2000, Tampere, Finland
+
+parameters:
+for starting coefficient reasonable values for the dct and hartley schemes
+and this kind of dimensions is around 5000-20000, for the watermark length 10000-50000,
+and seed/key should be in the range 1-1000 so that the output file of the testing module
+gives a right similarity diagram
+
+for the subband dct version, things change corresponding to coefficients
+because the bands' sizes are 1/4 of the original image's size.
+starting coef should be between 3000-5000 and length 10000-20000
+for the alpha parameter i use 0.2 for all bands except LL for which i use
+0.1
+
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Fotopoulos/README_VASSILIS	Sun Aug 12 13:14:34 2007 +0200
@@ -0,0 +1,67 @@
+These codes use the DCT,Hartley and Subband DCT
+Transforms for watermarking purposes.All schemes
+are blind,no original image is used for detection.
+Each casting module is accompanied by a testing 
+module.Supposing that the watermark key that you
+select during casting is in the range 1-1000,the
+testing module will test all the keys in this range
+to produce the well known similarity diagrams used
+by Cox, Piva and many more with the peak being the
+proof of the watermark existence.
+
+I do not include a detection module because this implies
+the use of certain thresholds. Although the casting
+methods are almost standardized (multiplicative formula)
+there are still questions about this thresholding but
+the testing modules can be easily changed to fit this
+purpose.
+
+The DCT scheme does not use the visual masking improvement
+that Barni and his team suggest in one of their later works.
+In all casting programs we assume that the coefficients are
+diagonaly scanned,and ordered as shown in the following example.
+
+----------------------
+| 1| 3| 6|10|15|...
+----------------------
+| 2| 5| 9|14|...
+----------------------
+| 4| 8|13|...
+----------------------
+| 7|12|...
+----------------------
+|11|...
+----------------------
+
+which is quite simple comparing to the zig zag scanning 
+pattern that we know from the JPEG standard but does not
+affect at all the idea that we have of the middle 
+frequencies.Also the user should take care that
+
+starting_coefficient+number_of_coeffs_to_change<(N*N)/2
+
+which means that we shouldn't exceed the matrix diagonal.
+To do so the scanning scheme should be changed accordingly
+but this doesn't seem important because in all of the
+schemes we don't get out of the middle frequencies coefs.
+With correctly selected parameters,the schemes perform in
+the same way as if the coeffs were zig zag scanned.
+
+In the Subband DCT version,the first set of questions
+about starting coefficient,number of coefficients to
+alter and alpha parameter, refer to the LH,HL and HH
+band while the second set of questions sets the parameters
+about the LL band only.
+
+All schemes should not be used with the same set of parameters
+because each of the transforms, possess certain specific
+properties. This should be kept in mind for testing purposes.
+To use the right set of parameters please refer to corresponding
+bibliography.
+All code has been tested in Visual C++ v6.0
+
+Have some nice tests...
+Vassilis Fotopoulos
+
+for more info,ideas or points of discussion
+email vfotop1@physics.upatras.gr
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Fotopoulos/cast-hart.c	Sun Aug 12 13:14:34 2007 +0200
@@ -0,0 +1,112 @@
+/* Watermarking program - Hartley Transform based	*/
+/* Module	: Casting				*/
+/* Author	: Vassilis Fotopoulos			*/
+/* Date		: 26/7/1999				*/
+/* Revision	: 2.01a					*/
+/* Developed at	: ELLAB                  		*/
+/*                Electronics Laboratory           	*/
+/*                Department of Physics             	*/
+/*                University of Patras - GREECE      	*/
+/*		  Copyleft (c) 1999			*/
+/*------------------------------------------------------*/
+/*	pseudorandom noise generator's code is		*/
+/*	taken from "Numerical Recipes in C"		*/
+/*------------------------------------------------------*/
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <math.h>
+#include <float.h>
+#include <getopt.h>
+#include "common.h"
+
+int height, width;
+
+void add_watermark(double **in, int N, int coeff_start, int wm_length, int wm_key, double wm_alpha)
+{
+  int row, col, count;
+  long int elem, L, M, temp, seed;
+  double a;
+  count = 0;
+  elem = 0;
+  M = coeff_start;
+  L = wm_length;
+  seed = wm_key;
+  a = wm_alpha;
+  for (row = 0; row < N; row++)
+    for (col = 0; col < N; col++) {
+      elem++;
+      if (elem > M && count < L) {
+        in[row][col] += a * fabs(in[row][col]) * gasdev(&seed);
+        count++;
+      }
+    }
+
+}
+
+//--------------------------------------------------------
+int main(int argc, char* argv[])
+{
+  FILE *in, *out;
+  int **image;
+  double **image_i;
+  double **image_d;
+  int c;
+  int N;
+  int coeff_start = 5000, wm_length = 10000, wm_key = 123;
+  double wm_alpha = 0.2;
+
+  pgm_init(&argc, argv); wm_init();
+
+  while ((c = getopt(argc, argv, "a:s:l:k:")) != EOF) {
+    switch (c) {
+        case 'a':
+        wm_alpha = atof(optarg);
+        break;
+        case 's':
+        coeff_start = atoi(optarg);
+        break;
+        case 'l':
+        wm_length = atoi(optarg);
+        break;
+        case 'k':
+        wm_key = atoi(optarg);
+        break;
+    }
+  }
+  argc -= optind;
+  argv += optind;
+
+  in = stdin;
+  out = stdout;
+
+  open_image(in, &width, &height);
+  image = imatrix(height, width);
+  load_image(image, in, width, height);
+
+  if (height == width)
+    N = height;
+  else {
+    fprintf(stderr, "Cannot Proccess non-square images!\n");
+    exit( -11);
+  }
+
+  image_i = dmatrix(height, width);
+  image_d = dmatrix(height, width);
+  if (image_d == NULL) {
+    fprintf(stderr, "Unable to allocate the double array\n");
+    exit(1);
+  }
+  matrix_i2d(image, image_i, N);
+  hartley(image_i, image_d, N);
+  add_watermark(image_d, N, coeff_start, wm_length, wm_key, wm_alpha);
+  hartley(image_d, image_i, N);
+  matrix_d2i(image_i, image, N);
+  save_image(image, out, width, height);
+
+  freematrix_d(image_i, height);
+  freematrix_d(image_d, height);
+  fclose(in);
+  fclose(out);
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Fotopoulos/cast-pv.c	Sun Aug 12 13:14:34 2007 +0200
@@ -0,0 +1,132 @@
+/* Watermarking program - Fast Cosine Transform based	*/
+/* Module	: Casting				*/
+/* Author	: Vassilis Fotopoulos			*/
+/* Date		: 21/7/1999				*/
+/* Revision	: 2.01a					*/
+/* Developed at	: ELLAB                  		*/
+/*                Electronics Laboratory           	*/
+/*                Department of Physics             	*/
+/*                University of Patras - GREECE      	*/
+/*		  Copyleft (c) 1999	    		*/
+/*  		  (without Visual Masking)              */
+/*------------------------------------------------------*/
+/*	pseudorandom noise generator's code is		*/
+/*	taken from "Numerical Recipes in C"		*/
+/*	FCT implementation from the University of Bath	*/
+/*------------------------------------------------------*/
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <math.h>
+#include <float.h>
+#include <getopt.h>
+#include "common.h"
+
+double cu[1024];
+double cv[1024];
+int height, width;
+
+//--------------------------------------------------------
+void add_watermark(double *in, int N, int coeff_start, int wm_length, int wm_key, double wm_alpha)
+{
+  int row, col, count;
+  long int elem, L, M, temp, seed;
+  double a;
+  count = 0;
+  elem = 0;
+  row = 2;
+  col = -1;
+  M = coeff_start;
+  L = wm_length;
+  seed = wm_key;
+  a = wm_alpha;
+  do {
+    do {
+      row--;
+      col++;
+      elem++;
+      if (col < N) {
+        if (elem > M) {
+          temp = row * N + col;
+          in[temp] += a * fabs(in[temp]) * gasdev(&seed);
+          count++;
+        }
+      }
+    } while (row > 0);
+    row = 2 + col;
+    col = -1;
+  } while (count < L);
+}
+//--------------------------------------------------------
+void initialize_constants(void)
+{
+  int i;
+  cu[0] = cv[0] = 0.7071068;
+  for (i = 1; i < 1024; i++)
+    cu[i] = cv[i] = 1.0;
+}
+
+//--------------------------------------------------------
+int main(int argc, char* argv[])
+{
+  FILE *in, *out;
+  int **image_i;
+  double *image_f = NULL;
+  int N;
+  int c;
+  int coeff_start = 5000, wm_length = 10000, wm_key = 123;
+  double wm_alpha = 0.2;
+
+  pgm_init(&argc, argv); wm_init();
+
+  while ((c = getopt(argc, argv, "a:s:l:k:")) != EOF) {
+    switch (c) {
+        case 'a':
+        wm_alpha = atof(optarg);
+        break;
+        case 's':
+        coeff_start = atoi(optarg);
+        break;
+        case 'l':
+        wm_length = atoi(optarg);
+        break;
+        case 'k':
+        wm_key = atoi(optarg);
+        break;
+    }
+  }
+  argc -= optind;
+  argv += optind;
+
+  in = stdin;
+  out = stdout;
+
+  open_image(in, &width, &height);
+  image_i = imatrix(height, width);
+  load_image(image_i, in, width, height);
+
+  if (height == width)
+    N = height;
+  else {
+    fprintf(stderr, "Cannot Proccess non-square images!\n");
+    exit( -11);
+  }
+
+  initialize_constants();
+  image_f = (double *)calloc(N * N, sizeof(double));
+  if (image_f == NULL) {
+    printf("Unable to allocate the float array\n");
+    exit(1);
+  }
+
+  put_image_from_int_2_double(image_i, image_f, N);
+  fct2d(image_f, N, N);
+  add_watermark(image_f, N, coeff_start, wm_length, wm_key, wm_alpha);
+  ifct2d(image_f, N, N);
+  put_image_from_double_2_int(image_f, image_i, N);
+  save_image(image_i, out, width, height);
+  freematrix(image_i, height);
+  free(image_f);
+  fclose(in);
+  fclose(out);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Fotopoulos/cast-sub.c	Sun Aug 12 13:14:34 2007 +0200
@@ -0,0 +1,247 @@
+/* Watermarking program - Subband DCT Transform based	*/
+/* Module	: Casting				*/
+/* Author	: Vassilis Fotopoulos			*/
+/* Date		: 25/4/2000				*/
+/* Revision	: 7.0					*/
+/* Developed at	: ELLAB                  		*/
+/*                Electronics Laboratory           	*/
+/*                Department of Physics             	*/
+/*                University of Patras - GREECE      	*/
+/*		  Copyleft (c) 1999	    		*/
+/*------------------------------------------------------*/
+/*	pseudorandom noise generator's code is		*/
+/*	taken from "Numerical Recipes in C"		*/
+/*	FCT implementation from University of Bath	*/
+/*------------------------------------------------------*/
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <math.h>
+#include <float.h>
+#include <getopt.h>
+#include "common.h"
+
+void add_hor_add_ver(double **in, int N, double **out);
+void add_hor_sub_ver(double **in, int N, double **out);
+void sub_hor_add_ver(double **in, int N, double **out);
+void sub_hor_sub_ver(double **in, int N, double **out);
+void band_synthesis(double **ll, double **lh, double **hl, double **hh, int N, double **s);
+void watermark(double **i, int N, long key, long int L, long int M, double a);
+
+double cu[1024];
+double cv[1024];
+int height, width;
+
+//--------------------------------------------------------
+void add_hor_add_ver(double **in, int N, double **out)
+{
+  double **temp;
+  int r, c;
+  temp = dmatrix(N, N);
+  for (r = 0; r < N; r++)
+    for (c = 0; c < N / 2; c++)
+      temp[r][c] = (in[r][2 * c] + in[r][2 * c + 1]) / 2;
+  for (c = 0; c < N / 2; c++)
+    for (r = 0; r < N / 2; r++)
+      out[r][c] = (temp[2 * r][c] + temp[2 * r + 1][c]) / 2;
+  freematrix_d(temp, N);
+}
+//--------------------------------------------------------
+void add_hor_sub_ver(double **in, int N, double **out)
+{
+  double **temp;
+  int r, c;
+  temp = dmatrix(N, N);
+  for (r = 0; r < N; r++)
+    for (c = 0; c < N / 2; c++)
+      temp[r][c] = (in[r][2 * c] + in[r][2 * c + 1]) / 2;
+  for (c = 0; c < N / 2; c++)
+    for (r = 0; r < N / 2; r++)
+      out[r][c] = (temp[2 * r][c] - temp[2 * r + 1][c]) / 2;
+  freematrix_d(temp, N);
+}
+//--------------------------------------------------------
+void sub_hor_add_ver(double **in, int N, double **out)
+{
+  double **temp;
+  int r, c;
+  temp = dmatrix(N, N);
+  for (r = 0; r < N; r++)
+    for (c = 0; c < N / 2; c++)
+      temp[r][c] = (in[r][2 * c] - in[r][2 * c + 1]) / 2;
+  for (c = 0; c < N / 2; c++)
+    for (r = 0; r < N / 2; r++)
+      out[r][c] = (temp[2 * r][c] + temp[2 * r + 1][c]) / 2;
+  freematrix_d(temp, N);
+}
+//--------------------------------------------------------
+void sub_hor_sub_ver(double **in, int N, double **out)
+{
+  double **temp;
+  int r, c;
+  temp = dmatrix(N, N);
+  for (r = 0; r < N; r++)
+    for (c = 0; c < N / 2; c++)
+      temp[r][c] = (in[r][2 * c] - in[r][2 * c + 1]) / 2;
+  for (c = 0; c < N / 2; c++)
+    for (r = 0; r < N / 2; r++)
+      out[r][c] = (temp[2 * r][c] - temp[2 * r + 1][c]) / 2;
+  freematrix_d(temp, N);
+}
+//--------------------------------------------------------
+void band_synthesis(double **ll, double **lh, double **hl, double **hh, int N, double **s)
+{
+  int r, c;
+  double b1, b2, b3, b4;
+  for (r = 0; r < N; r++)
+    for (c = 0; c < N; c++) {
+      b1 = ll[r][c] + lh[r][c] + hl[r][c] + hh[r][c]; 	//Reconstruct each
+      b2 = ll[r][c] + lh[r][c] - hl[r][c] - hh[r][c]; 	//of the pixels
+      b3 = ll[r][c] - lh[r][c] + hl[r][c] - hh[r][c];
+      b4 = ll[r][c] - lh[r][c] - hl[r][c] + hh[r][c];
+      b1 = (b1 > 255.0) ? 255.0 : b1; 					//Check for positive...
+      b1 = (b1 < 0.0) ? 0.0 : b1; 						//or negative core!
+      b2 = (b2 > 255.0) ? 255.0 : b2;
+      b2 = (b2 < 0.0) ? 0.0 : b2;
+      b3 = (b3 > 255.0) ? 255.0 : b3;
+      b3 = (b3 < 0.0) ? 0.0 : b3;
+      b4 = (b4 > 255.0) ? 255.0 : b4;
+      b4 = (b4 < 0.0) ? 0.0 : b4;
+      s[2*r][2*c] = b1; 							//Put them back in
+      s[2*r][2*c + 1] = b2; 						//the right position
+      s[2*r + 1][2*c] = b3;
+      s[2*r + 1][2*c + 1] = b4;
+    }
+}
+
+void watermark(double **i, int N, long key, long int L, long int M, double a)
+{
+  int row, col, count;
+  long int elem, temp, seed;
+  double *v;
+  v = dvector(N * N);
+  put_matrix_2_vector(i, v, N);
+  fct2d(v, N, N);
+  seed = key;
+  count = 0;
+  elem = 0;
+  row = 2;
+  col = -1;
+  do {
+    do {
+      row--;
+      col++;
+      elem++;
+      if (col < N) {
+        if (elem > M) {
+          temp = row * N + col;
+          v[temp] += a * fabs(v[temp]) * gasdev(&seed);
+          count++;
+        }
+      }
+    } while (row > 0);
+    row = 2 + col;
+    col = -1;
+  } while (count < L);
+  ifct2d(v, N, N);
+  put_vector_2_matrix(v, i, N);
+  free(v);
+}
+
+int main(int argc, char* argv[])
+{
+  double **i;
+  double **o;
+  FILE *in;
+  FILE *out;
+  int N;
+  int c;
+  long int M1, L1, M2, L2;
+  int **image_i;
+  double **ll, **lh, **hl, **hh;
+  double a_ll = 0.1, a_other = 0.2;
+  int wm_length_1 = 10000, wm_length_ll = 10000, coeff_start_1 = 3000,
+                                          coeff_start_ll = 3000, wm_key = 123;
+
+  pgm_init(&argc, argv); wm_init();
+
+  while ((c = getopt(argc, argv, "a:b:t:m:s:l:k:")) != EOF) {
+    switch (c) {
+        case 'a':
+        a_ll = atof(optarg);
+        break;
+        case 'b':
+        a_other = atof(optarg);
+        break;
+        case 't':
+        coeff_start_1 = atoi(optarg);
+        break;
+        case 'm':
+        wm_length_1 = atoi(optarg);
+        break;
+        case 's':
+        coeff_start_ll = atoi(optarg);
+        break;
+        case 'l':
+        wm_length_ll = atoi(optarg);
+        break;
+        case 'k':
+        wm_key = atoi(optarg);
+        break;
+    }
+  }
+  argc -= optind;
+  argv += optind;
+
+  in = stdin;
+  out = stdout;
+  open_image(in, &width, &height);
+  image_i = imatrix(height, width);
+  load_image(image_i, in, width, height);
+  if (height == width)
+    N = height;
+  else {
+    fprintf(stderr, "Cannot Proccess non-square images!\n");
+    exit( -11);
+  }
+  // starting coeff. for 1st level decomp.
+  M1 = coeff_start_1;
+  // number of coeffs to alter
+  L1 = wm_length_1;
+
+  // now the LL band
+  M2 = coeff_start_ll;
+  L2 = wm_length_ll;
+
+  i = dmatrix(N, N);
+  o = dmatrix(N, N);
+  ll = dmatrix(N / 2, N / 2);
+  lh = dmatrix(N / 2, N / 2);
+  hl = dmatrix(N / 2, N / 2);
+  hh = dmatrix(N / 2, N / 2);
+
+  matrix_i2d(image_i, i, N);
+
+  //---------------------1o decomposition-------------------
+  add_hor_add_ver(i, N, ll);
+  add_hor_sub_ver(i, N, lh);
+  sub_hor_add_ver(i, N, hl);
+  sub_hor_sub_ver(i, N, hh);
+  //---------------------Watermark medium frequency bands---
+  watermark(lh, N / 2, wm_key, L1, M1, a_other);
+  watermark(hl, N / 2, wm_key, L1, M1, a_other);
+  watermark(hh, N / 2, wm_key, L1, M1, a_other);
+  watermark(ll, N / 2, wm_key, L2, M2, a_ll);
+  //---------------------Synthesis stage--------------------
+  band_synthesis(ll, lh, hl, hh, N / 2, o);
+  //--------------------------------------------------------
+  matrix_d2i(o, image_i, N);
+  save_image(image_i, out, width, height);
+
+  fclose(in);
+  fclose(out);
+}
+
+
+
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Fotopoulos/common.c	Sun Aug 12 13:14:34 2007 +0200
@@ -0,0 +1,571 @@
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <math.h>
+#include <float.h>
+#include "pgm.h"
+#include "common.h"
+
+#define IA      16807
+#define IM      2147483647
+#define AM      (1.0/IM)
+#define IQ      127773
+#define IR      2836
+#define MASK    123459876
+
+static int NN = 0;
+static int m = 0;
+static double two_over_N = 0;
+static double root2_over_rootN = 0;
+static double *C = NULL;
+
+static gray maxval;
+static int format;
+
+void open_image(FILE *in, int *width, int *height)
+{
+
+  pgm_readpgminit(in, width, height, &maxval, &format);
+}
+
+void load_image(int **im, FILE *in, int width, int height)
+{
+  int col, row;
+  gray *rowbuf;
+
+  rowbuf = malloc(sizeof(gray) * width);
+
+  for (row = 0; row < height; row++) {
+    pgm_readpgmrow(in, rowbuf, width, maxval, format);
+    for (col = 0; col < width; col++)
+      im[row][col] = rowbuf[col];
+  }
+
+  free(rowbuf);
+}
+
+void save_image(int **im, FILE *out, int width, int height)
+{
+  int col, row;
+  gray *rowbuf;
+
+  pgm_writepgminit(out, width, height, 255, 0);
+
+  rowbuf = malloc(sizeof(gray) * width);
+
+  for (row = 0; row < height; row++) {
+    for (col = 0; col < width; col++)
+      rowbuf[col] = im[row][col];
+    pgm_writepgmrow(out, rowbuf, width, 255, 0);
+  }
+
+  free(rowbuf);
+}
+
+int ** imatrix(int nrows, int ncols)
+{
+  int **m;
+  int i, j;
+  m = (int **) malloc (nrows * sizeof(int *));
+  for (i = 0; i < nrows; i++) {
+    m[i] = (int *) malloc (ncols * sizeof(int));
+    if (!m[i]) fprintf(stderr, "\nIt's not working");
+  }
+  for (i = 0; i < nrows; i++)
+    for (j = 0; j < ncols; j++)
+      m[i][j] = 0;
+  return m;
+}
+
+void freematrix(int **I, int rows)
+{
+  int k;
+  for (k = 0; k < rows; k++)
+    free (I[k]);
+}
+
+float ran0(long int *idum)
+{
+  long int k;
+  float ans;
+  *idum ^= MASK;
+  k = (*idum) / IQ;
+  *idum = IA * (*idum - k * IQ) - IR * k;
+  if (*idum < 0) *idum += IM;
+  ans = AM * (*idum);
+  *idum ^= MASK;
+  return ans;
+}
+
+float gasdev(long int *idum)
+{
+
+  float v1;
+  v1 = (float) sqrt( -2.0 * log(ran0(idum))) * cos(2 * PI * ran0(idum));
+  return v1;
+}
+
+
+void put_image_from_int_2_double(int **i, double *f, int N)
+{
+  int l, j, k;
+  k = 0;
+  for (l = 0; l < N; l++)
+    for (j = 0; j < N; j++)
+      f[k++] = (double) i[l][j];
+}
+
+void put_image_from_double_2_int(double *f, int **i, int N)
+{
+  int l, j, k;
+  k = 0;
+  for (l = 0; l < N; l++)
+    for (j = 0; j < N; j++)
+      i[l][j] = (int) f[k++];
+}
+
+
+void bitrev(double *f, int len)
+{
+  int i, j, m, halflen;
+  double temp;
+
+  if (len <= 2) return ;  /* No action necessary if n=1 or n=2 */
+  halflen = len >> 1;
+  j = 1;
+  for (i = 1; i <= len; i++) {
+    if (i < j) {
+      temp = f[j - 1];
+      f[j - 1] = f[i - 1];
+      f[i - 1] = temp;
+    }
+    m = halflen;
+    while (j > m) {
+      j = j - m;
+      m = (m + 1) >> 1;
+    }
+    j = j + m;
+  }
+}
+
+void inv_sums(double *f)
+{
+  int ii, stepsize, stage, curptr, nthreads, thread, step, nsteps;
+
+  for (stage = 1; stage <= m - 1; stage++) {
+    nthreads = 1 << (stage - 1);
+    stepsize = nthreads << 1;
+    nsteps = (1 << (m - stage)) - 1;
+    for (thread = 1; thread <= nthreads; thread++) {
+      curptr = NN - thread;
+      for (step = 1; step <= nsteps; step++) {
+        f[curptr] += f[curptr - stepsize];
+        curptr -= stepsize;
+      }
+    }
+  }
+}
+
+//--------------------------------------------------------
+//Foreign code - FCT from Bath Univerity
+//--------------------------------------------------------
+void rarrwrt(double f[], int n)
+{
+  int i;
+
+  for (i = 0; i <= n - 1; i++) {
+    fprintf(stderr, "%4d : %f\n", i, f[i]);
+  }
+}
+
+/* fast DCT based on IEEE signal proc, 1992 #8, yugoslavian authors. */
+
+void fwd_sums(double *f)
+{
+  int ii, stepsize, stage, curptr, nthreads, thread, step, nsteps;
+
+  for (stage = m - 1; stage >= 1; stage--) {
+    nthreads = 1 << (stage - 1);
+    stepsize = nthreads << 1;
+    nsteps = (1 << (m - stage)) - 1;
+    for (thread = 1; thread <= nthreads; thread++) {
+      curptr = nthreads + thread - 1;
+      for (step = 1; step <= nsteps; step++) {
+        f[curptr] += f[curptr + stepsize];
+        curptr += stepsize;
+      }
+    }
+  }
+}
+
+void scramble(double *f, int len)
+{
+  double temp;
+  int i, ii1, ii2, halflen, qtrlen;
+
+  halflen = len >> 1;
+  qtrlen = halflen >> 1;
+  bitrev(f, len);
+  bitrev(&f[0], halflen);
+  bitrev(&f[halflen], halflen);
+  ii1 = len - 1;
+  ii2 = halflen;
+  for (i = 0; i <= qtrlen - 1; i++) {
+    temp = f[ii1];
+    f[ii1] = f[ii2];
+    f[ii2] = temp;
+    ii1--;
+    ii2++;
+  }
+}
+
+void unscramble(double *f, int len)
+{
+  double temp;
+  int i, ii1, ii2, halflen, qtrlen;
+
+  halflen = len >> 1;
+  qtrlen = halflen >> 1;
+  ii1 = len - 1;
+  ii2 = halflen;
+  for (i = 0; i <= qtrlen - 1; i++) {
+    temp = f[ii1];
+    f[ii1] = f[ii2];
+    f[ii2] = temp;
+    ii1--;
+    ii2++;
+  }
+  bitrev(&f[0], halflen);
+  bitrev(&f[halflen], halflen);
+  bitrev(f, len);
+}
+
+void initcosarray(int length)
+{
+  int i, group, base, item, nitems, halfN;
+  double factor;
+
+  m = -1;
+  do {
+    m++;
+    NN = 1 << m;
+    if (NN > length) {
+      fprintf(stderr, "ERROR in FCT-- length %d not a power of 2\n", length);
+      exit(1);
+    }
+  } while (NN < length);
+  if (C != NULL) free(C);
+  C = (double *)calloc(NN, sizeof(double));
+  if (C == NULL) {
+    fprintf(stderr, "Unable to allocate C array\n");
+    exit(1);
+  }
+  halfN = NN / 2;
+  two_over_N = 2.0 / (double)NN;
+  root2_over_rootN = sqrt(2.0 / (double)NN);
+  for (i = 0; i <= halfN - 1; i++) C[halfN + i] = 4 * i + 1;
+  for (group = 1; group <= m - 1; group++) {
+    base = 1 << (group - 1);
+    nitems = base;
+    factor = 1.0 * (1 << (m - group));
+    for (item = 1; item <= nitems; item++) C[base + item - 1] = factor * C[halfN + item - 1];
+  }
+
+  //printf("before taking cos, C array =\n"); rarrwrt(C,N);
+  for (i = 1; i <= NN - 1; i++) C[i] = 1.0 / (2.0 * cos(C[i] * PI / (2.0 * NN)));
+  //printf("After taking cos, Carray = \n"); rarrwrt(C,N);
+}
+
+
+void inv_butterflies(double *f)
+{
+  int stage, ii1, ii2, butterfly, ngroups, group, wingspan, increment, baseptr;
+  double Cfac, T;
+
+  for (stage = 1; stage <= m; stage++) {
+    ngroups = 1 << (m - stage);
+    wingspan = 1 << (stage - 1);
+    increment = wingspan << 1;
+    for (butterfly = 1; butterfly <= wingspan; butterfly++) {
+      Cfac = C[wingspan + butterfly - 1];
+      baseptr = 0;
+      for (group = 1; group <= ngroups; group++) {
+        ii1 = baseptr + butterfly - 1;
+        ii2 = ii1 + wingspan;
+        T = Cfac * f[ii2];
+        f[ii2] = f[ii1]-T;
+        f[ii1] = f[ii1] + T;
+        baseptr += increment;
+      }
+    }
+  }
+}
+
+void fwd_butterflies(double *f)
+{
+  int stage, ii1, ii2, butterfly, ngroups, group, wingspan, increment, baseptr;
+  double Cfac, T;
+
+  for (stage = m; stage >= 1; stage--) {
+    ngroups = 1 << (m - stage);
+    wingspan = 1 << (stage - 1);
+    increment = wingspan << 1;
+    for (butterfly = 1; butterfly <= wingspan; butterfly++) {
+      Cfac = C[wingspan + butterfly - 1];
+      baseptr = 0;
+      for (group = 1; group <= ngroups; group++) {
+        ii1 = baseptr + butterfly - 1;
+        ii2 = ii1 + wingspan;
+        T = f[ii2];
+        f[ii2] = Cfac * (f[ii1]-T);
+        f[ii1] = f[ii1] + T;
+        baseptr += increment;
+      }
+    }
+  }
+}
+
+void ifct_noscale(double *f, int length)
+{
+  if (length != NN) initcosarray(length);
+  f[0] *= INVROOT2;
+  inv_sums(f);
+  bitrev(f, NN);
+  inv_butterflies(f);
+  unscramble(f, NN);
+}
+
+void fct_noscale(double *f, int length)
+{
+  if (length != NN) initcosarray(length);
+  scramble(f, NN);
+  fwd_butterflies(f);
+  bitrev(f, NN);
+  fwd_sums(f);
+  f[0] *= INVROOT2;
+}
+
+void ifct_defn_scaling(double *f, int length)
+{
+  ifct_noscale(f, length);
+}
+
+void fct_defn_scaling(double *f, int length)
+{
+  int i;
+
+  fct_noscale(f, length);
+  for (i = 0; i <= NN - 1; i++) f[i] *= two_over_N;
+}
+
+void ifct(double *f, int length)
+{
+  /* CALL THIS FOR INVERSE 1D DCT DON-MONRO PREFERRED SCALING */
+  int i;
+
+  if (length != NN) initcosarray(length);   /* BGS patch June 1997 */
+  for (i = 0; i <= NN - 1; i++) f[i] *= root2_over_rootN;
+  ifct_noscale(f, length);
+}
+
+void fct(double *f, int length)
+{
+  /* CALL THIS FOR FORWARD 1D DCT DON-MONRO PREFERRED SCALING */
+  int i;
+
+  fct_noscale(f, length);
+  for (i = 0; i <= NN - 1; i++) f[i] *= root2_over_rootN;
+}
+
+/****************************************************************
+    2D FAST DCT SECTION
+****************************************************************/
+
+static double *g = NULL;
+static double two_over_sqrtncolsnrows = 0.0;
+static int ncolsvalue = 0;
+static int nrowsvalue = 0;
+
+void initfct2d(int nrows, int ncols)
+{
+  if ((nrows <= 0) || (ncols < 0)) {
+    fprintf(stderr, "FCT2D -- ncols=%d or nrows=%d is <=0\n", nrows, ncols);
+    exit(1);
+  }
+  if (g != NULL) free(g);
+  g = (double *)calloc(nrows, sizeof(double));
+  if (g == NULL) {
+    fprintf(stderr, "FCT2D -- Unable to allocate g array\n");
+    exit(1);
+  }
+  ncolsvalue = ncols;
+  nrowsvalue = nrows;
+  two_over_sqrtncolsnrows = 2.0 / sqrt(ncols * 1.0 * nrows);
+}
+
+void fct2d(double f[], int nrows, int ncols)
+/* CALL THIS FOR FORWARD 2d DCT DON-MONRO PREFERRED SCALING */
+{
+  int u, v;
+
+  if ((ncols != ncolsvalue) || (nrows != nrowsvalue)){
+    initfct2d(nrows, ncols);
+  }
+  for (u = 0; u <= nrows - 1; u++){
+    fct_noscale(&f[u*ncols], ncols);
+  }
+  for (v = 0; v <= ncols - 1; v++){
+    for (u = 0; u <= nrows - 1; u++) {
+      g[u] = f[u * ncols + v];
+    }
+    fct_noscale(g, nrows);
+    for (u = 0; u <= nrows - 1; u++) {
+      f[u*ncols + v] = g[u] * two_over_sqrtncolsnrows;
+    }
+  }
+}
+
+void ifct2d(double f[], int nrows, int ncols)
+/* CALL THIS FOR INVERSE 2d DCT DON-MONRO PREFERRED SCALING */
+{
+  int u, v;
+
+  if ((ncols != ncolsvalue) || (nrows != nrowsvalue)){
+    initfct2d(nrows, ncols);
+  }
+  for (u = 0; u <= nrows - 1; u++){
+    ifct_noscale(&f[u*ncols], ncols);
+  }
+  for (v = 0; v <= ncols - 1; v++){
+    for (u = 0; u <= nrows - 1; u++) {
+      g[u] = f[u * ncols + v];
+    }
+    ifct_noscale(g, nrows);
+    for (u = 0; u <= nrows - 1; u++) {
+      f[u*ncols + v] = g[u] * two_over_sqrtncolsnrows;
+    }
+  }
+}
+
+void matmul(double **a, double **b, double **r, int N)
+{
+  int i, j, k;
+
+  for (i = 0; i < N; i++)
+    for (j = 0; j < N; j++) {
+      r[i][j] = 0.0;
+      for (k = 0; k < N; k++)
+        r[i][j] += a[i][k] * b[k][j];
+    }
+}
+
+void hartley(double **in, double **out, int N)
+{
+  int k, n;
+  double **h;
+
+  h = dmatrix(N, N);
+  //Building up the transformation matrix
+  for (k = 0; k < N; k++)
+    for (n = 0; n < N; n++)
+      h[k][n] = (cos(2 * PI * k * n / N) + sin(2 * PI * k * n / N)) / sqrt(N);
+
+  // Now we have to multiply the input with the transformation matrix
+  matmul(h, in, out, N);
+  freematrix_d(h, N);
+  return ;
+}
+
+double ** dmatrix(int nrows, int ncols)
+{
+  double **m;
+  int i, j;
+  m = (double **) malloc (nrows * sizeof(double *));
+  for (i = 0; i < nrows; i++) {
+    m[i] = (double *) malloc (ncols * sizeof(double));
+    if (!m[i]) printf("\nIt's not working");
+  }
+  for (i = 0; i < nrows; i++)
+    for (j = 0; j < ncols; j++)
+      m[i][j] = 0.0;
+  return m;
+}
+
+void freematrix_d(double **I, int rows)
+{
+  int k;
+  for (k = 0; k < rows; k++)
+    free (I[k]);
+}
+
+void matrix_i2d(int **i, double **d, int N)
+{
+  int x, y;
+  for (x = 0; x < N; x++)
+    for (y = 0; y < N; y++)
+      d[y][x] = i[y][x];
+}
+
+void matrix_d2i(double **d, int **i, int N)
+{
+  int x, y;
+  for (x = 0; x < N; x++)
+    for (y = 0; y < N; y++)
+      i[y][x] = d[y][x];
+}
+
+double * dvector(long int N)
+{
+  double *m;
+  m = (double *) malloc (N * sizeof(double));
+  if (!m) printf("\nIt's not working");
+  return m;
+}
+
+void put_matrix_2_vector(double **i, double *f, int N)
+{
+  int l, j, k;
+  k = 0;
+  for (l = 0; l < N; l++)
+    for (j = 0; j < N; j++)
+      f[k++] = i[l][j];
+}
+
+void put_vector_2_matrix(double *f, double **i, int N)
+{
+  int l, j, k;
+  k = 0;
+  for (l = 0; l < N; l++)
+    for (j = 0; j < N; j++)
+      i[l][j] = f[k++];
+}
+
+void set_in_binary() {
+#if defined(EMX)
+  _fsetmode(in, "b");
+#elif defined(MINGW)
+  setmode(STDIN_FILENO, O_BINARY);
+#endif
+}
+
+void set_out_binary() {
+#if defined(EMX)  
+  _fsetmode(out, "b");
+#elif defined(MINGW)
+  setmode(STDOUT_FILENO, O_BINARY);
+#endif
+}
+ 
+void wm_init2() {
+  set_out_binary();
+}
+
+void wm_init1() {
+  set_in_binary();
+}
+
+void wm_init() {
+  set_in_binary();
+  set_out_binary();
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Fotopoulos/common.h	Sun Aug 12 13:14:34 2007 +0200
@@ -0,0 +1,28 @@
+#define PI      3.1415926535897932
+#define INVROOT2 0.7071067814
+
+void open_image(FILE *in, int *width, int *height);
+void load_image(int **im, FILE *in, int width, int height);
+void save_image(int **im, FILE *out, int width, int height);
+int ** imatrix(int nrows, int ncols);
+void freematrix(int **I, int rows);
+float ran0(long int *idum);
+float gasdev(long int *idum);
+void put_image_from_int_2_double(int **i, double *f, int N);
+void put_image_from_double_2_int(double *f, int **i, int N);
+void fct2d(double f[], int nrows, int ncols);
+void ifct2d(double f[], int nrows, int ncols);
+void matmul(double **a, double **b, double **r, int N);
+void hartley(double **in, double **out, int N);
+double ** dmatrix(int nrows, int ncols);
+void freematrix_d(double **I, int rows);
+void hartley(double **in, double **out, int N);
+void matrix_i2d(int **i, double **d, int N);
+void matrix_d2i(double **d, int **i, int N);
+void put_matrix_2_vector(double **i, double *f, int N);
+void put_vector_2_matrix(double *f, double **i, int N);
+double * dvector(long int N);
+
+void wm_init();   
+void wm_init1();   
+void wm_init2(); 
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Fotopoulos/test-hart.c	Sun Aug 12 13:14:34 2007 +0200
@@ -0,0 +1,109 @@
+/* Watermarking program - Hartley Transform based	*/
+/* Module	: Testing				*/
+/* Author	: Vassilis Fotopoulos			*/
+/* Date		: 26/7/1999		      		*/
+/* Developed at	: ELLAB                 		*/
+/*                Electronics Laboratory            	*/
+/*                Department of Physics             	*/
+/*                University of Patras - GREECE      	*/
+/*		  Copyleft (c) 1999             	*/
+/*------------------------------------------------------*/
+/*	pseudorandom noise generator's code is		*/
+/*	taken from "Numerical Recipes in C"		*/
+/*------------------------------------------------------*/
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <math.h>
+#include <float.h>
+#include <getopt.h>
+#include "common.h"
+
+int height, width;
+
+void read_watermark(double **in, int N, int coeff_start, int wm_length, double wm_alpha)
+{
+  int row, col, count;
+  long int elem, L, M, seed, i;
+  double a;
+  double z;
+  M = coeff_start;
+  L = wm_length;
+  a = wm_alpha;
+  for (i = 1; i <= 1000; i++) {
+    seed = i;
+    z = 0.0;
+    count = 0;
+    elem = 0;
+
+    for (row = 0; row < N; row++)
+      for (col = 0; col < N; col++) {
+        elem++;
+        if (elem > M && count < L) {
+          z += in[row][col] * gasdev(&seed);
+          count++;
+        }
+      }
+
+    printf("%ld\t%f\n", i, z / L);
+  }
+  return ;
+}
+
+int main(int argc, char* argv[])
+{
+  FILE *in;
+  int **image;
+  double **image_i;
+  double **image_d;
+  int c;
+  int N;
+  int coeff_start = 5000, wm_length = 10000;
+  double wm_alpha = 0.2;
+  int width, height;
+
+  pgm_init(&argc, argv); wm_init2();
+
+  while ((c = getopt(argc, argv, "a:s:l:")) != EOF) {
+    switch (c) {
+        case 'a':
+        wm_alpha = atof(optarg);
+        break;
+        case 's':
+        coeff_start = atoi(optarg);
+        break;
+        case 'l':
+        wm_length = atoi(optarg);
+        break;
+    }
+  }
+  argc -= optind;
+  argv += optind;
+
+  in = stdin;
+
+  open_image(in, &width, &height);
+  image = imatrix(height, width);
+  load_image(image, in, width, height);
+
+  if (height == width)
+    N = height;
+  else {
+    fprintf(stderr, "Cannot Proccess non-square images!\n");
+    exit( -11);
+  }
+
+  image_i = dmatrix(height, width);
+  image_d = dmatrix(height, width);
+  if (image_d == NULL) {
+    fprintf(stderr, "Unable to allocate the double array\n");
+    exit(1);
+  }
+  matrix_i2d(image, image_i, N);
+  hartley(image_i, image_d, N);
+  read_watermark(image_d, N, coeff_start, wm_length, wm_alpha);
+
+  freematrix_d(image_i, height);
+  freematrix_d(image_d, height);
+  fclose(in);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Fotopoulos/test-pv.c	Sun Aug 12 13:14:34 2007 +0200
@@ -0,0 +1,127 @@
+/* Watermarking program - Fast Cosine Transform based	*/
+/* Module	: Testing				*/
+/* Author	: Vassilis Fotopoulos			*/
+/* Date		: 21/7/1999				*/
+/* Developed at	: ELLAB                  		*/
+/*                Electronics Laboratory            	*/
+/*                Department of Physics             	*/
+/*                University of Patras - GREECE      	*/
+/*		  Copyleft (c) 1999	    		*/
+/*		  Testing Program       		*/
+/*------------------------------------------------------*/
+/*	pseudorandom noise generator's code is		*/
+/*	taken from "Numerical Recipes in C"		*/
+/*	FCT implementation from the University of Bath	*/
+/*------------------------------------------------------*/
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <math.h>
+#include <float.h>
+#include <getopt.h>
+#include "common.h"
+
+double cu[1024];
+double cv[1024];
+int height, width;
+
+void read_watermark(double *in, int N, int start_coeff, int wm_length, double wm_alpha)
+{
+  int row, col, count;
+  long int elem, L, M, temp, seed, i;
+  double a;
+  double z;
+  FILE *f;
+  M = start_coeff;
+  L = wm_length;
+  a = wm_alpha;
+  for (i = 1; i <= 1000; i++) {
+    seed = i;
+    z = 0.0;
+    count = 0;
+    elem = 0;
+    row = 2;
+    col = -1;
+    do {
+      do {
+        row--;
+        col++;
+        elem++;
+        if (col < N) {
+          if (elem > M) {
+            temp = row * N + col;
+            z += in[temp] * gasdev(&seed);
+            count++;
+          }
+        }
+      } while (row > 0);
+      row = 2 + col;
+      col = -1;
+    } while (count < L);
+    printf("%ld\t%f\n", i, z / L);
+  }
+  return ;
+}
+//--------------------------------------------------------
+void initialize_constants(void)
+{
+  int i;
+  cu[0] = cv[0] = 0.7071068;
+  for (i = 1; i < 1024; i++)
+    cu[i] = cv[i] = 1.0;
+}
+
+int main(int argc, char* argv[])
+{
+  FILE *in;
+  int **image_i;
+  double *image_f = NULL;
+  int N;
+  int c;
+  int coeff_start = 5000, wm_length = 10000;
+  double wm_alpha = 0.2;
+
+  pgm_init(&argc, argv); wm_init2();
+
+  while ((c = getopt(argc, argv, "a:s:l:")) != EOF) {
+    switch (c) {
+        case 'a':
+        wm_alpha = atof(optarg);
+        break;
+        case 's':
+        coeff_start = atoi(optarg);
+        break;
+        case 'l':
+        wm_length = atoi(optarg);
+        break;
+    }
+  }
+  argc -= optind;
+  argv += optind;
+  in = stdin;
+
+  open_image(in, &width, &height);
+  image_i = imatrix(height, width);
+  load_image(image_i, in, width, height);
+
+  if (height == width)
+    N = height;
+  else {
+    fprintf(stderr, "Cannot Proccess non-square images!\n");
+    exit( -11);
+  }
+
+  initialize_constants();
+  image_f = (double *)calloc(N * N, sizeof(double));
+  if (image_f == NULL) {
+    printf("Unable to allocate the float array\n");
+    exit(1);
+  }
+
+  put_image_from_int_2_double(image_i, image_f, N);
+  fct2d(image_f, N, N);
+  read_watermark(image_f, N, coeff_start, wm_length, wm_alpha);
+  fclose(in);
+  freematrix(image_i, height);
+  free(image_f);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Fotopoulos/test-sub.c	Sun Aug 12 13:14:34 2007 +0200
@@ -0,0 +1,237 @@
+/* Watermarking program - Subband DCT Transform based	*/
+/* Module	: Testing				*/
+/* Author	: Vassilis Fotopoulos			*/
+/* Date		: 25/4/2000				*/
+/* Revision	: 6.0					*/
+/* Developed at	: ELLAB                  		*/
+/*                Electronics Laboratory           	*/
+/*                Department of Physics             	*/
+/*                University of Patras - GREECE      	*/
+/*		  Copyleft (c) 1999	    		*/
+/*------------------------------------------------------*/
+/*	pseudorandom noise generator's code is		*/
+/*	taken from "Numerical Recipes in C"		*/
+/*	FCT implementation from University of Bath	*/
+/*------------------------------------------------------*/
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <math.h>
+#include <float.h>
+#include <getopt.h>
+#include "common.h"
+
+//--------------------------------------------------------
+void add_hor_add_ver(double **in, int N, double **out);
+void add_hor_sub_ver(double **in, int N, double **out);
+void sub_hor_add_ver(double **in, int N, double **out);
+void sub_hor_sub_ver(double **in, int N, double **out);
+double detect_mark(double *i, int N, long key, long int L, long int M, double a);
+
+//--------------------------------------------------------
+double cu[1024];
+double cv[1024];
+int height, width;
+//--------------------------------------------------------
+void add_hor_add_ver(double **in, int N, double **out)
+{
+  double **temp;
+  int r, c;
+  temp = dmatrix(N, N);
+  for (r = 0; r < N; r++)
+    for (c = 0; c < N / 2; c++)
+      temp[r][c] = (in[r][2 * c] + in[r][2 * c + 1]) / 2;
+  for (c = 0; c < N / 2; c++)
+    for (r = 0; r < N / 2; r++)
+      out[r][c] = (temp[2 * r][c] + temp[2 * r + 1][c]) / 2;
+  freematrix_d(temp, N);
+}
+//--------------------------------------------------------
+void add_hor_sub_ver(double **in, int N, double **out)
+{
+  double **temp;
+  int r, c;
+  temp = dmatrix(N, N);
+  for (r = 0; r < N; r++)
+    for (c = 0; c < N / 2; c++)
+      temp[r][c] = (in[r][2 * c] + in[r][2 * c + 1]) / 2;
+  for (c = 0; c < N / 2; c++)
+    for (r = 0; r < N / 2; r++)
+      out[r][c] = (temp[2 * r][c] - temp[2 * r + 1][c]) / 2;
+  freematrix_d(temp, N);
+}
+//--------------------------------------------------------
+void sub_hor_add_ver(double **in, int N, double **out)
+{
+  double **temp;
+  int r, c;
+  temp = dmatrix(N, N);
+  for (r = 0; r < N; r++)
+    for (c = 0; c < N / 2; c++)
+      temp[r][c] = (in[r][2 * c] - in[r][2 * c + 1]) / 2;
+  for (c = 0; c < N / 2; c++)
+    for (r = 0; r < N / 2; r++)
+      out[r][c] = (temp[2 * r][c] + temp[2 * r + 1][c]) / 2;
+  freematrix_d(temp, N);
+}
+//--------------------------------------------------------
+void sub_hor_sub_ver(double **in, int N, double **out)
+{
+  double **temp;
+  int r, c;
+  temp = dmatrix(N, N);
+  for (r = 0; r < N; r++)
+    for (c = 0; c < N / 2; c++)
+      temp[r][c] = (in[r][2 * c] - in[r][2 * c + 1]) / 2;
+  for (c = 0; c < N / 2; c++)
+    for (r = 0; r < N / 2; r++)
+      out[r][c] = (temp[2 * r][c] - temp[2 * r + 1][c]) / 2;
+  freematrix_d(temp, N);
+}
+
+//---------------------------------------------------------
+double detect_mark(double *i, int N, long key, long int L, long int M, double a)
+{
+  int row, col, count;
+  long int elem, temp, seed;
+  double z;
+
+
+  seed = key;
+  z = 0.0;
+  count = 0;
+  elem = 0;
+  row = 2;
+  col = -1;
+  do {
+    do {
+      row--;
+      col++;
+      elem++;
+      if (col < N) {
+        if (elem > M) {
+          temp = row * N + col;
+          z += i[temp] * gasdev(&seed);
+          count++;
+        }
+      }
+    } while (row > 0);
+    row = 2 + col;
+    col = -1;
+  } while (count < L);
+
+  return (z / L);
+}
+
+int main(int argc, char* argv[])
+{
+  double **i;
+  FILE *in;
+  int N;
+  long int key, M1, L1, M2, L2;
+  double **ll, **lh, **hl, **hh;
+  double *v1, *v2, *v3, *v99;
+  double m1, m2, m3, detect_value, m99;
+  int ** image_i;
+  int c;
+  int wm_length_1 = 10000, wm_length_ll = 10000, coeff_start_1 = 3000, coeff_start_ll = 3000;
+  double a_ll = 0.1, a_other = 0.2;
+
+  pgm_init(&argc, argv); wm_init2();
+
+  while ((c = getopt(argc, argv, "a:b:t:m:s:l:")) != EOF) {
+    switch (c) {
+        case 'a':
+        a_ll = atof(optarg);
+        break;
+        case 'b':
+        a_other = atof(optarg);
+        break;
+        case 't':
+        coeff_start_1 = atoi(optarg);
+        break;
+        case 'm':
+        wm_length_1 = atoi(optarg);
+        break;
+        case 's':
+        coeff_start_ll = atoi(optarg);
+        break;
+        case 'l':
+        wm_length_ll = atoi(optarg);
+        break;
+    }
+  }
+  argc -= optind;
+  argv += optind;
+
+  in = stdin;
+  open_image(in, &width, &height);
+  image_i = imatrix(height, width);
+  load_image(image_i, in, width, height);
+
+  if (height == width)
+    N = height;
+  else {
+    fprintf(stderr, "Cannot Proccess non-square images!\n");
+    exit( -11);
+  }
+  // starting coeff. for 1st level decomp.
+  M1 = coeff_start_1;
+  // number of coeffs to alter
+  L1 = wm_length_1;
+  // alpha parameter
+
+  // now the LL band
+  M2 = coeff_start_ll;
+  L2 = wm_length_ll;
+
+
+  i = dmatrix(N, N);
+  ll = dmatrix(N / 2, N / 2);
+  lh = dmatrix(N / 2, N / 2);
+  hl = dmatrix(N / 2, N / 2);
+  hh = dmatrix(N / 2, N / 2);
+  v1 = dvector(N * N / 4);
+  v2 = dvector(N * N / 4);
+  v3 = dvector(N * N / 4);
+  v99 = dvector(N * N / 4);
+
+  matrix_i2d(image_i, i, N);
+
+  //---------------------1o decomposition-------------------
+  add_hor_add_ver(i, N, ll);
+  add_hor_sub_ver(i, N, lh);
+  sub_hor_add_ver(i, N, hl);
+  sub_hor_sub_ver(i, N, hh);
+  //---------------------Detect Watermark from all bands----
+  put_matrix_2_vector(lh, v1, N / 2);
+  put_matrix_2_vector(hl, v2, N / 2);
+  put_matrix_2_vector(hh, v3, N / 2);
+  put_matrix_2_vector(ll, v99, N / 2);
+  fct2d(v1, N / 2, N / 2);
+  fct2d(v2, N / 2, N / 2);
+  fct2d(v3, N / 2, N / 2);
+  fct2d(v99, N / 2, N / 2);
+  for (key = 1; key <= 1000; key++) {
+    m1 = detect_mark(v1, N / 2, key, L1, M1, a_other);
+    m2 = detect_mark(v2, N / 2, key, L1, M1, a_other);
+    m3 = detect_mark(v3, N / 2, key, L1, M1, a_other);
+    m99 = detect_mark(v99, N / 2, key, L2, M2, a_ll);
+    detect_value = (m1 + m2 + m3 + m99) / 4;
+    printf("%ld\t%f\t%f\t%f\t%f\t%f\n", key, m1, m2, m3, m99, detect_value);
+  }
+  //--------------------------------------------------------
+  free(v1);
+  free(v2);
+  free(v3);
+  free(v99);
+  freematrix_d(ll, N / 2);
+  freematrix_d(hl, N / 2);
+  freematrix_d(lh, N / 2);
+  freematrix_d(hh, N / 2);
+  fclose(in);
+}
+
+
+
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Makefile	Sun Aug 12 13:14:34 2007 +0200
@@ -0,0 +1,36 @@
+# Makefile
+
+WEBDIR = /home/scicomp/pmeerw/public-www/Watermarking/source
+
+all: meerwald fotopoulos 
+
+meerwald:
+	cd Meerwald ; make
+
+fotopoulos:
+	cd Fotopoulos ; make
+
+install:
+	cd Meerwald ; make install
+	cd Fotopoulos ; make install
+
+clean:
+	cd Meerwald ; make clean
+	cd Fotopoulos ; make clean
+
+dist:
+	cp -v manual.pdf manual.ps $(WEBDIR)
+	cp -v ANNOUNCEMENT README $(WEBDIR)
+	cd linux_bin ; tar -czf ../wm_linux_bin.tar.gz *
+	mv -v wm_linux_bin.tar.gz $(WEBDIR)
+	cd win32_bin ; zip -9 ../wm_win32_bin.zip *
+	mv -v wm_win32_bin.zip $(WEBDIR)
+	tar -czf wm_source_bin.tar.gz *
+	mv -v wm_source_bin.tar.gz $(WEBDIR)
+	zip -9r wm_source_bin.zip *
+	mv -v wm_source_bin.zip $(WEBDIR)
+	tar -czf wm_source.tar.gz ANNOUNCEMENT Fotopoulos/* Meerwald/* Makefile README images/* make/* manual.* sigs/.dummy watermarked/.dummy wms/.dummy win32_bin/.dummy linux_bin/.dummy
+	mv -v wm_source.tar.gz $(WEBDIR)
+	zip -9r wm_source.zip ANNOUNCEMENT Fotopoulos/* Meerwald/* Makefile README images/* make/* manual.* sigs/.dummy watermarked/.dummy wms/.dummy linux_bin/.dummy win32_bin/.dummy
+	mv -v wm_source.zip $(WEBDIR)
+	chmod a+r $(WEBDIR)/*
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Meerwald/Makefile	Sun Aug 12 13:14:34 2007 +0200
@@ -0,0 +1,423 @@
+# Makefile
+
+# choose build platform
+include ../make/make.config
+
+all: 	tools \
+	bruyn \
+	koch \
+	corvi \
+	xia \
+	xie \
+	cox \
+	zhu \
+	dugad \
+	wang \
+	frid2 \
+	kim
+
+.SUFFIXES: .c .o .1 .ps
+
+.c$(O):
+	$(CC) $(CFLAGS) $(INCLUDES) -o $@ -c $<
+
+.1.ps:
+	$(GROFF) $< > $@ 
+
+# library containing general stuff
+
+$(LIBPREFIX)wm$(LIB): dct$(O) coeff$(O) gray$(O) sort$(O) signature$(O) coord$(O) wm$(O)
+	$(RM) $@
+	ar -rc $@ dct$(O) coeff$(O) gray$(O) sort$(O) signature$(O) coord$(O) wm$(O)
+
+libraryclean:
+	$(RM) $(LIBPREFIX)wm$(LIB)
+
+# library containing wavelet transform stuff
+
+$(LIBPREFIX)wavelet$(LIB): wavelet$(O) dwt$(O) dwt_util$(O)
+	$(RM) $@
+	ar -rc $@ wavelet$(O) dwt$(O) dwt_util$(O)
+
+waveletclean:
+	$(RM) $(LIBPREFIX)wavelet$(LIB)
+
+# some general tools to compute difference image, PSNR, ...
+
+tools: cmp_pgm$(EXE)  cmp_dct8x8$(EXE)  cmp_dct$(EXE) cmp_dwt$(EXE)
+
+toolstest:
+
+toolsinstall: tools
+	$(CP) cmp_pgm$(EXE)  cmp_dct8x8$(EXE)  cmp_dct$(EXE) cmp_dwt$(EXE) $(INSTALLDIR)
+
+toolsman: cmp_pgm.ps cmp_dct8x8.ps cmp_dct.ps
+
+toolsclean:
+	$(RM) cmp_pgm$(EXE) cmp_dct$(EXE) cmp_dct8x8$(EXE)
+
+cmp_pgm$(EXE):  cmp_pgm$(O) $(LIBPREFIX)wm$(LIB)
+	$(CC) $(LDFLAGS) -o $@ cmp_pgm$(O) $(WMLIB) $(PGMLIBS)
+
+cmp_dct$(EXE):  cmp_dct$(O) $(LIBPREFIX)wm$(LIB)
+	$(CC) $(LDFLAGS) -o $@ cmp_dct$(O) $(WMLIB) $(PGMLIBS)
+
+cmp_dwt$(EXE):  cmp_dwt$(O) $(LIBPREFIX)wavelet$(LIB)  $(LIBPREFIX)wm$(LIB)
+	$(CC) $(LDFLAGS) -o $@ cmp_dwt$(O) $(WAVELIB) $(WMLIB) $(PGMLIBS)
+
+cmp_dct8x8$(EXE): cmp_dct8x8$(O) $(LIBPREFIX)wm$(LIB)
+	$(CC) $(LDFLAGS) -o $@ cmp_dct8x8$(O) $(WMLIB) $(PGMLIBS)
+
+
+# Koch's algorithm (8x8 block DCT, blind, binary)
+
+koch: gen_koch_sig$(EXE) wm_koch_e$(EXE) wm_koch_d$(EXE) cmp_koch_sig$(EXE)
+
+kochtest: koch
+	gen_koch_sig$(EXE) -n 150 < gen_koch_sig.c > ../sigs/koch.sig
+	wm_koch_e$(EXE) -s ../sigs/koch.sig -o ../watermarked/koch_lena.pgm ../images/lena.pgm
+	wm_koch_d$(EXE) -s ../sigs/koch.sig -o ../wms/koch.wm ../watermarked/koch_lena.pgm
+	cmp_koch_sig$(EXE) -s ../sigs/koch.sig ../wms/koch.wm
+
+kochinstall: koch
+	$(CP) gen_koch_sig$(EXE) wm_koch_e$(EXE) wm_koch_d$(EXE) cmp_koch_sig$(EXE) $(INSTALLDIR)
+
+kochclean:
+	$(RM) gen_koch_sig$(EXE) wm_koch_e$(EXE) wm_koch_d$(EXE) cmp_koch_sig$(EXE)
+
+kochman:
+
+wm_koch_e$(EXE): wm_koch_e$(O) $(LIBPREFIX)wm$(LIB)
+	$(CC) $(LDFLAGS) -o $@ wm_koch_e$(O) $(WMLIB) $(LIBS) $(PGMLIBS)
+
+wm_koch_d$(EXE): wm_koch_d$(O) $(LIBPREFIX)wm$(LIB)
+	$(CC) $(LDFLAGS) -o $@  wm_koch_d$(O) $(WMLIB) $(LIBS) $(PGMLIBS)
+
+gen_koch_sig$(EXE): gen_koch_sig$(O) wm$(O)
+	$(CC) $(LDFLAGS) -o $@ gen_koch_sig$(O) wm$(O) $(LIBS)
+
+cmp_koch_sig$(EXE): cmp_koch_sig$(O) $(LIBPREFIX)wm$(LIB)
+	$(CC) $(LDFLAGS) -o $@ cmp_koch_sig$(O) $(WMLIB) $(LIBS)
+
+# Fridrich's 2. scheme (full-frame DCT, blind, binary)
+
+frid2: gen_frid2_sig$(EXE) wm_frid2_e$(EXE) wm_frid2_d$(EXE) cmp_frid2_sig$(EXE)
+
+frid2test: frid2
+	gen_frid2_sig$(EXE) -n 250 < gen_frid2_sig.c > ../sigs/frid2.sig
+	wm_frid2_e$(EXE) -s ../sigs/frid2.sig -o ../watermarked/frid2_lena.pgm ../images/lena.pgm
+	wm_frid2_d$(EXE) -s ../sigs/frid2.sig -o ../wms/frid2.wm ../watermarked/frid2_lena.pgm
+	cmp_frid2_sig$(EXE) -s ../sigs/frid2.sig ../wms/frid2.wm
+
+frid2install: frid2
+	$(CP) gen_frid2_sig$(EXE) wm_frid2_e$(EXE) wm_frid2_d$(EXE) cmp_frid2_sig$(EXE) $(INSTALLDIR)
+
+frid2clean:
+	$(RM) gen_frid2_sig$(EXE) wm_frid2_e$(EXE) wm_frid2_d$(EXE) cmp_frid2_sig$(EXE)
+
+frid2man:
+
+wm_frid2_e$(EXE): wm_frid2_e$(O) $(LIBPREFIX)wm$(LIB) frid2_common$(O)
+	$(CC) $(LDFLAGS) -o $@ wm_frid2_e$(O) frid2_common$(O) $(WMLIB) $(LIBS) $(PGMLIBS)
+
+wm_frid2_d$(EXE): wm_frid2_d$(O) $(LIBPREFIX)wm$(LIB) frid2_common$(O)
+	$(CC) $(LDFLAGS) -o $@  wm_frid2_d$(O) frid2_common$(O) $(WMLIB) $(LIBS) $(PGMLIBS)
+
+gen_frid2_sig$(EXE): gen_frid2_sig$(O) wm$(O)
+	$(CC) $(LDFLAGS) -o $@ gen_frid2_sig$(O) wm$(O) $(LIBS)
+
+cmp_frid2_sig$(EXE): cmp_frid2_sig$(O) $(LIBPREFIX)wm$(LIB)
+	$(CC) $(LDFLAGS) -o $@ cmp_frid2_sig$(O) $(WMLIB) $(LIBS)
+
+
+# Bruyndonckx's algorithm (spatial domain, block classification, blind)
+
+bruyn: gen_bruyn_sig$(EXE) wm_bruyn_e$(EXE) wm_bruyn_d$(EXE) cmp_bruyn_sig$(EXE)
+
+bruyntest: bruyn
+	gen_bruyn_sig$(EXE) -n 400 < gen_bruyn_sig.c > ../sigs/bruyn.sig
+	wm_bruyn_e$(EXE) -s ../sigs/bruyn.sig -o ../watermarked/bruyn_lena.pgm ../images/lena.pgm
+	wm_bruyn_d$(EXE) -s ../sigs/bruyn.sig -o ../wms/bruyn.wm ../watermarked/bruyn_lena.pgm
+	cmp_bruyn_sig$(EXE) -s ../sigs/bruyn.sig ../wms/bruyn.wm
+
+bruyninstall: bruyn
+	$(CP) gen_bruyn_sig$(EXE) wm_bruyn_e$(EXE) wm_bruyn_d$(EXE) cmp_bruyn_sig$(EXE) $(INSTALLDIR)
+
+bruynclean:
+	$(RM) gen_bruyn_sig$(EXE) wm_bruyn_e$(EXE) wm_bruyn_d$(EXE) cmp_bruyn_sig$(EXE)
+
+bruynman:
+
+wm_bruyn_e$(EXE): wm_bruyn_e$(O) bruyn_common$(O) $(LIBPREFIX)wm$(LIB)
+	$(CC) $(LDFLAGS) -o $@ wm_bruyn_e$(O) bruyn_common$(O) $(WMLIB) $(LIBS) $(PGMLIBS)
+
+wm_bruyn_d$(EXE): wm_bruyn_d$(O)  bruyn_common$(O) $(LIBPREFIX)wm$(LIB)
+	$(CC) $(LDFLAGS) -o $@  wm_bruyn_d$(O) bruyn_common$(O) $(WMLIB) $(LIBS) $(PGMLIBS)
+
+gen_bruyn_sig$(EXE): gen_bruyn_sig$(O) wm$(O)
+	$(CC) $(LDFLAGS) -o $@ gen_bruyn_sig$(O) wm$(O) $(LIBS)
+
+cmp_bruyn_sig$(EXE): cmp_bruyn_sig$(O) $(LIBPREFIX)wm$(LIB)
+	$(CC) $(LDFLAGS) -o $@ cmp_bruyn_sig$(O) $(WMLIB) $(LIBS)
+
+
+# Cox's algorithm (full-frame DCT, non-blind, spread-spectrum)
+
+cox: gen_cox_sig$(EXE) wm_cox_e$(EXE) wm_cox_d$(EXE) cmp_cox_sig$(EXE)
+
+coxtest: cox
+	gen_cox_sig$(EXE) > ../sigs/cox.sig
+	wm_cox_e$(EXE) -s ../sigs/cox.sig -o ../watermarked/cox_lena.pgm ../images/lena.pgm
+	wm_cox_d$(EXE) -s ../sigs/cox.sig -o ../wms/cox.wm -i ../images/lena.pgm ../watermarked/cox_lena.pgm 
+	cmp_cox_sig$(EXE) -s ../sigs/cox.sig ../wms/cox.wm
+
+coxinstall: cox
+	$(CP) gen_cox_sig$(EXE) wm_cox_e$(EXE) wm_cox_d$(EXE) cmp_cox_sig$(EXE) $(INSTALLDIR)
+
+coxman: gen_cox_sig.ps wm_cox_e.ps wm_cox_d.ps
+
+wm_cox_e$(EXE): wm_cox_e$(O) $(LIBPREFIX)wm$(LIB)
+	$(CC) $(LDFLAGS) -o $@ wm_cox_e$(O) $(WMLIB) $(LIBS) $(PGMLIBS)
+
+wm_cox_d$(EXE): wm_cox_d$(O) $(LIBPREFIX)wm$(LIB)
+	$(CC) $(LDFLAGS) -o $@  wm_cox_d$(O) $(WMLIB) $(LIBS) $(PGMLIBS)
+
+gen_cox_sig$(EXE): gen_cox_sig$(O)
+	$(CC) $(LDFLAGS) -o $@ gen_cox_sig$(O) $(LIBS)
+
+cmp_cox_sig$(EXE): cmp_cox_sig$(O)
+	$(CC) $(LDFLAGS) -o $@ cmp_cox_sig$(O) $(LIBS)
+
+coxclean:
+	$(RM) gen_cox_sig$(EXE) wm_cox_e$(EXE) wm_cox_d$(EXE) cmp_cox_sig$(EXE)
+
+
+# Corvi's algorithm (DWT, non-blind, spread-spectrum, approximation image)
+
+corvi: gen_corvi_sig$(EXE) wm_corvi_e$(EXE) wm_corvi_d$(EXE) cmp_corvi_sig$(EXE)
+
+corvitest: corvi
+	gen_corvi_sig$(EXE) > ../sigs/corvi.sig
+	wm_corvi_e$(EXE) -s ../sigs/corvi.sig -o ../watermarked/corvi_lena.pgm ../images/lena.pgm
+	wm_corvi_d$(EXE) -s ../sigs/corvi.sig -o ../wms/corvi.wm -i ../images/lena.pgm ../watermarked/corvi_lena.pgm 
+	cmp_corvi_sig$(EXE) -s ../sigs/corvi.sig ../wms/corvi.wm
+
+corviinstall: corvi
+	$(CP) gen_corvi_sig$(EXE) wm_corvi_e$(EXE) wm_corvi_d$(EXE) cmp_corvi_sig$(EXE) $(INSTALLDIR)
+
+corviman: gen_corvi_sig.ps wm_corvi_e.ps wm_corvi_d.ps
+
+wm_corvi_e$(EXE): wm_corvi_e$(O) $(LIBPREFIX)wm$(LIB) $(LIBPREFIX)wavelet$(LIB)
+	$(CC) $(LDFLAGS) -o $@ wm_corvi_e$(O) $(WMLIB) $(WAVELIB) $(LIBS) $(PGMLIBS)
+
+wm_corvi_d$(EXE): wm_corvi_d$(O) $(LIBPREFIX)wm$(LIB) $(LIBPREFIX)wavelet$(LIB)
+	$(CC) $(LDFLAGS) -o $@  wm_corvi_d$(O) $(WMLIB) $(WAVELIB) $(LIBS) $(PGMLIBS)
+
+gen_corvi_sig$(EXE): gen_corvi_sig$(O)
+	$(CC) $(LDFLAGS) -o $@ gen_corvi_sig$(O) $(LIBS)
+
+cmp_corvi_sig$(EXE): cmp_corvi_sig$(O)
+	$(CC) $(LDFLAGS) -o $@ cmp_corvi_sig$(O) $(LIBS)
+
+corviclean:
+	$(RM) gen_corvi_sig$(EXE) wm_corvi_e$(EXE) wm_corvi_d$(EXE) cmp_corvi_sig$(EXE)
+
+
+# Xia's algorithm (DWT, non-blind, spread-spectrum, detail subbands)
+
+xia: gen_xia_sig$(EXE) wm_xia_e$(EXE) wm_xia_d$(EXE) cmp_xia_sig$(EXE)
+
+xiatest: xia
+	gen_xia_sig$(EXE) > ../sigs/xia.sig
+	wm_xia_e$(EXE) -s ../sigs/xia.sig -o ../watermarked/xia_lena.pgm ../images/lena.pgm
+	wm_xia_d$(EXE) -s ../sigs/xia.sig -o ../wms/xia.wm -i ../images/lena.pgm ../watermarked/xia_lena.pgm 
+	cmp_xia_sig$(EXE) -s ../sigs/xia.sig ../wms/xia.wm
+
+xiainstall: xia
+	$(CP) gen_xia_sig$(EXE) wm_xia_e$(EXE) wm_xia_d$(EXE) cmp_xia_sig$(EXE) $(INSTALLDIR)
+
+xiaman: gen_xia_sig.ps wm_xia_e.ps wm_xia_d.ps
+
+wm_xia_e$(EXE): wm_xia_e$(O) $(LIBPREFIX)wm$(LIB) $(LIBPREFIX)wavelet$(LIB)
+	$(CC) $(LDFLAGS) -o $@ wm_xia_e$(O) $(WMLIB) $(WAVELIB) $(LIBS) $(PGMLIBS)
+
+wm_xia_d$(EXE): wm_xia_d$(O) $(LIBPREFIX)wm$(LIB) $(LIBPREFIX)wavelet$(LIB)
+	$(CC) $(LDFLAGS) -o $@  wm_xia_d$(O) $(WMLIB) $(WAVELIB) $(LIBS) $(PGMLIBS)
+
+gen_xia_sig$(EXE): gen_xia_sig$(O)
+	$(CC) $(LDFLAGS) -o $@ gen_xia_sig$(O) $(LIBS)
+
+cmp_xia_sig$(EXE): cmp_xia_sig$(O)
+	$(CC) $(LDFLAGS) -o $@ cmp_xia_sig$(O) $(LIBS)
+
+xiaclean:
+	$(RM) gen_xia_sig$(EXE) wm_xia_e$(EXE) wm_xia_d$(EXE) cmp_xia_sig$(EXE)
+
+# Wang's algorithm (DWT, non-blind, spread-spectrum, detail subbands)
+
+wang: gen_wang_sig$(EXE) wm_wang_e$(EXE) wm_wang_d$(EXE) cmp_wang_sig$(EXE)
+
+wangtest: wang
+	gen_wang_sig$(EXE) -n 1000 > ../sigs/wang.sig
+	wm_wang_e$(EXE) -s ../sigs/wang.sig -o ../watermarked/wang_lena.pgm ../images/lena.pgm
+	wm_wang_d$(EXE) -s ../sigs/wang.sig -o ../wms/wang.wm -i ../images/lena.pgm ../watermarked/wang_lena.pgm 
+	cmp_wang_sig$(EXE) -s ../sigs/wang.sig ../wms/wang.wm
+
+wanginstall: wang
+	$(CP) gen_wang_sig$(EXE) wm_wang_e$(EXE) wm_wang_d$(EXE) cmp_wang_sig$(EXE) $(INSTALLDIR)
+
+wangman: gen_wang_sig.ps wm_wang_e.ps wm_wang_d.ps
+
+wm_wang_e$(EXE): wm_wang_e$(O) $(LIBPREFIX)wm$(LIB) $(LIBPREFIX)wavelet$(LIB) wang_common$(O)
+	$(CC) $(LDFLAGS) -o $@ wm_wang_e$(O) wang_common$(O) $(WMLIB) $(WAVELIB) $(LIBS) $(PGMLIBS)
+
+wm_wang_d$(EXE): wm_wang_d$(O) $(LIBPREFIX)wm$(LIB) $(LIBPREFIX)wavelet$(LIB) wang_common$(O)
+	$(CC) $(LDFLAGS) -o $@  wm_wang_d$(O) wang_common$(O) $(WMLIB) $(WAVELIB) $(LIBS) $(PGMLIBS)
+
+gen_wang_sig$(EXE): gen_wang_sig$(O)
+	$(CC) $(LDFLAGS) -o $@ gen_wang_sig$(O) $(LIBS)
+
+cmp_wang_sig$(EXE): cmp_wang_sig$(O)
+	$(CC) $(LDFLAGS) -o $@ cmp_wang_sig$(O) $(LIBS)
+
+wangclean:
+	$(RM) gen_wang_sig$(EXE) wm_wang_e$(EXE) wm_wang_d$(EXE) cmp_wang_sig$(EXE)
+
+# Kim's algorithm (DWT, non-blind, spread-spectrum, approx. & detail subbands)
+
+kim: gen_kim_sig$(EXE) wm_kim_e$(EXE) wm_kim_d$(EXE) cmp_kim_sig$(EXE)
+
+kimtest: kim
+	gen_kim_sig$(EXE) -n 1000 > ../sigs/kim.sig
+	wm_kim_e$(EXE) -s ../sigs/kim.sig -o ../watermarked/kim_lena.pgm ../images/lena.pgm
+	wm_kim_d$(EXE) -s ../sigs/kim.sig -o ../wms/kim.wm -i ../images/lena.pgm ../watermarked/kim_lena.pgm 
+	cmp_kim_sig$(EXE) -s ../sigs/kim.sig ../wms/kim.wm
+
+kiminstall: kim
+	$(CP) gen_kim_sig$(EXE) wm_kim_e$(EXE) wm_kim_d$(EXE) cmp_kim_sig$(EXE) $(INSTALLDIR)
+
+kimman: gen_kim_sig.ps wm_kim_e.ps wm_kim_d.ps
+
+wm_kim_e$(EXE): wm_kim_e$(O) $(LIBPREFIX)wm$(LIB) $(LIBPREFIX)wavelet$(LIB) kim_common$(O)
+	$(CC) $(LDFLAGS) -o $@ wm_kim_e$(O) kim_common$(O) $(WMLIB) $(WAVELIB) $(LIBS) $(PGMLIBS)
+
+wm_kim_d$(EXE): wm_kim_d$(O) $(LIBPREFIX)wm$(LIB) $(LIBPREFIX)wavelet$(LIB) kim_common$(O)
+	$(CC) $(LDFLAGS) -o $@  wm_kim_d$(O) kim_common$(O) $(WMLIB) $(WAVELIB) $(LIBS) $(PGMLIBS)
+
+gen_kim_sig$(EXE): gen_kim_sig$(O)
+	$(CC) $(LDFLAGS) -o $@ gen_kim_sig$(O) $(LIBS)
+
+cmp_kim_sig$(EXE): cmp_kim_sig$(O)
+	$(CC) $(LDFLAGS) -o $@ cmp_kim_sig$(O) $(LIBS)
+
+kimclean:
+	$(RM) gen_kim_sig$(EXE) wm_kim_e$(EXE) wm_kim_d$(EXE) cmp_kim_sig$(EXE)
+
+# Zhu's algorithm (DWT, non-blind, spread-spectrum, detail subbands)
+
+zhu: gen_zhu_sig$(EXE) wm_zhu_e$(EXE) wm_zhu_d$(EXE) cmp_zhu_sig$(EXE)
+
+zhutest: zhu
+	gen_zhu_sig$(EXE) > ../sigs/zhu.sig
+	wm_zhu_e$(EXE) -s ../sigs/zhu.sig -o ../watermarked/zhu_lena.pgm ../images/lena.pgm
+	wm_zhu_d$(EXE) -s ../sigs/zhu.sig -o ../wms/zhu.wm -i ../images/lena.pgm ../watermarked/zhu_lena.pgm 
+	cmp_zhu_sig$(EXE) -s ../sigs/zhu.sig ../wms/zhu.wm
+
+zhuinstall: zhu
+	$(CP) gen_zhu_sig$(EXE) wm_zhu_e$(EXE) wm_zhu_d$(EXE) cmp_zhu_sig$(EXE) $(INSTALLDIR)
+
+zhuman: gen_zhu_sig.ps wm_zhu_e.ps wm_zhu_d.ps
+
+wm_zhu_e$(EXE): wm_zhu_e$(O) $(LIBPREFIX)wm$(LIB) $(LIBPREFIX)wavelet$(LIB)
+	$(CC) $(LDFLAGS) -o $@ wm_zhu_e$(O) $(WMLIB) $(WAVELIB) $(LIBS) $(PGMLIBS)
+
+wm_zhu_d$(EXE): wm_zhu_d$(O) $(LIBPREFIX)wm$(LIB) $(LIBPREFIX)wavelet$(LIB)
+	$(CC) $(LDFLAGS) -o $@  wm_zhu_d$(O) $(WMLIB) $(WAVELIB) $(LIBS) $(PGMLIBS)
+
+gen_zhu_sig$(EXE): gen_zhu_sig$(O)
+	$(CC) $(LDFLAGS) -o $@ gen_zhu_sig$(O) $(LIBS)
+
+cmp_zhu_sig$(EXE): cmp_zhu_sig$(O)
+	$(CC) $(LDFLAGS) -o $@ cmp_zhu_sig$(O) $(LIBS)
+
+zhuclean:
+	$(RM) gen_zhu_sig$(EXE) wm_zhu_e$(EXE) wm_zhu_d$(EXE) cmp_zhu_sig$(EXE)
+
+# Xie's algorithm (DWT, blind, binary, quantization, approximation image)
+
+xie: gen_xie_sig$(EXE) wm_xie_e$(EXE) wm_xie_d$(EXE) cmp_xie_sig$(EXE)
+
+xietest: xie
+	gen_xie_sig$(EXE) -n 800 gen_xie_sig.c > ../sigs/xie.sig
+	wm_xie_e$(EXE) -s ../sigs/xie.sig -o ../watermarked/xie_lena.pgm ../images/lena.pgm
+	wm_xie_d$(EXE) -s ../sigs/xie.sig -o ../wms/xie.wm ../watermarked/xie_lena.pgm 
+	cmp_xie_sig$(EXE) -s ../sigs/xie.sig ../wms/xie.wm
+
+xieinstall: xie
+	$(CP) gen_xie_sig$(EXE) wm_xie_e$(EXE) wm_xie_d$(EXE) cmp_xie_sig$(EXE) $(INSTALLDIR)
+
+xieman: gen_xie_sig.ps wm_xie_e.ps wm_xie_d.ps
+
+wm_xie_e$(EXE): wm_xie_e$(O) $(LIBPREFIX)wm$(LIB) $(LIBPREFIX)wavelet$(LIB)
+	$(CC) $(LDFLAGS) -o $@ wm_xie_e$(O) $(WMLIB) $(WAVELIB) $(LIBS) $(PGMLIBS)
+
+wm_xie_d$(EXE): wm_xie_d$(O) $(LIBPREFIX)wm$(LIB) $(LIBPREFIX)wavelet$(LIB)
+	$(CC) $(LDFLAGS) -o $@  wm_xie_d$(O) $(WMLIB) $(WAVELIB) $(LIBS) $(PGMLIBS)
+
+gen_xie_sig$(EXE): gen_xie_sig$(O) wm$(O)
+	$(CC) $(LDFLAGS) -o $@ gen_xie_sig$(O) wm$(O) $(LIBS)
+
+cmp_xie_sig$(EXE): cmp_xie_sig$(O) $(LIBPREFIX)wm$(LIB)
+	$(CC) $(LDFLAGS) -o $@ cmp_xie_sig$(O) $(WMLIB) $(LIBS)
+
+xieclean:
+	$(RM) gen_xie_sig$(EXE) wm_xie_e$(EXE) wm_xie_d$(EXE) cmp_xie_sig$(EXE)
+
+# Dugad's algorithm (DWT, blind)
+
+dugad: gen_dugad_sig$(EXE) wm_dugad_e$(EXE) wm_dugad_d$(EXE) cmp_dugad_sig$(EXE)
+
+dugadtest: dugad
+	gen_dugad_sig$(EXE) -o ../sigs/dugad.sig
+	wm_dugad_e$(EXE) -s ../sigs/dugad.sig -o ../watermarked/dugad_lena.pgm ../images/lena.pgm
+	wm_dugad_d$(EXE) -s ../sigs/dugad.sig -o ../wms/dugad.wm ../watermarked/dugad_lena.pgm 
+	cmp_dugad_sig$(EXE) -s ../sigs/dugad.sig ../wms/dugad.wm
+
+dugadinstall: dugad
+	$(CP) gen_dugad_sig$(EXE) wm_dugad_e$(EXE) wm_dugad_d$(EXE) cmp_dugad_sig$(EXE) $(INSTALLDIR)
+
+dugadman: gen_dugad_sig.ps wm_dugad_e.ps wm_dugad_d.ps
+
+wm_dugad_e$(EXE): wm_dugad_e$(O) $(LIBPREFIX)wm$(LIB) $(LIBPREFIX)wavelet$(LIB)
+	$(CC) $(LDFLAGS) -o $@ wm_dugad_e$(O) $(WMLIB) $(WAVELIB) $(LIBS) $(PGMLIBS)
+
+wm_dugad_d$(EXE): wm_dugad_d$(O) $(LIBPREFIX)wm$(LIB) $(LIBPREFIX)wavelet$(LIB)
+	$(CC) $(LDFLAGS) -o $@  wm_dugad_d$(O) $(WMLIB) $(WAVELIB) $(LIBS) $(PGMLIBS)
+
+gen_dugad_sig$(EXE): gen_dugad_sig$(O)
+	$(CC) $(LDFLAGS) -o $@ gen_dugad_sig$(O) $(LIBS)
+
+cmp_dugad_sig$(EXE): cmp_dugad_sig$(O) $(LIBPREFIX)wm$(LIB)
+	$(CC) $(LDFLAGS) -o $@ cmp_dugad_sig$(O) $(WMLIB) $(LIBS)
+
+dugadclean:
+	$(RM) gen_dugad_sig$(EXE) wm_dugad_e$(EXE) wm_dugad_d$(EXE) cmp_dugad_sig$(EXE)
+
+
+
+clean:	coxclean bruynclean kochclean corviclean xiaclean zhuclean xieclean \
+	dugadclean kimclean wangclean frid2clean toolsclean libraryclean waveletclean
+	$(RM) *$(O) *.ps ../sigs/* ../wms/* ../watermarked/* 
+	
+
+man:	coxman bruynman kochman corviman xiaman xieman toolsman
+
+test:	coxtest bruyntest kochtest corvitest xiatest xietest dugadtest zhutest \
+	wangtest frid2test kimtest toolstest
+
+install: coxinstall bruyninstall kochinstall corviinstall xiainstall xieinstall \
+	dugadinstall zhuinstall wanginstall frid2install kiminstall toolsinstall
+
+depend:
+	$(MAKEDEP) *.h *.c
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Meerwald/README	Sun Aug 12 13:14:34 2007 +0200
@@ -0,0 +1,157 @@
+This package provides source code for some watermarking algorithms in portable
+C code. Currently it includes the following
+
+  watermarking algorithms
+
+    Bruyndonckx
+      refer to
+        O. Bruyndonckx, Jean-Jacques Quisquater, and Benoit M. Macq. 
+        Spatial method for copyright labeling of digital images. 
+        In IEEE Workshop on Nonlinear Signal and Image Processing '95, 
+        Thessaloniki, Greece, pages 456 - 459, 1995. 
+
+    Corvi
+      refer to
+        Marco Corvi and Gianluca Nicchiotti. 
+        Wavelet-based image watermarking for copyright protection. 
+        In Scandinavian Conference on Image Analysis SCIA '97, Lappeenranta, 
+        Finland, June 1997. 
+
+    Cox 
+      refer to
+	Ingemar J. Cox, Joe Kilian, Tom Leighton, and Talal G. Shamoon. 
+	Secure spread spectrum watermarking for multimedia. 
+	In Proceedings of the IEEE ICIP '97, 
+	volume 6, pages 1673 - 1687, Santa Barbara, California, USA, 1997. 
+
+    Dugad
+      refer to
+        Rakesh Dugad, Krishna Ratakonda, and Narendra Ahuja.
+        A new wavelet-based scheme for watermarking images. In Proceedings of
+        the IEEE International Conference on Image Processing, ICIP '98,
+        Chicago, IL, USA, October 1998.
+
+    Fridrich (2. scheme)
+      refer to
+        Jiri Fridrich.
+        Combining low-frequency and spread spectrum watermarking. In
+        Proceedings of the SPIE Symposium on Optical Science, Engineering and
+        Instrumentation, San Diego, USA, July 1998.
+
+    Koch
+      refer to
+        Eckhard Koch and Jian Zhao. 
+        Towards robust and hidden image copyright labeling. 
+        In Proceedings of the IEEE International Workshop on Nonlinear 
+        Signal and Image Processing, pages 452 - 455, Halkidiki, Marmaras, 
+        Greece, June 1995. 
+
+    Kim
+      refer to
+        Jong Ryul Kim and Young Shik Moon. 
+        A robust wavelet-based digital watermark using level-adaptive
+        thresholding. In Proceedings of the 6th IEEE International
+        Conference on Image Processing ICIP '99, page 202,
+        Kobe, Japan, October 1999. 
+
+    Wang
+      refer to
+        Houng-Jyh Wang, Po-Chyi Su, and C.-C. Jay Kuo.
+        Wavelet-based digital image watermarking. Optics Express, 3
+        pp. 497, December 1998.
+
+    Xia
+      refer to
+        Xiang-Gen Xia, Charles G. Boncelet, and Gonzalo R. Arce. 
+        Wavelet transform based watermark for digital images. Optics Express, 3
+        pp. 497, December 1998. 
+
+    Xie
+      refer to
+        Liehua Xie and Gonzalo R. Arce. 
+        Joint wavelet compression and authentication watermarking. In 
+        Proceedings of the IEEE International Conference on Image Processing, 
+        ICIP '98, Chicago, IL, USA, 1998. 
+
+    Zhu
+      refer to
+       Wenwu Zhu, Zixiang Xiong, and Ya-Qin Zhang.
+       Multiresolution watermarking for images and video: a unified approach.
+       In Proceedings of the IEEE International Conference o
+
+    many more algorithms to come! 
+    see what is in stock: http://www.cosy.sbg.ac.at/~pmeerw/Watermarking
+
+  and utility programs
+
+    cmp_pgm	- compute difference image, PSNR, ...
+    cmp_dct	- compute full-frame DCT domain difference image
+    cmp_dct8x8  - compute 8x8 block-based DCT difference image
+    cmp_dwt     - compute DWT domain difference image
+
+What do I need?
+
+Unix (Linux), a reasonable C compiler (GCC), and the netpbm library which you 
+can get at http://wuarchive.wustl.edu/graphics/graphics/packages/NetPBM/
+
+
+Directions: How do I use the stuff?
+
+look at the MAKEFILE...
+each algorithms has at least 4 files: gen_algo_sig.c, wm_algo_e.c, wm_algo_d.c,
+cmp_algo_sig.c where 'algo' is the name of the actual watermarking algorithm 
+(usually the principal author's name), where might also be some common files 
+for each algorithm, algo_common.{c|h}, and some support files for sorting,
+the DCT, ...
+
+just try
+  
+  make
+  make test
+
+next, try to run each program with the -h parameter to find out what options 
+are supported - the programs are pretty consistent and have reasonable
+default settings
+
+e.g. 
+
+  wm_cox_e -h
+
+The programs all support standard input and standard output, the only
+supported image file format is PGM for grayscale images and PPM for color
+images; most programs have only been tested with 512x512 images.
+You can find the Lena image in PGM format in the images/ sub-directory.
+
+
+Disclaimer: #include <disclaimer.h>
+
+Feel free to use the accompaigning code for your research! However, I do
+not guarantee for anything, in particular parts of the provided code may
+be covered by copyrights of a third party or by patent claims. I do not
+guarantee for any functionality, bla-bla, ...
+
+If you use the accompanying code, please cite my thesis:
+
+  Peter Meerwald, Digital Image Watermarking in the Wavelet Transform Domain, 
+  Master's Thesis, Department of Scientific Computing, University of Salzburg,
+  Austria, January 2001.
+
+
+Contact: Comments are welcome!
+
+More algorithms will be added over time, I have implemented about 13
+watermarking algorithms in the spatial-, DCT-, and wavelet domain so far.
+Please report what problems you have, suggestions, ...
+
+Peter Meerwald
+
+Dept. of Scientific Computing
+University of Salzburg
+Jakob-Haringer-Str. 2
+A-5020 Salzburg 
+AUSTRIA
+
+pmeerw@cosy.sbg.ac.at
+http://www.cosy.sbg.ac.at/~pmeerw/Watermarking
+
++43-662-8044-6327
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Meerwald/bruyn_common.c	Sun Aug 12 13:14:34 2007 +0200
@@ -0,0 +1,44 @@
+#include "bruyn_common.h"
+
+gray lookup_pattern(int pattern, int c, int r) {
+#define A CATEGORY_A
+#define B CATEGORY_B
+
+  gray pattern1[4][4] =
+    {{A, A, B, B},
+     {A, A, B, B},
+     {B, B, A, A},
+     {B, B, A, A}};
+
+  gray pattern2[8][8] =
+    {{B, B, B, B, A, A, A, A},
+     {B, B, B, B, A, A, A, A},
+     {B, B, B, B, A, A, A, A},
+     {B, B, B, B, A, A, A, A},
+     {A, A, A, A, B, B, B, B},
+     {A, A, A, A, B, B, B, B},
+     {A, A, A, A, B, B, B, B},
+     {A, A, A, A, B, B, B, B}};
+
+  gray pattern3[2][2] =
+    {{A, B}, {B, A}};
+
+#undef A
+#undef B
+
+  switch (pattern) {
+    case 1:
+      return pattern1[r % 4][c % 4];
+      break;
+    case 2:
+      return pattern2[r % 8][c % 8];
+      break;
+    case 3:
+      return pattern3[r % 2][c % 2];
+      break;
+  }
+
+  return CATEGORY_VOID;
+}
+
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Meerwald/bruyn_common.h	Sun Aug 12 13:14:34 2007 +0200
@@ -0,0 +1,41 @@
+#ifndef BRUYN_COMMON_H
+#define BRUYN_COMMON_H
+
+#include "pgm.h"
+
+// for block type classification
+#define BLOCKTYPE_UNKNOWN 0
+#define BLOCKTYPE_HARD 1
+#define BLOCKTYPE_PROGRESSIVE 2
+#define BLOCKTYPE_NOISE 3
+
+// thresholds
+#define THRESHOLD_NOISE 10.0
+#define THRESHOLD_SLOPE 5.0
+#define THRESHOLD_NOISE_USAGE "10.0"
+#define THRESHOLD_SLOPE_USAGE "5.0"
+
+// zone classification
+#define ZONE_VOID 0
+#define ZONE_1 1
+#define ZONE_2 2
+
+// category classification
+#define CATEGORY_VOID 0
+#define CATEGORY_A 4
+#define CATEGORY_B 8
+
+// classifiction = zone | category
+#define CLASSIFICATION_1A (ZONE_1 | CATEGORY_A)
+#define CLASSIFICATION_1B (ZONE_1 | CATEGORY_B)
+#define CLASSIFICATION_2A (ZONE_2 | CATEGORY_A)
+#define CLASSIFICATION_2B (ZONE_2 | CATEGORY_B)
+#define CLASSIFICATION_A CATEGORY_A
+#define CLASSIFICATION_B CATEGORY_B
+
+#define NPATTERN 3
+#define NPATTERN_USAGE "3"
+
+gray lookup_pattern(int pattern, int c, int r);
+
+#endif BRUYN_COMMON_H
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Meerwald/cmp_bruyn_sig.c	Sun Aug 12 13:14:34 2007 +0200
@@ -0,0 +1,150 @@
+#include "wm.h"
+#include "signature.h"
+
+char *progname;
+
+void usage(void) {
+  fprintf(stderr, "usage: %s [-h] [-C] [-o file] [-v n] -s file file\n\n", progname);
+  fprintf(stderr, "\t-C\t\toutput correlation only\n");
+  fprintf(stderr, "\t-h\t\tprint usage\n");
+  fprintf(stderr, "\t-o file\t\toutput file\n");
+  fprintf(stderr, "\t-s file\t\toriginal signature file\n");
+  fprintf(stderr, "\t-v n\t\tverbosity level\n");
+  exit(0);
+}
+
+int main(int argc, char *argv[]) {
+
+  FILE *in = stdin;
+  FILE *out = stdout;
+  FILE *sig = NULL;
+
+  char signature_name[MAXPATHLEN];
+  char output_name[MAXPATHLEN] = "(stdout)";
+  char input_name[MAXPATHLEN] = "(stdin)";
+
+  int c, i;
+  int pattern1, pattern2;
+  double quality;
+  double threshold1, threshold2;
+  int blocksize;
+  int corr = 0, match = 0;
+  int verbose = 0;
+  int skipping = 0;
+
+  int correlation_only = 0;
+
+  int seed;
+  char line[32];
+
+  progname = argv[0];
+
+  while ((c = getopt(argc, argv, "h?Co:s:v:")) != EOF) {
+    switch (c) {
+      case 'h':
+      case '?':
+        usage();
+        break; 
+      case 'C':
+        correlation_only = 1;
+        break;
+      case 'o':
+        if ((out = fopen(optarg, "w")) == NULL) {
+          fprintf(stderr, "%s: unable to open output file %s\n", progname, optarg);
+          exit(1);
+        }
+        strcpy(output_name, optarg);
+        break;
+      case 's':
+        if ((sig = fopen(optarg, "r")) == NULL) {
+          fprintf(stderr, "%s: unable to open signature file %s\n", progname, optarg);
+          exit(1);
+        }
+        strcpy(signature_name, optarg);
+        break;
+     case 'v':
+        verbose = atoi(optarg);
+        if (verbose < 0) {
+          fprintf(stderr, "%s: verbosity level %d out of range\n", progname, verbose);
+          exit(1);
+        }
+        break;
+    }
+  }
+
+  argc -= optind;
+  argv += optind;
+
+  if (argc > 1) {
+    usage();
+    exit(1);
+  }
+
+  if (argc == 1 && *argv[0] != '-')
+    if ((in = fopen(argv[0], "r")) == NULL) {
+      fprintf(stderr, "%s: unable to open input file %s\n", progname, argv[0]);
+      exit(1);
+    }
+    else
+      strcpy(input_name, argv[0]);
+
+  if (sig) {
+    fgets(line, sizeof(line), sig);
+    if (strspn(line, "BRSG") >= 4) {
+      fscanf(sig, "%d\n", &nbit_signature1);
+      fscanf(sig, "%d\n", &skipping);
+      fscanf(sig, "%d\n", &pattern1);
+      fscanf(sig, "%d\n", &pattern2);
+      fscanf(sig, "%lf\n", &quality);
+      fscanf(sig, "%lf\n", &threshold1);
+      fscanf(sig, "%lf\n", &threshold2);
+      fscanf(sig, "%d\n", &blocksize);
+      fscanf(sig, "%d\n", &seed);
+      srandom(seed);
+      n_signature1 = NBITSTOBYTES(nbit_signature1);
+      fread(signature1, sizeof(char), n_signature1, sig);
+      fscanf(sig, "\n");
+    }
+    else {
+      fprintf(stderr, "%s: invalid signature file %s\n", progname, signature_name);
+      exit(1);
+    }
+    close(sig);
+  }
+  else {
+    fprintf(stderr, "%s: original signature file not specified, use -s file option\n", progname);
+    exit(1);
+  }
+
+  fgets(line, sizeof(line), in);
+  if (strspn(line, "BRWM") >= 4) {
+    fscanf(in, "%d\n", &nbit_signature2);
+    n_signature2 = NBITSTOBYTES(nbit_signature2);
+    fread(signature2, sizeof(char), n_signature2, in);
+    fscanf(in, "\n");    
+  }
+  else {
+    fprintf(stderr, "%s: invalid watermark file %s\n", progname, input_name);
+    exit(1);
+  }
+
+  if (verbose > 0) {
+    fprintf(stderr, "signature length: %d\n", nbit_signature1);
+    fprintf(stderr, "watermark length: %d\n", nbit_signature2);
+  }
+
+  for (i = 0; i < nbit_signature2; i++)
+    if (get_signature1_bit(i % nbit_signature1) == get_signature2_bit(i))
+      corr++, match++;
+    else
+      corr--;
+
+  if (correlation_only)
+    fprintf(out, "%lf\n", (double) corr / nbit_signature2);
+  else {
+    fprintf(out, "bit matches: %d/%d\n", match, nbit_signature2);
+    fprintf(out, "correlation: %lf\n", (double) corr / nbit_signature2);
+  }
+
+  exit(0);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Meerwald/cmp_corvi_sig.c	Sun Aug 12 13:14:34 2007 +0200
@@ -0,0 +1,159 @@
+#include "wm.h"
+
+char *progname;
+
+void usage(void) {
+  fprintf(stderr, "usage: %s [-h] [-C] [-o file] [-v n] -s file file\n\n", progname);
+  fprintf(stderr, "\t-C\t\toutput correlation only\n");
+  fprintf(stderr, "\t-h\t\tprint usage\n");
+  fprintf(stderr, "\t-o file\t\toutput file\n");
+  fprintf(stderr, "\t-v n\t\tverbosity level\n");
+  fprintf(stderr, "\t-s file\t\toriginal signature file\n");
+  exit(0);
+}
+
+int main(int argc, char *argv[]) {
+
+  FILE *in = stdin;
+  FILE *out = stdout;
+  FILE *sig = NULL;
+
+  char signature_name[MAXPATHLEN];
+  char output_name[MAXPATHLEN] = "(stdout)";
+  char input_name[MAXPATHLEN] = "(stdin)";
+
+  int c;
+  int sig_n, in_n;
+  double s1, s2, s3;
+  char line[32];
+  int matches;
+
+  int verbose = 0;
+  int correlation_only = 0;
+
+  progname = argv[0];
+
+  while ((c = getopt(argc, argv, "h?o:s:v:C")) != EOF) {
+    switch (c) {
+      case 'h':
+      case '?':
+        usage();
+        break;
+      case 'o':
+        if ((out = fopen(optarg, "w")) == NULL) {
+          fprintf(stderr, "%s: unable to open output file %s\n", progname, optarg);
+          exit(1);
+        }
+        strcpy(output_name, optarg);
+        break;
+      case 's':
+        if ((sig = fopen(optarg, "r")) == NULL) {
+          fprintf(stderr, "%s: unable to open signature file %s\n", progname, optarg);
+          exit(1);
+        }
+        strcpy(signature_name, optarg);
+        break;
+     case 'v':
+        verbose = atoi(optarg);
+        if (verbose < 0) {
+          fprintf(stderr, "%s: verbosity level %d out of range\n", progname, verbose);
+          exit(1);
+        }
+        break;
+     case 'C':
+        correlation_only = 1;
+        break;
+    }
+  }
+
+  argc -= optind;
+  argv += optind;
+
+  if (argc > 1) {
+    usage();
+    exit(1);
+  }
+
+  if (argc == 1 && *argv[0] != '-')
+    if ((in = fopen(argv[0], "r")) == NULL) {
+      fprintf(stderr, "%s: unable to open input file %s\n", progname, argv[0]);
+      exit(1);
+    }
+    else
+      strcpy(input_name, argv[0]);
+
+  if (!sig) {
+    fprintf(stderr, "%s: original signature file not specified, use -s file option\n", progname);
+    exit(1);
+  }
+
+  fgets(line, sizeof(line), sig);
+  if (strspn(line, "CVSG") < 4) {
+    fprintf(stderr, "%s: original signature file %s invalid\n", progname, signature_name);
+    exit(1);
+  }
+
+  fgets(line, sizeof(line), in);
+  if (strspn(line, "CVWM") < 4) {
+    fprintf(stderr, "%s: signature file %s invalid\n", progname, input_name);
+    exit(1);
+  }
+
+  fscanf(sig, "%d\n", &sig_n);
+  fscanf(in, "%d\n", &in_n);
+  if (sig_n != in_n) {
+    fprintf(stderr, "%s: watermark length mismatch (original %d, input %d)\n", progname, sig_n, in_n);
+    exit(1);
+  }
+  if (sig_n <= 0 || sig_n > 1000) {
+    fprintf(stderr, "%s: invalid original watermark length %d\n", progname, sig_n);
+    exit(1);
+  }
+  if (in_n <= 0 || in_n > 1000) {
+    fprintf(stderr, "%s: invalid watermark length %d\n", progname, in_n);
+    exit(1);
+  }
+
+  fscanf(sig, "%*lf\n");
+  fscanf(sig, "%*d\n");
+  fscanf(sig, "%*d\n");
+  fscanf(sig, "%*[^\n\r]\n");
+
+  /*
+   * normalized correlation
+   * Craver, S., "Can Invisible Watermarks Resolve Rightful Ownership?", IBM Research Report, 1996, p. 5
+   */
+
+  s1 = s2 = s3 = 0.0;
+  matches = 0;
+  while (in_n > 0) {
+    double sig_x, in_x;
+
+    fscanf(sig, "%lf\n", &sig_x);
+    fscanf(in, "%lf\n", &in_x);
+
+    matches += SIGN(sig_x * in_x);
+
+    if (verbose >= 1) {
+      fprintf(stderr, "orig %f input %f\n", sig_x, in_x);
+    }
+
+    s1 += sig_x * in_x;
+    s2 += in_x * in_x;
+    s3 += sig_x * sig_x;
+
+    in_n--;
+  }
+
+  if (!correlation_only) {
+    fprintf(out, "%s: correlation %f, hamming distance %f\n", progname, s1 / sqrt(s2 * s3), (double) matches / sig_n);
+  }
+  else
+    fprintf(out, "%f\n", (double) matches / sig_n);
+
+  fclose(sig);
+  fclose(out);
+  fclose(in);
+
+  exit(0);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Meerwald/cmp_cox_sig.c	Sun Aug 12 13:14:34 2007 +0200
@@ -0,0 +1,153 @@
+#include "wm.h"
+
+char *progname;
+
+void usage(void) {
+  fprintf(stderr, "usage: %s [-h] [-C] [-o file] [-v n] -s file file\n\n", progname);
+  fprintf(stderr, "\t-C\t\toutput correlation only\n");
+  fprintf(stderr, "\t-h\t\tprint usage\n");
+  fprintf(stderr, "\t-o file\t\toutput file\n");
+  fprintf(stderr, "\t-s file\t\toriginal signature file\n");
+  fprintf(stderr, "\t-v n\t\tverbosity level\n");
+  exit(0);
+}
+
+int main(int argc, char *argv[]) {
+
+  FILE *in = stdin;
+  FILE *out = stdout;
+  FILE *sig = NULL;
+
+  char signature_name[MAXPATHLEN];
+  char output_name[MAXPATHLEN] = "(stdout)";
+  char input_name[MAXPATHLEN] = "(stdin)";
+
+  int c;
+  int sig_n, in_n;
+  double sig_a, in_a;
+  double sig_mean, sig_variance;
+  double s1, s2, s3;
+  char line[32];
+ 
+  int verbose = 0;
+  int correlation_only = 0;
+
+  progname = argv[0];
+
+  while ((c = getopt(argc, argv, "h?Co:s:v:")) != EOF) {
+    switch (c) {
+      case 'h':
+      case '?':
+        usage();
+        break;
+      case 'C':
+        correlation_only = 1;
+        break;
+      case 'o':
+        if ((out = fopen(optarg, "w")) == NULL) {
+          fprintf(stderr, "%s: unable to open output file %s\n", progname, optarg);
+          exit(1);
+        }
+        strcpy(output_name, optarg);
+        break;
+      case 's':
+        if ((sig = fopen(optarg, "r")) == NULL) {
+          fprintf(stderr, "%s: unable to open signature file %s\n", progname, optarg);
+          exit(1);
+        }
+        strcpy(signature_name, optarg);
+        break;
+     case 'v':
+        verbose = atoi(optarg);
+        if (verbose < 0) {
+          fprintf(stderr, "%s: verbosity level %d out of range\n", progname, verbose);
+          exit(1);
+        }
+        break;
+    }
+  }
+
+  argc -= optind;
+  argv += optind;
+
+  if (argc > 1) {
+    usage();
+    exit(1);
+  }
+
+  if (argc == 1 && *argv[0] != '-')
+    if ((in = fopen(argv[0], "r")) == NULL) {
+      fprintf(stderr, "%s: unable to open input file %s\n", progname, argv[0]);
+      exit(1);
+    }
+    else
+      strcpy(input_name, argv[0]);
+
+  if (!sig) {
+    fprintf(stderr, "%s: original signature file not specified, use -s file option\n", progname);
+    exit(1);
+  }
+
+  fgets(line, sizeof(line), sig);
+  if (strspn(line, "CXSG") < 4) {
+    fprintf(stderr, "%s: original signature file %s invalid\n", progname, signature_name);
+    exit(1);
+  }
+
+  fgets(line, sizeof(line), in);
+  if (strspn(line, "CXWM") < 4) {
+    fprintf(stderr, "%s: watermark file %s invalid\n", progname, input_name);
+    exit(1);
+  }
+
+  fscanf(sig, "%d\n", &sig_n);
+  fscanf(in, "%d\n", &in_n);
+  if (sig_n != in_n) {
+    fprintf(stderr, "%s: watermark length mismatch (original %d, input %d)\n", progname, sig_n, in_n);
+    exit(1);
+  }
+  if (sig_n <= 0 || sig_n > 32000) {
+    fprintf(stderr, "%s: invalid original watermark length %d\n", progname, sig_n);
+    exit(1);
+  }
+  if (in_n <= 0 || in_n > 32000) {
+    fprintf(stderr, "%s: invalid watermark length %d\n", progname, in_n);
+    exit(1);
+  }
+
+  fscanf(sig, "%lf\n", &sig_a);
+
+  fscanf(sig, "%lf\n", &sig_mean);
+  fscanf(sig, "%lf\n", &sig_variance);
+
+  /*
+   * normalized correlation
+   * Craver, S., "Can Invisible Watermarks Resolve Rightful Ownership?", IBM Research Report, 1996, p. 5
+   */
+
+  s1 = s2 = s3 = 0.0;
+  while (in_n > 0) {
+    double sig_x, in_x;
+
+    fscanf(sig, "%lf\n", &sig_x);
+    fscanf(in, "%lf\n", &in_x);
+
+    if (verbose >= 1) {
+      fprintf(stderr, "orig %f input %f\n", sig_x, in_x);  
+    }
+
+    s1 += sig_x * in_x;
+    s2 += in_x * in_x;
+    s3 += sig_x * sig_x;
+
+    in_n--;
+  }
+
+  fprintf(out, "%f\n", s1 / sqrt(s2 * s3));
+
+  fclose(sig);
+  fclose(out);
+  fclose(in);
+
+  exit(0);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Meerwald/cmp_dct.1	Sun Aug 12 13:14:34 2007 +0200
@@ -0,0 +1,79 @@
+.\"
+.\" cmp_dct.1 - the *roff document processor man page source
+.\"
+.TH cmp_dct 1 "98/07/08" "Watermarking, Version 1.0"
+.SH NAME
+cmp_dct \- a program to create the difference image of the
+frequency domain of two PGM images
+.SH SYNOPSIS
+.B cmp_dct
+[
+.B \-h
+]
+[
+.BI \-m \ number
+]
+[
+.BI \-o \ ofile
+]
+.BI \-i \ ifile
+.I file
+.SH DESCRIPTION
+.B cmp_dct
+is a program to create the difference image of the
+frequency domain of two PGM (portable graymap) grayscale
+images. To compare images in the spatial domain, either in
+PPM (portable pixmap) format for RGB color images or in PGM (portable
+graymap) format for grayscale images, use the
+.B cmp_ppm
+program or the
+.B cmp_pgm
+program, respectively.
+.PP
+If
+.I file
+or
+.I ofile
+is not specified, then standard input or standard output is
+used.
+.PP
+.SH OPTIONS
+.TP
+.B \-h
+Print a help message.
+.TP
+.BI \-i \ ifile
+The original image. Mandatory.
+.TP
+.BI \-m \ number
+Multiplication factor to magnify differences between the to
+original and input image.
+Default value: 16.
+.TP
+.BI \-o \ ofile
+Output image file to contain the difference image in PGM format.
+.TP
+.I file
+Input image that is compared against
+.I ifile.
+Default: standard input.
+.SH OUTPUT
+The difference image in PGM format is written to standard output or,
+optionally, to
+.I ofile.
+.SH AUTHOR
+Peter Meerwald.
+Email bug reports to pmeerw@cosy.sbg.ac.at.
+.SH AVAILABILITY
+The most recent released version of
+.B cmp_dct
+is always available
+at http://www.cosy.sbg.ac.at/~pmeerw/Watermarking or via anonymous ftp from ftp.cosy.sbg.ac.at in the
+directory /pub/people/pmeerw/Watermarking.
+.SH "SEE ALSO"
+.B cmp_pgm
+(1),
+.B cmp_ppm
+(1),
+.B cmp_dct8x8
+(1)
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Meerwald/cmp_dct.c	Sun Aug 12 13:14:34 2007 +0200
@@ -0,0 +1,197 @@
+#include "wm.h"
+#include "dct.h"
+#include "gray.h"
+#include "pgm.h"
+
+char *progname;
+
+void usage(void) {
+  fprintf(stderr, "usage: %s [-h] [-m n] [-o file] [-pP] -i file file\n\n", progname);
+  fprintf(stderr, "\t-h\t\tprint usage\n");
+  fprintf(stderr, "\t-i file\t\toriginal image file\n");
+  fprintf(stderr, "\t-m n\t\tmultiplication factor (default 16)\n");
+  fprintf(stderr, "\t-o file\t\toutput file\n");
+  fprintf(stderr, "\t-p\t\tprint PSNR, RMS and MSE\n");
+  fprintf(stderr, "\t-P\t\tonly print PSNR, RMS and MSE, no difference image\n");
+  exit(0);
+}
+
+int main(int argc, char *argv[]) {
+
+  FILE *in = stdin;
+  FILE *out = stdout;
+  FILE *orig = NULL;
+
+  gray **input_image;
+  gray **orig_image;
+  double **input_dcts;
+  double **orig_dcts;
+  gray **output;
+
+  char output_name[MAXPATHLEN] = "(stdout)";
+  char input_name[MAXPATHLEN] = "(stdin)";
+  char orig_name[MAXPATHLEN];
+
+  int in_cols, in_rows, in_format;
+  gray in_maxval;
+  int orig_cols, orig_rows, orig_format;
+  gray orig_maxval;
+  int cols, rows, format;
+  gray maxval;
+  int col, row;
+
+  int no_orig = 0;
+  int c;
+
+  double error = 0.0;
+  int print_psnr = 0;
+  int print_psnr_only = 0;
+  int m = 16;
+
+  progname = argv[0];
+
+  pgm_init(&argc, argv); wm_init();
+
+  while ((c = getopt(argc, argv, "h?i:m:o:pP")) != EOF) {
+    switch (c) {
+      case 'h':
+      case '?':
+        usage();
+        break;
+      case 'i':
+        if (!strcmp(optarg, "-")) {
+          no_orig = 1;
+          strcpy(orig_name, "(zero)");
+        }
+        else {
+          if ((orig = fopen(optarg, "rb")) == NULL) {
+            fprintf(stderr, "%s: unable to open original image file %s\n", progname, optarg);
+            exit(1);
+          }
+          strcpy(orig_name, optarg);
+        }
+        break;
+      case 'm':
+        m = atoi(optarg);
+        if (m <= 0) {
+          fprintf(stderr, "%s: multiplication factor %d out of range\n", progname, m);
+          exit(1);
+        }
+        break;
+      case 'o':
+        if ((out = fopen(optarg, "wb")) == NULL) {
+          fprintf(stderr, "%s: unable to open output file %s\n", progname, optarg);
+          exit(1);
+        }
+        strcpy(output_name, optarg);
+        break;
+      case 'p':
+        print_psnr = 1;
+        break;
+      case 'P':
+        print_psnr_only = 1;
+        break;
+    }
+  }
+
+  argc -= optind;
+  argv += optind;
+
+  if (argc > 1) {
+    usage();
+    exit(1);
+  }
+
+  if (argc == 1 && *argv[0] != '-')
+    if ((in = fopen(argv[0], "rb")) == NULL) {
+      fprintf(stderr, "%s: unable to open input file %s\n", progname, argv[0]);
+      exit(1);
+    }
+    else
+      strcpy(input_name, argv[0]);
+
+  if (!orig && !no_orig) {
+    fprintf(stderr, "%s: original image file not specified, using zero image\n", progname);
+    strcpy(orig_name, "(zero)");
+    no_orig = 1;
+  }
+
+  pgm_readpgminit(in, &in_cols, &in_rows, &in_maxval, &in_format);
+
+  if (!no_orig) {
+    pgm_readpgminit(orig, &orig_cols, &orig_rows, &orig_maxval, &orig_format);
+
+    if (in_cols != orig_cols || in_rows != orig_rows) {
+      fprintf(stderr, "%s: input image %s does not match dimensions of original image %s\n", progname, input_name, orig_name);
+      exit(1);
+    }
+  }
+
+  cols = in_cols;
+  rows = in_rows;
+  format = in_format;
+  maxval = in_maxval;
+
+  input_image = pgm_allocarray(cols, rows);
+  orig_image = pgm_allocarray(cols, rows);
+
+  init_dct_NxN(cols, rows);
+  input_dcts = alloc_coeffs(cols, rows);
+  orig_dcts = alloc_coeffs(cols, rows);
+  output = alloc_grays(cols, rows);
+
+  if (no_orig) {
+    for (row = 0; row < rows; row++) {
+      pgm_readpgmrow(in, input_image[row], cols, maxval, format);
+      bzero(orig_image[row], sizeof(gray) * cols);
+    }
+  }
+  else {
+    for (row = 0; row < rows; row++) {
+      pgm_readpgmrow(in, input_image[row], cols, maxval, format);
+      pgm_readpgmrow(orig, orig_image[row], cols, maxval, format);
+    }
+  }
+
+  fclose(in);
+  if (!no_orig)
+    fclose(orig);
+
+  fdct_NxN(input_image, input_dcts);
+  fdct_NxN(orig_image, orig_dcts);
+
+  for (row = 0; row < rows; row++)
+    for (col = 0; col < cols; col++) {
+      error += sqr(input_dcts[row][col] - orig_dcts[row][col]);
+      output[row][col] = PIXELRANGE(fabs(input_dcts[row][col] - orig_dcts[row][col]) * m);
+    }
+
+  if (!print_psnr_only) {
+    pgm_writepgminit(out, cols, rows, maxval, 0);
+    for (row = 0; row < rows; row++)
+      pgm_writepgmrow(out, output[row], cols, maxval, 0);
+
+    fclose(out);
+  }
+
+  pgm_freearray(input_image, rows);
+  pgm_freearray(orig_image, rows);
+  free_coeffs(input_dcts);
+  free_coeffs(orig_dcts);
+  free_grays(output);
+
+  if (print_psnr || print_psnr_only) {
+    double mse = error / (double) (cols * rows);
+    double rmse = sqrt(mse);
+    double psnr = 20.0 * log(255.0 / rmse) / log(10.0);
+    FILE *print = print_psnr_only ? out : stderr;
+    if (mse > 0.0)
+      fprintf(print, "PSNR: %lf dB\n", psnr);
+    else
+      fprintf(print, "PSNR: inf\n");
+    fprintf(print, "RMS: %lf\n", rmse);
+    fprintf(print, "MSE: %lf\n", mse);
+  }
+
+  exit(0);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Meerwald/cmp_dct8x8.1	Sun Aug 12 13:14:34 2007 +0200
@@ -0,0 +1,79 @@
+.\"
+.\" cmp_dct8x8.1 - the *roff document processor man page source
+.\"
+.TH cmp_dct8x8 1 "98/07/08" "Watermarking, Version 1.0"
+.SH NAME
+cmp_dct8x8 \- a program to create the difference image of the
+8x8 DCT blocks of two PGM images
+.SH SYNOPSIS
+.B cmp_dct8x8
+[
+.B \-h
+]
+[
+.BI \-m \ number
+]
+[
+.BI \-o \ ofile
+]
+.BI \-i \ ifile
+.I file
+.SH DESCRIPTION
+.B cmp_dct8x8
+is a program to create the difference image of the 8x8 DCT blocks
+(frequency domain) of two PGM (portable graymap) grayscale
+images. To compare images in the spatial domain, either in
+PPM (portable pixmap) format for RGB color images or in PGM (portable
+graymap) format for grayscale images, use the
+.B cmp_ppm
+program or the
+.B cmp_pgm
+program, respectively.
+.PP
+If
+.I file
+or
+.I ofile
+is not specified, then standard input or standard output is
+used.
+.PP
+.SH OPTIONS
+.TP
+.B \-h
+Print a help message.
+.TP
+.BI \-i \ ifile
+The original image. Mandatory.
+.TP
+.BI \-m \ number
+Multiplication factor to magnify differences between the to
+original and input image.
+Default value: 16.
+.TP
+.BI \-o \ ofile
+Output image file to contain the difference image in PGM format.
+.TP
+.I file
+Input image that is compared against
+.I ifile.
+Default: standard input.
+.SH OUTPUT
+The difference image in PGM format is written to standard output or,
+optionally, to
+.I ofile.
+.SH AUTHOR
+Peter Meerwald. 
+Email bug reports to pmeerw@cosy.sbg.ac.at.
+.SH AVAILABILITY
+The most recent released version of
+.B cmp_dct8x8
+is always available
+at http://www.cosy.sbg.ac.at/~pmeerw/Watermarking or via anonymous ftp from ftp.cosy.sbg.ac.at in the
+directory /pub/people/pmeerw/Watermarking.
+.SH "SEE ALSO"
+.B cmp_pgm
+(1),
+.B cmp_ppm
+(1),
+.B cmp_dct
+(1)
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Meerwald/cmp_dct8x8.c	Sun Aug 12 13:14:34 2007 +0200
@@ -0,0 +1,196 @@
+#include "wm.h"
+#include "dct.h"
+#include "gray.h"
+#include "pgm.h"
+
+char *progname;
+
+void usage(void) {
+  fprintf(stderr, "usage: %s [-h] [-m n] [-o file] [-pP] -i file file\n\n", progname);
+  fprintf(stderr, "\t-h\t\tprint usage\n");
+  fprintf(stderr, "\t-i file\t\toriginal image file\n");
+  fprintf(stderr, "\t-m n\t\tmultiplication factor (default 16)\n");
+  fprintf(stderr, "\t-o file\t\toutput file\n");
+  fprintf(stderr, "\t-p\t\tprint PSNR, RMS and MSE\n");
+  fprintf(stderr, "\t-P\t\tonly print PSNR, RMS and MSE, no difference image\n");
+  exit(0);
+}
+
+int main(int argc, char *argv[]) {
+
+  FILE *in = stdin;
+  FILE *out = stdout;
+  FILE *orig = NULL;
+
+  gray **input_image;
+  gray **orig_image;
+  double **input_dcts;
+  double **orig_dcts;
+  gray **output;
+
+  char output_name[MAXPATHLEN] = "(stdout)";
+  char input_name[MAXPATHLEN] = "(stdin)";
+  char orig_name[MAXPATHLEN];
+
+  int in_cols, in_rows, in_format;
+  gray in_maxval;
+  int orig_cols, orig_rows, orig_format;
+  gray orig_maxval;
+  int cols, rows, format;
+  gray maxval;
+  int col, row;
+
+  int i, j;
+  int c;
+
+  int m = 16;
+
+  int print_psnr = 0;
+  int print_psnr_only = 0;
+  double error = 0.0;
+
+  progname = argv[0];
+
+  pgm_init(&argc, argv); wm_init();
+
+  while ((c = getopt(argc, argv, "h?i:m:o:pP")) != EOF) {
+    switch (c) {
+      case 'h':
+      case '?':
+        usage();
+        break;
+      case 'i':
+        if ((orig = fopen(optarg, "rb")) == NULL) {
+          fprintf(stderr, "%s: unable to open original image file %s\n", progname, optarg);
+          exit(1);
+        }
+        strcpy(orig_name, optarg);
+        break;
+      case 'm':
+        m = atoi(optarg);
+        if (m <= 0) {
+          fprintf(stderr, "%s: multiplication factor %d out of range\n", progname, m);
+          exit(1);
+        }
+        break;
+      case 'o':
+        if ((out = fopen(optarg, "w")) == NULL) {
+          fprintf(stderr, "%s: unable to open output file %s\n", progname, optarg);
+          exit(1);
+        }
+        strcpy(output_name, optarg);
+        break;
+      case 'p':
+        print_psnr = 1;
+        break;
+      case 'P':
+        print_psnr_only = 1;
+        break;
+    }
+  }
+
+  argc -= optind;
+  argv += optind;
+
+  if (argc > 1) {
+    usage();
+    exit(1);
+  }
+
+  if (argc == 1 && *argv[0] != '-')
+    if ((in = fopen(argv[0], "rb")) == NULL) {
+      fprintf(stderr, "%s: unable to open input file %s\n", progname, argv[0]);
+      exit(1);
+    }
+    else
+      strcpy(input_name, argv[0]);
+
+  if (!orig) {
+    fprintf(stderr, "%s: original image file not specified, use -i file option\n", progname);
+    exit(1);
+  }
+
+  pgm_readpgminit(in, &in_cols, &in_rows, &in_maxval, &in_format);
+
+  pgm_readpgminit(orig, &orig_cols, &orig_rows, &orig_maxval, &orig_format);
+
+  if (in_cols != orig_cols || in_rows != orig_rows) {
+    fprintf(stderr, "%s: input image %s does not match dimensions of original image %s\n", progname, input_name, orig_name);
+    exit(1);
+  }
+
+  if (cols % NJPEG) {
+    fprintf(stderr, "%s: image width %d not a multiple of %d\n", progname, cols, NJPEG);
+    exit(1);
+  }
+
+  if (rows % NJPEG) {
+    fprintf(stderr, "%s: image height %d not a multiple of %d\n", progname, rows, NJPEG);
+    exit(1);
+  }
+
+  cols = in_cols;
+  rows = in_rows;
+  format = in_format;
+  maxval = in_maxval;
+
+  input_image = pgm_allocarray(cols, NJPEG);
+  orig_image = pgm_allocarray(cols, NJPEG);
+
+  init_dct_8x8();
+  input_dcts = alloc_coeffs_8x8();
+  orig_dcts = alloc_coeffs_8x8();
+  output = alloc_grays(cols, NJPEG);
+
+  if (!print_psnr_only)
+    pgm_writepgminit(out, cols, rows, maxval, 0);
+
+  for (row = 0; row < rows; row += NJPEG) {
+
+    for (i = 0; i < NJPEG; i++) {
+      pgm_readpgmrow(in, input_image[row % NJPEG], cols, maxval, format);
+      pgm_readpgmrow(orig, orig_image[row % NJPEG], cols, maxval, format);
+    }
+
+    for (col = 0; col < cols; col += NJPEG) {
+      fdct_block_8x8(input_image, col, 0, input_dcts);
+      fdct_block_8x8(orig_image, col, 0, orig_dcts);
+
+      for (i = 0; i < NJPEG; i++)
+        for (j = 0; j < NJPEG; j++)
+          error += sqr(input_dcts[j][i + cols] - orig_dcts[j][i + cols]);
+          output[j][i + col] = PIXELRANGE(fabs(input_dcts[j][i + cols] - orig_dcts[j][i + cols]) * m);
+    }
+
+    if (!print_psnr_only) {
+      for (i = 0; i < NJPEG; i++)
+        pgm_writepgmrow(out, output[i], cols, maxval, 0);
+    }
+
+  }
+  fclose(in);
+  fclose(orig);
+  if (!print_psnr_only)
+    fclose(out);
+
+  pgm_freearray(input_image, NJPEG);
+  pgm_freearray(orig_image, NJPEG);
+  free_coeffs(input_dcts);
+  free_coeffs(orig_dcts);
+  free_grays(output);
+
+ if (print_psnr || print_psnr_only) {
+    double mse = error / (double) (cols * rows);
+    double rmse = sqrt(mse);
+    double psnr = 20.0 * log(255.0 / rmse) / log(10.0);
+    FILE *print = print_psnr_only ? out : stderr;
+    if (mse > 0.0)
+      fprintf(print, "PSNR: %lf dB\n", psnr);
+    else
+      fprintf(print, "PSNR: inf\n");
+    fprintf(print, "RMS: %lf\n", rmse);
+    fprintf(print, "MSE: %lf\n", mse);
+  }
+
+  exit(0);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Meerwald/cmp_dugad_sig.c	Sun Aug 12 13:14:34 2007 +0200
@@ -0,0 +1,147 @@
+#include "wm.h"
+
+char *progname;
+
+void usage(void) {
+  fprintf(stderr, "usage: %s [-h] [-s file] [-C] [-o file] [-v] file\n\n", progname);
+  fprintf(stderr, "\t-C\t\toutput correlation only\n");
+  fprintf(stderr, "\t-h\t\tprint usage\n");
+  fprintf(stderr, "\t-o file\t\toutput file\n");
+  fprintf(stderr, "\t-s file\t\tignored\n");
+  exit(0);
+}
+
+int main(int argc, char *argv[]) {
+
+  FILE *in = stdin;
+  FILE *out = stdout;
+  FILE *sig = NULL;
+
+  char output_name[MAXPATHLEN] = "(stdout)";
+  char input_name[MAXPATHLEN] = "(stdin)";
+
+  int c, i, n, ok;
+  int levels;
+  double alpha;
+  double diff;
+  char line[32];
+
+  int correlation_only = 0;
+  int verbose = 0;
+  double corr;
+	
+  progname = argv[0];
+
+  while ((c = getopt(argc, argv, "h?Co:v:s:")) != EOF) {
+    switch (c) {
+      case 'h':
+      case '?':
+        usage();
+        break;
+      case 'C':
+        correlation_only = 1;
+        break;
+      case 's':
+        break;
+      case 'o':
+        if ((out = fopen(optarg, "w")) == NULL) {
+          fprintf(stderr, "%s: unable to open output file %s\n", progname, optarg);
+          exit(1);
+        }
+        strcpy(output_name, optarg);
+        break;
+      case 'v':
+        verbose = atoi(optarg);
+        if (verbose < 0) {
+          fprintf(stderr, "%s: verbosity level %d out of range\n", progname, verbose);
+          exit(1);
+        }
+        break;
+    }
+  }
+
+  argc -= optind;
+  argv += optind;
+
+  if (argc > 1) {
+    usage();
+    exit(1);
+  }
+
+  if (argc == 1 && *argv[0] != '-')
+    if ((in = fopen(argv[0], "r")) == NULL) {
+      fprintf(stderr, "%s: unable to open input file %s\n", progname, argv[0]);
+      exit(1);
+    }
+    else
+      strcpy(input_name, argv[0]);
+
+  fgets(line, sizeof(line), in);
+  if (strspn(line, "DGWM") < 4) {
+    fprintf(stderr, "%s: watermark file %s invalid\n", progname, input_name);
+    exit(1);
+  }
+
+  fscanf(in, "%d\n", &levels);
+  fscanf(in, "%lf\n", &alpha);
+
+  n = 3 * levels;
+  ok = 0;
+  diff = 0.0;
+  for (i = 0; i < levels; i++) {
+    int m;
+    double z, v;
+
+    // HL subband
+    fscanf(in, "%d %lf %lf\n", &m, &z, &v);
+    if (verbose && !correlation_only)
+      if (m)
+        fprintf(out, "%f %f\n",  z /  (double) m, (v * alpha) / (double) (1.0 * m));
+      else
+        fprintf(out, "0.0 0.0\n");
+    if (m) {
+      ok += (z > v * alpha / (double) 1.0) ? 1 : 0;
+      diff += ((z - v * alpha) / (double) (1.0 * m)); 
+    }
+    else
+      n--;
+
+    // LH subband
+    fscanf(in, "%d %lf %lf\n", &m, &z, &v);
+    if (verbose && !correlation_only)
+      if (m)
+        fprintf(out, "%f %f\n", z / (double) m, (v * alpha) / (double) (1.0 * m));
+      else
+        fprintf(out, "0.0 0.0\n");
+    if (m) {
+      ok += (z > v * alpha / (double) 1.0) ? 1 : 0;
+      diff += ((z - v * alpha) / (double) (1.0 * m)); 
+    }
+    else
+      n--;
+
+    // HH subband
+    fscanf(in, "%d %lf %lf\n", &m, &z, &v);
+    if (verbose && !correlation_only)
+      if (m)
+        fprintf(out, "%f %f\n", z / (double) m, (v * alpha) / (double) (1.0 * m));
+      else
+        fprintf(out, "0.0 0.0\n");
+ 
+    if (m) {
+      ok += (z > v * alpha / (double) 1.0) ? 1 : 0;
+      diff += ((z - v * alpha) / (double) (1.0 * m)); 
+    }
+    else
+      n--;
+  }
+
+  if (!correlation_only)
+    fprintf(out, "%d/%d, diff %f\n", ok, n, diff);
+  fprintf(out, "%f\n", (double) ok / (double) n);
+
+  fclose(out);
+  fclose(in);
+
+  exit(0);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Meerwald/cmp_dwt.c	Sun Aug 12 13:14:34 2007 +0200
@@ -0,0 +1,390 @@
+#include "wm.h"
+#include "dwt.h"
+#include "coeff.h"
+#include "gray.h"
+#include "pgm.h"
+#include "dwt_util.h"
+
+char *progname;
+
+void usage(void) {
+  fprintf(stderr, "usage: %s [-e n] [-f n] [-F file] [-h] [-l n] [-o file] [-pP] [-s name,..] -i file file\n\n", progname);
+  fprintf(stderr, "\t-e n\t\twavelet filtering method (default: 2)\n");
+  fprintf(stderr, "\t-f n\t\tfilter number (default: 2)\n");
+  fprintf(stderr, "\t-F file\t\tfilter definition file (default: filter.dat\n");
+  fprintf(stderr, "\t-h\t\tprint usage\n");
+  fprintf(stderr, "\t-i file\t\toriginal image file\n");
+  fprintf(stderr, "\t-l n\t\tmax. decomposition level (default: 0 = max)\n");
+  fprintf(stderr, "\t-m n\t\tmultiplication factor (default: 0 = auto)\n");
+  fprintf(stderr, "\t-o file\t\toutput file\n");
+  fprintf(stderr, "\t-p\t\tprint PSNR, RMS and MSE\n");
+  fprintf(stderr, "\t-P\t\tonly print PSNR, RMS and MSE, no difference image\n");
+  fprintf(stderr, "\t-q\t\tprint PSNR, RMS and MSE per subband\n");
+  fprintf(stderr, "\t-s name,...\tsubband/level (default: all subbands)\n");
+  fprintf(stderr, "\t-v n\t\tverbosity level\n");
+  exit(0);
+}
+
+void process_subband_var(gray **output, int cols, int rows, Image_tree p, Image_tree q, int type, double min, double max, gray maxval) {
+  int i;
+  int col, row, startcol, startrow;
+
+  if (!p || !q) return;
+
+  calc_subband_location(cols, rows, type, p->level, &startcol, &startrow);
+
+  for (row = 0; row < p->image->height; row++)
+    for (col = 0; col < p->image->width; col++) {
+      double diff = fabs(get_pixel(p->image, col, row) - get_pixel(q->image, col, row));
+      output[startrow + row][startcol + col] = PIXELRANGE((double) (diff - min) / (double) (max - min) * maxval);
+    }
+}
+
+void process_subband_fixed(gray **output, int cols, int rows, Image_tree p, Image_tree q, int type, double m) {
+  int i;
+  int col, row, startcol, startrow;
+
+  if (!p || !q) return;
+
+  calc_subband_location(cols, rows, type, p->level, &startcol, &startrow);
+
+  for (row = 0; row < p->image->height; row++)
+    for (col = 0; col < p->image->width; col++) {
+      double diff = fabs(get_pixel(p->image, col, row) - get_pixel(q->image, col, row));
+      output[startrow + row][startcol + col] = PIXELRANGE(diff * m);
+    }
+}
+
+void print_subband_psnr(int type, int level, double error, int cols, int rows, double min, double max, FILE *print) {
+  double mse = error / (double) (cols * rows);
+  double rmse = sqrt(mse);
+  double psnr = 20.0 * log(255.0 / rmse) / log(10.0);
+  int startcol, startrow;
+
+  calc_subband_location(cols << level, rows << level, type, level, &startcol, &startrow);
+  fprintf(print, "%s%d (%d x %d) at %d x %d\n", subband_name(type), level, cols, rows, startcol, startrow);
+  if (mse > 0.0)
+    fprintf(print, "  PSNR: %lf dB\n", psnr);
+  else
+    fprintf(print, "  PSNR: inf\n");
+  fprintf(print, "  RMS: %lf\n", rmse);
+  fprintf(print, "  MSE: %lf\n", mse);
+  fprintf(print, "  dmin, dmax: %lf, %lf\n", min, max);
+}
+
+int main(int argc, char *argv[]) {
+  FILE *in = stdin;
+  FILE *out = stdout;
+  FILE *orig = NULL;
+  FILE *print;
+
+  gray **input_image;
+  gray **orig_image;
+  Image_tree input_dwts, p;
+  Image_tree orig_dwts, q;
+  gray **output;
+
+  char output_name[MAXPATHLEN] = "(stdout)";
+  char input_name[MAXPATHLEN] = "(stdin)";
+  char orig_name[MAXPATHLEN];
+  char *subband_list = NULL;
+
+  int in_cols, in_rows, in_format;
+  gray in_maxval;
+  int orig_cols, orig_rows, orig_format;
+  gray orig_maxval;
+  int cols, rows, format;
+  gray maxval;
+  int col, row;
+
+  int no_orig = 0;
+  int m = 0;
+  int c;
+  int maxlevel = 0;
+
+  int filter = 1;
+  int method = 2; 
+  int levels;
+  char filter_name[MAXPATHLEN] = "filter.dat";
+
+  double error = 0.0;
+  int print_psnr = 0;
+  int print_psnr_subband = 0;
+  int print_psnr_only = 0;
+
+  double min, max;
+
+  int verbose = 0;
+
+  progname = argv[0];
+
+  pgm_init(&argc, argv); wm_init();
+
+  while ((c = getopt(argc, argv, "e:f:F:h?i:l:m:o:pPqs:v:")) != EOF) {
+    switch (c) {
+      case 'h':
+      case '?':
+        usage();
+        break;
+      case 'e':
+        method = atoi(optarg);
+        if (method < 0) {
+          fprintf(stderr, "%s: wavelet filtering method %d out of range\n", progname, method);
+          exit(1);
+        }
+        break;
+      case 'f':
+        filter = atoi(optarg);
+        if (filter <= 0) {
+          fprintf(stderr, "%s: filter number %d out of range\n", progname, filter);
+          exit(1);
+        }
+        break;
+      case 'F':
+        strcpy(filter_name, optarg);
+        break;
+      case 'i':
+        if (!strcmp(optarg, "-")) {
+          no_orig = 1;
+          strcpy(orig_name, "(zero)");
+        }
+        else {
+          if ((orig = fopen(optarg, "rb")) == NULL) {
+            fprintf(stderr, "%s: unable to open original image file %s\n", progname, optarg);
+            exit(1);
+          }
+          strcpy(orig_name, optarg);
+        }
+        break;
+      case 'l':
+        maxlevel = atoi(optarg);
+        if (maxlevel < 0) {
+          fprintf(stderr, "%s: decomposition level %d out of range\n", progname, maxlevel);
+          exit(1);
+        }
+        break;
+      case 'm':
+        m = atoi(optarg);
+        if (m < -1) {
+          fprintf(stderr, "%s: multiplication factor %d out of range\n", progname, m);
+          exit(1);
+        }
+        break;
+      case 'o':
+        if ((out = fopen(optarg, "wb")) == NULL) {
+          fprintf(stderr, "%s: unable to open output file %s\n", progname, optarg);
+          exit(1);
+        }
+        strcpy(output_name, optarg);
+        break;
+      case 'p':
+        print_psnr = 1;
+        break;
+      case 'P':
+        print_psnr_only = 1;
+        break;
+      case 'q':
+        print_psnr = 1;
+        print_psnr_subband = 1;
+      case 's':
+        subband_list = optarg;
+        break;
+      case 'v':
+        verbose = atoi(optarg);
+        if (verbose < 0) {
+          fprintf(stderr, "%s: verbosity level %d out of range\n", progname, verbose);
+          exit(1);
+        }
+        break;
+
+    }
+  }
+
+  argc -= optind;
+  argv += optind;
+
+  if (argc > 1) {
+    usage();
+    exit(1);
+  }
+
+  print = print_psnr_only ? out : stderr;
+
+  if (argc == 1 && *argv[0] != '-')
+    if ((in = fopen(argv[0], "rb")) == NULL) {
+      fprintf(stderr, "%s: unable to open input file %s\n", progname, argv[0]);
+      exit(1);
+    }
+    else
+      strcpy(input_name, argv[0]);
+
+  if (!orig && !no_orig) {
+    fprintf(stderr, "%s: original image file not specified, using zero image\n", progname);
+    strcpy(orig_name, "(zero)");
+    no_orig = 1;
+  }
+
+  pgm_readpgminit(in, &in_cols, &in_rows, &in_maxval, &in_format);
+
+  if (!no_orig) {
+    pgm_readpgminit(orig, &orig_cols, &orig_rows, &orig_maxval, &orig_format);
+    if (in_cols != orig_cols || in_rows != orig_rows) {
+      fprintf(stderr, "%s: input image %s does not match dimensions of original image %s\n", progname, input_name, orig_name);
+      exit(1);
+    }
+  }
+
+  cols = in_cols;
+  rows = in_rows;
+  format = in_format;
+  maxval = in_maxval;
+
+  input_image = pgm_allocarray(cols, rows);
+  orig_image = pgm_allocarray(cols, rows);
+
+  output = alloc_grays(cols, rows);
+
+  if (no_orig) {
+    for (row = 0; row < rows; row++) {
+      pgm_readpgmrow(in, input_image[row], cols, maxval, format);
+      bzero(orig_image[row], sizeof(gray) * cols);
+    }
+  }
+  else {
+    for (row = 0; row < rows; row++) {
+      pgm_readpgmrow(in, input_image[row], in_cols, in_maxval, in_format);
+      pgm_readpgmrow(orig, orig_image[row], orig_cols, orig_maxval, orig_format);
+    }
+  }
+
+  fclose(in);
+  if (!no_orig)
+    fclose(orig);
+
+  // complete decomposition
+  levels = find_deepest_level(cols, rows) - 1;
+  if (!maxlevel) maxlevel = levels;
+  if (maxlevel > levels) {
+    fprintf(stderr, "%s: decomposition level %d not possible (max. %d), image size is %d x %d\n", progname, maxlevel, levels, cols, rows);
+    exit(1);
+  }
+
+  init_dwt(cols, rows, filter_name, filter, maxlevel, method);
+
+  input_dwts = fdwt(input_image);
+  orig_dwts = fdwt(orig_image);
+
+  p = input_dwts;
+  q = orig_dwts;  
+  min = 10000000.0;
+  max = 0.0;
+  error = 0.0;
+  while (p->coarse && q->coarse) {
+    double localmin, localmax, localerror;
+
+    if (subband_in_list(subband_list, HORIZONTAL, p->horizontal->level)) {
+      calc_subband(p->horizontal, q->horizontal, HORIZONTAL, &localmin, &localmax, &localerror);
+      if (m == -1) process_subband_var(output, cols, rows, p->horizontal, q->horizontal, HORIZONTAL, localmin, localmax, maxval);
+      if (localmin < min) min = localmin;
+      if (localmax > max) max = localmax;
+      error += localerror;
+      if (print_psnr_subband)
+        print_subband_psnr(HORIZONTAL, p->horizontal->level, error, p->horizontal->image->width, p->horizontal->image->height, localmin, localmax, print);
+    }
+    else if (verbose > 5)
+      fprintf(stderr, "%s: subband %s%d skipped\n", progname, subband_name(HORIZONTAL), p->horizontal->level);
+
+    if (subband_in_list(subband_list, VERTICAL, p->vertical->level)) {
+      calc_subband(p->vertical, q->vertical, VERTICAL, &localmin, &localmax, &localerror);
+      if (m == -1) process_subband_var(output, cols, rows, p->vertical, q->vertical, VERTICAL, localmin, localmax, maxval);
+      if (localmin < min) min = localmin;
+      if (localmax > max) max = localmax;
+      error += localerror;
+      if (print_psnr_subband)
+        print_subband_psnr(VERTICAL, p->vertical->level, error, p->vertical->image->width, p->vertical->image->height, localmin, localmax, print);
+    }
+    else if (verbose > 5)
+      fprintf(stderr, "%s: subband %s%d skipped\n", progname, subband_name(VERTICAL), p->vertical->level);
+
+    if (subband_in_list(subband_list, DIAGONAL, p->diagonal->level)) {
+      calc_subband(p->diagonal, q->diagonal, DIAGONAL, &localmin, &localmax, &localerror);
+      if (m == -1) process_subband_var(output, cols, rows, p->diagonal, q->diagonal, DIAGONAL, localmin, localmax, maxval);
+      if (localmin < min) min = localmin;
+      if (localmax > max) max = localmax;
+      error += localerror;
+      if (print_psnr_subband)
+        print_subband_psnr(DIAGONAL, p->vertical->level, error, p->diagonal->image->width, p->diagonal->image->height, localmin, localmax, print);
+    }
+    else if (verbose > 5)
+      fprintf(stderr, "%s: subband %s%d skipped\n", progname, subband_name(DIAGONAL), p->diagonal->level);
+
+    p = p->coarse;
+    q = q->coarse;
+
+    if (!p->coarse) {
+      if (subband_in_list(subband_list, COARSE, p->level)) {
+        calc_subband(p, q, COARSE, &localmin, &localmax, &localerror);
+        if (m == -1) process_subband_var(output, cols, rows, p, q, COARSE, localmin, localmax, maxval);
+        if (localmin < min) min = localmin;
+        if (localmax > max) max = localmax;
+        error += localerror;
+        if (print_psnr_subband)
+          print_subband_psnr(COARSE, p->level, error, p->image->width, p->image->height, localmin, localmax, print);
+      }
+      else if (verbose > 5)
+        fprintf(stderr, "%s: subband %s%d skipped\n", progname, subband_name(COARSE), p->level);
+    }
+  }
+
+  p = input_dwts;
+  q = orig_dwts;
+  while (p->coarse && q->coarse) {
+    if (m > 0) {
+      process_subband_fixed(output, cols, rows, p->horizontal, q->horizontal, HORIZONTAL, m);    
+      process_subband_fixed(output, cols, rows, p->vertical, q->vertical, VERTICAL, m);    
+      process_subband_fixed(output, cols, rows, p->diagonal, q->diagonal, DIAGONAL, m);    
+    }
+    else if (m == 0) {
+      process_subband_var(output, cols, rows, p->horizontal, q->horizontal, HORIZONTAL, min, max, maxval);    
+      process_subband_var(output, cols, rows, p->vertical, q->vertical, VERTICAL, min, max, maxval);    
+      process_subband_var(output, cols, rows, p->diagonal, q->diagonal, DIAGONAL, min, max, maxval);    
+    }
+
+    p = p->coarse;
+    q = q->coarse;
+
+    if (!p->coarse) {
+      if (m > 0) 
+        process_subband_fixed(output, cols, rows, p, q, COARSE, m);
+      else if (m == 0) 
+        process_subband_var(output, cols, rows, p, q, COARSE, min, max, maxval);
+    }
+  }
+
+  if (!print_psnr_only) {
+    pgm_writepgminit(out, cols, rows, maxval, 0);
+    for (row = 0; row < rows; row++)
+      pgm_writepgmrow(out, output[row], cols, maxval, 0);
+
+    fclose(out);
+  }
+
+ pgm_freearray(input_image, rows);
+ pgm_freearray(orig_image, rows);
+ free_grays(output);
+
+ if (print_psnr || print_psnr_only) {
+    double mse = error / (double) (cols * rows);
+    double rmse = sqrt(mse);
+    double psnr = 20.0 * log(255.0 / rmse) / log(10.0);
+    if (mse > 0.0)
+      fprintf(print, "PSNR: %lf dB\n", psnr);
+    else
+      fprintf(print, "PSNR: inf\n");
+    fprintf(print, "RMS: %lf\n", rmse);
+    fprintf(print, "MSE: %lf\n", mse);
+    fprintf(print, "dmin, dmax: %lf, %lf\n", min, max);
+  }
+
+  exit(0);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Meerwald/cmp_frid2_sig.c	Sun Aug 12 13:14:34 2007 +0200
@@ -0,0 +1,154 @@
+#include "wm.h"
+#include "signature.h"
+
+char *progname;
+
+void usage(void) {
+  fprintf(stderr, "usage: %s [-h] [-C] [-o file] [-v n] -s file file\n\n", progname);
+  fprintf(stderr, "\t-C\t\toutput correlation only\n");
+  fprintf(stderr, "\t-h\t\tprint usage\n");
+  fprintf(stderr, "\t-o file\t\toutput file\n");
+  fprintf(stderr, "\t-s file\t\toriginal signature file\n");
+  fprintf(stderr, "\t-v n\t\tverbosity level\n");
+  exit(0);
+}
+
+int main(int argc, char *argv[]) {
+
+  FILE *in = stdin;
+  FILE *out = stdout;
+  FILE *sig = NULL;
+
+  char signature_name[MAXPATHLEN];
+  char output_name[MAXPATHLEN] = "(stdout)";
+  char input_name[MAXPATHLEN] = "(stdin)";
+
+  int correlation_only = 0;
+
+  int c, i;
+  int corr1 = 0, match1 = 0;
+  int corr2 = 0, match2 = 0;
+  int verbose = 0;
+  char filter_name[MAXPATHLEN] = "";
+
+  int seed;
+  char line[32];
+
+  progname = argv[0];
+
+  while ((c = getopt(argc, argv, "h?Co:s:v:")) != EOF) {
+    switch (c) {
+      case 'h':
+      case '?':
+        usage();
+        break; 
+      case 'C':
+        correlation_only = 1;
+        break;
+      case 'o':
+        if ((out = fopen(optarg, "w")) == NULL) {
+          fprintf(stderr, "%s: unable to open output file %s\n", progname, optarg);
+          exit(1);
+        }
+        strcpy(output_name, optarg);
+        break;
+      case 's':
+        if ((sig = fopen(optarg, "r")) == NULL) {
+          fprintf(stderr, "%s: unable to open signature file %s\n", progname, optarg);
+          exit(1);
+        }
+        strcpy(signature_name, optarg);
+        break;
+     case 'v':
+        verbose = atoi(optarg);
+        if (verbose < 0) {
+          fprintf(stderr, "%s: verbosity level %d out of range\n", progname, verbose);
+          exit(1);
+        }
+        break;
+    }
+  }
+
+  argc -= optind;
+  argv += optind;
+
+  if (argc > 1) {
+    usage();
+    exit(1);
+  }
+
+  if (argc == 1 && *argv[0] != '-')
+    if ((in = fopen(argv[0], "r")) == NULL) {
+      fprintf(stderr, "%s: unable to open input file %s\n", progname, argv[0]);
+      exit(1);
+    }
+    else
+      strcpy(input_name, argv[0]);
+
+  if (sig) {
+    fgets(line, sizeof(line), sig);
+    if (strspn(line, "FR2SG") >= 5) {
+      fscanf(sig, "%d\n", &nbit_signature);
+      fscanf(sig, "%*lf\n");
+      fscanf(sig, "%*lf\n");
+      fscanf(sig, "%*d\n");
+      n_signature = NBITSTOBYTES(nbit_signature);
+      fread(signature, sizeof(char), n_signature, sig);
+      fscanf(sig, "\n");
+    }
+    else {
+      fprintf(stderr, "%s: invalid signature file %s\n", progname, signature_name);
+      exit(1);
+    }
+    close(sig);
+  }
+  else {
+    fprintf(stderr, "%s: original signature file not specified, use -s file option\n", progname);
+    exit(1);
+  }
+
+  fgets(line, sizeof(line), in);
+  if (strspn(line, "FR2WM") >= 5) {
+    fscanf(in, "%d\n", &nbit_signature1);
+    n_signature1 = NBITSTOBYTES(nbit_signature1);
+    fread(signature1, sizeof(char), n_signature1, in);
+//    fscanf(in, "\n");    
+    fscanf(in, "%d\n", &nbit_signature2);
+    n_signature2 = NBITSTOBYTES(nbit_signature2);
+    fread(signature2, sizeof(char), n_signature2, in);
+    fscanf(in, "\n");    
+  }
+  else {
+    fprintf(stderr, "%s: invalid watermark file %s\n", progname, input_name);
+    exit(1);
+  }
+
+  if (verbose > 0) {
+    fprintf(stderr, "signature length: %d\n", nbit_signature);
+    fprintf(stderr, "watermark length (low. freq.): %d\n", nbit_signature1);
+    fprintf(stderr, "watermark length (med. freq.): %d\n", nbit_signature2);
+  }
+
+  for (i = 0; i < nbit_signature; i++) {
+    if (get_signature_bit(i) == get_signature1_bit(i))
+      corr1++, match1++;
+    else
+      corr1--;
+    if (get_signature_bit(i) == get_signature2_bit(i))
+      corr2++, match2++;
+    else
+      corr2--;
+  }
+
+  if (correlation_only)
+    fprintf(out, "%lf\n", (double) (corr1 + corr2) / (nbit_signature1 + nbit_signature2));
+  else {
+    fprintf(out, "bit matches (low freq.): %d/%d\n", match1, nbit_signature1);
+    fprintf(out, "correlation (low. freq.): %lf\n", (double) corr1 / nbit_signature1);
+    fprintf(out, "bit matches (med. freq.): %d/%d\n", match2, nbit_signature2);
+    fprintf(out, "correlation (med. freq.): %lf\n", (double) corr2 / nbit_signature2);
+    fprintf(out, "total correlation: %lf\n", (double) (corr1 + corr2) / (nbit_signature1 + nbit_signature2));
+  }
+
+  exit(0);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Meerwald/cmp_kim_sig.c	Sun Aug 12 13:14:34 2007 +0200
@@ -0,0 +1,164 @@
+#include "wm.h"
+
+char *progname;
+
+void usage(void) {
+  fprintf(stderr, "usage: %s [-h] [-C] [-o file] [-v n] -s file file\n\n", progname);
+  fprintf(stderr, "\t-C\t\toutput correlation only\n");
+  fprintf(stderr, "\t-h\t\tprint usage\n");
+  fprintf(stderr, "\t-o file\t\toutput file\n");
+  fprintf(stderr, "\t-v n\t\tverbosity level\n");
+  fprintf(stderr, "\t-s file\t\toriginal signature file\n");
+  exit(0);
+}
+
+int main(int argc, char *argv[]) {
+
+  FILE *in = stdin;
+  FILE *out = stdout;
+  FILE *sig = NULL;
+
+  char signature_name[MAXPATHLEN];
+  char output_name[MAXPATHLEN] = "(stdout)";
+  char input_name[MAXPATHLEN] = "(stdin)";
+
+  int c, i, j, n;
+  int in_level;
+  double *input_watermark, *orig_watermark;
+  int sig_n, in_n;
+  double sig_a;
+  double sig_A;
+  int sig_l;
+  int sig_e, sig_f;
+  double s1, s2, s3;
+  double correlation;
+  char line[32];
+
+  int verbose = 0;
+  int correlation_only = 0;
+
+  progname = argv[0];
+
+  while ((c = getopt(argc, argv, "h?Co:s:v:")) != EOF) {
+    switch (c) {
+      case 'h':
+      case '?':
+        usage();
+        break;
+      case 'C':
+        correlation_only = 1;
+        break;
+      case 'o':
+        if ((out = fopen(optarg, "w")) == NULL) {
+          fprintf(stderr, "%s: unable to open output file %s\n", progname, optarg);
+          exit(1);
+        }
+        strcpy(output_name, optarg);
+        break;
+      case 's':
+        if ((sig = fopen(optarg, "r")) == NULL) {
+          fprintf(stderr, "%s: unable to open signature file %s\n", progname, optarg);
+          exit(1);
+        }
+        strcpy(signature_name, optarg);
+        break;
+     case 'v':
+        verbose = atoi(optarg);
+        if (verbose < 0) {
+          fprintf(stderr, "%s: verbosity level %d out of range\n", progname, verbose);
+          exit(1);
+        }
+        break;
+    }
+  }
+
+  argc -= optind;
+  argv += optind;
+
+  if (argc > 1) {
+    usage();
+    exit(1);
+  }
+
+  if (argc == 1 && *argv[0] != '-')
+    if ((in = fopen(argv[0], "r")) == NULL) {
+      fprintf(stderr, "%s: unable to open input file %s\n", progname, argv[0]);
+      exit(1);
+    }
+    else
+      strcpy(input_name, argv[0]);
+
+  if (!sig) {
+    fprintf(stderr, "%s: original signature file not specified, use -s file option\n", progname);
+    exit(1);
+  }
+
+  fgets(line, sizeof(line), sig);
+  if (strspn(line, "KISG") < 4) {
+    fprintf(stderr, "%s: original signature file %s invalid\n", progname, signature_name);
+    exit(1);
+  }
+
+  fgets(line, sizeof(line), in);
+  if (strspn(line, "KIWM") < 4) {
+    fprintf(stderr, "%s: watermark file %s invalid\n", progname, input_name);
+    exit(1);
+  }
+
+  fscanf(sig, "%d\n", &sig_n);
+  fscanf(in, "%d\n", &in_n);
+
+  if (sig_n <= 0 || sig_n > 32000) {
+    fprintf(stderr, "%s: invalid original watermark length %d\n", progname, sig_n);
+    exit(1);
+  }
+
+  fscanf(sig, "%lf\n", &sig_a);
+  fscanf(sig, "%lf\n", &sig_A);
+  fscanf(sig, "%d\n", &sig_l);
+  fscanf(sig, "%d\n", &sig_e);
+  fscanf(sig, "%d\n", &sig_f);
+  fscanf(sig, "%*[^\n\r]\n");
+
+  orig_watermark = malloc(sig_n * sizeof(double));
+  for (i = 0; i < sig_n; i++)
+    fscanf(sig, "%lf\n", &orig_watermark[i]);
+  fclose(sig);
+
+  fscanf(in, "%d\n", &in_level);
+  input_watermark = malloc(in_n * sizeof(double));
+  for (i = 0; i < in_n; i++)
+    fscanf(in, "%lf\n", &input_watermark[i]);
+  fclose(in);
+
+  /*
+   * normalized correlation
+   * Craver, S., "Can Invisible Watermarks Resolve Rightful Ownership?", IBM Research Report, 1996, p. 5
+   */
+
+  s1 = s2 = s3 = 0.0;
+  for (i = 0; i < in_n; i++) {
+    double in_x, sig_x;
+
+    in_x = input_watermark[i];
+    sig_x = orig_watermark[i % sig_n];
+
+    s1 += sig_x * in_x;
+    s2 += in_x * in_x;
+    s3 += sig_x * sig_x;
+  }
+
+  correlation = s1 / sqrt(s2 * s3);
+      
+  if (!correlation_only)  
+    fprintf(out, "%s: correlation: %f\n", progname, correlation);
+  else
+    fprintf(out, "%f\n", correlation);
+
+  fclose(out);
+
+  free(orig_watermark);
+  free(input_watermark);
+
+  exit(0);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Meerwald/cmp_koch_sig.c	Sun Aug 12 13:14:34 2007 +0200
@@ -0,0 +1,142 @@
+#include "wm.h"
+#include "signature.h"
+
+char *progname;
+
+void usage(void) {
+  fprintf(stderr, "usage: %s [-h] [-C] [-o file] [-v n] -s file file\n\n", progname);
+  fprintf(stderr, "\t-C\t\toutput correlation only\n");
+  fprintf(stderr, "\t-h\t\tprint usage\n");
+  fprintf(stderr, "\t-o file\t\toutput file\n");
+  fprintf(stderr, "\t-s file\t\toriginal signature file\n");
+  fprintf(stderr, "\t-v n\t\tverbosity level\n");
+  exit(0);
+}
+
+int main(int argc, char *argv[]) {
+
+  FILE *in = stdin;
+  FILE *out = stdout;
+  FILE *sig = NULL;
+
+  char signature_name[MAXPATHLEN];
+  char output_name[MAXPATHLEN] = "(stdout)";
+  char input_name[MAXPATHLEN] = "(stdin)";
+
+  int c, i;
+  double quality = 0.0;
+  int quantization = 0;
+  int corr = 0, match = 0;
+  int verbose = 0;
+
+  int correlation_only = 0;
+
+  int seed;
+  char line[32];
+
+  progname = argv[0];
+
+  while ((c = getopt(argc, argv, "h?Co:s:v:")) != EOF) {
+    switch (c) {
+      case 'h':
+      case '?':
+        usage();
+        break; 
+      case 'C':
+        correlation_only = 1;
+        break;
+      case 'o':
+        if ((out = fopen(optarg, "w")) == NULL) {
+          fprintf(stderr, "%s: unable to open output file %s\n", progname, optarg);
+          exit(1);
+        }
+        strcpy(output_name, optarg);
+        break;
+      case 's':
+        if ((sig = fopen(optarg, "r")) == NULL) {
+          fprintf(stderr, "%s: unable to open signature file %s\n", progname, optarg);
+          exit(1);
+        }
+        strcpy(signature_name, optarg);
+        break;
+     case 'v':
+        verbose = atoi(optarg);
+        if (verbose < 0) {
+          fprintf(stderr, "%s: verbosity level %d out of range\n", progname, verbose);
+          exit(1);
+        }
+        break;
+    }
+  }
+
+  argc -= optind;
+  argv += optind;
+
+  if (argc > 1) {
+    usage();
+    exit(1);
+  }
+
+  if (argc == 1 && *argv[0] != '-')
+    if ((in = fopen(argv[0], "r")) == NULL) {
+      fprintf(stderr, "%s: unable to open input file %s\n", progname, argv[0]);
+      exit(1);
+    }
+    else
+      strcpy(input_name, argv[0]);
+
+  if (sig) {
+    fgets(line, sizeof(line), sig);
+    if (strspn(line, "KCSG") >= 4) {
+      fscanf(sig, "%d\n", &nbit_signature1);
+      fscanf(sig, "%lf\n", &quality);
+      fscanf(sig, "%d\n", &quantization);
+      fscanf(sig, "%d\n", &seed);
+      srandom(seed);
+      n_signature1 = NBITSTOBYTES(nbit_signature1);
+      fread(signature1, sizeof(char), n_signature1, sig);
+      fscanf(sig, "\n");
+    }
+    else {
+      fprintf(stderr, "%s: invalid signature file %s\n", progname, signature_name);
+      exit(1);
+    }
+    close(sig);
+  }
+  else {
+    fprintf(stderr, "%s: original signature file not specified, use -s file option\n", progname);
+    exit(1);
+  }
+
+  fgets(line, sizeof(line), in);
+  if (strspn(line, "KCWM") >= 4) {
+    fscanf(in, "%d\n", &nbit_signature2);
+    n_signature2 = NBITSTOBYTES(nbit_signature2);
+    fread(signature2, sizeof(char), n_signature2, in);
+    fscanf(in, "\n");    
+  }
+  else {
+    fprintf(stderr, "%s: invalid watermark file %s\n", progname, input_name);
+    exit(1);
+  }
+
+  if (verbose > 0) {
+    fprintf(stderr, "signature length: %d\n", nbit_signature1);
+    fprintf(stderr, "watermark length: %d\n", nbit_signature2);
+  }
+
+  for (i = 0; i < nbit_signature2; i++)
+    if (get_signature1_bit(i % nbit_signature1) == get_signature2_bit(i))
+      corr++, match++;
+    else
+      corr--;
+
+  if (correlation_only)
+    fprintf(out, "%lf\n", (double) corr / nbit_signature2);
+  else {
+    fprintf(out, "bit matches: %d/%d\n", match, nbit_signature2);
+    fprintf(out, "correlation: %lf\n", (double) corr / nbit_signature2);
+  }
+
+  exit(0);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Meerwald/cmp_pgm.1	Sun Aug 12 13:14:34 2007 +0200
@@ -0,0 +1,69 @@
+.\"
+.\" cmp_pgm.1 - the *roff document processor man page source
+.\"
+.TH cmp_pgm 1 "98/07/08" "Watermarking, Version 1.0"
+.SH NAME
+cmp_pgm \- a program to create the difference image of two PGM images
+.SH SYNOPSIS
+.B cmp_pgm
+[
+.B \-h
+]
+[
+.BI \-m \ number
+]
+[
+.BI \-o \ ofile
+]
+.BI \-i \ ifile
+.I file
+.SH DESCRIPTION
+.B cmp_pgm
+is a program to create the difference image of two PGM (portable graymap)
+grayscale images. To compare PPM (portable pixmap) RGB color images, use the
+.B cmp_ppm
+program.
+.PP
+If
+.I file
+or
+.I ofile
+is not specified, then standard input or standard output is
+used.
+.PP
+.SH OPTIONS
+.TP
+.B \-h
+Print a help message.
+.TP
+.BI \-i \ ifile
+The original image. Mandatory.
+.TP
+.BI \-m \ number
+Multiplication factor to magnify differences between the to
+original and input image.
+Default value: 16.
+.TP
+.BI \-o \ ofile
+Output image file to contain the difference image in PGM format.
+.TP
+.I file
+Input image that is compared against
+.I ifile.
+Default: standard input.
+.SH OUTPUT
+The difference image in PGM format is written to standard output or,
+optionally, to
+.I ofile.
+.SH AUTHOR
+Peter Meerwald.
+Email bug reports to pmeerw@cosy.sbg.ac.at.
+.SH AVAILABILITY
+The most recent released version of
+.B cmp_pgm
+is always available
+at http://www.cosy.sbg.ac.at/~pmeerw/Watermarking or via anonymous ftp from ftp.cosy.sbg.ac.at in the
+directory /pub/people/pmeerw/Watermarking.
+.SH "SEE ALSO"
+.B cmp_ppm
+(1)
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Meerwald/cmp_pgm.c	Sun Aug 12 13:14:34 2007 +0200
@@ -0,0 +1,262 @@
+#include "wm.h"
+#include "pgm.h"
+
+char *progname;
+
+void usage(void) {
+  fprintf(stderr, "usage: %s [-C] [-h] [-m n] [-o file] [-pP] [-r file] -i file file\n\n", progname);
+  fprintf(stderr, "\t-C\t\tprint PSNR value only\n");
+  fprintf(stderr, "\t-h\t\tprint usage\n");
+  fprintf(stderr, "\t-i file\t\toriginal image file\n");
+  fprintf(stderr, "\t-m n\t\tmultiplication factor (default auto)\n");
+  fprintf(stderr, "\t-o file\t\toutput file for difference image\n");
+  fprintf(stderr, "\t-p\t\tprint PSNR, RMS and MSE\n");
+  fprintf(stderr, "\t-P\t\tonly print PSNR, RMS and MSE, no difference image\n");
+  fprintf(stderr, "\t-r file\t\tROI (region-of-interest) mask (default none)\n");
+  exit(0);
+}
+
+int main(int argc, char *argv[]) {
+
+  FILE *in = stdin;
+  FILE *out = stdout;
+  FILE *orig = NULL;
+  FILE *roi = NULL;
+
+  gray **input_image;
+  gray **orig_image;
+  gray **roi_image;
+
+  char output_name[MAXPATHLEN] = "(stdout)";
+  char input_name[MAXPATHLEN] = "(stdin)";
+  char orig_name[MAXPATHLEN];
+  char roi_name[MAXPATHLEN];
+
+  int in_cols, in_rows, in_format;
+  gray in_maxval;
+  int roi_cols, roi_rows, roi_format;
+  gray roi_maxval;
+  int orig_cols, orig_rows, orig_format;
+  gray orig_maxval;
+  int cols, rows, format;
+  gray maxval;
+  int col, row;
+
+  int roisize = 0;
+
+  int i;
+  int c;
+
+  int m = 0;
+  int min, max;
+
+  int print_psnr = 0;
+  int print_psnr_only = 0;
+  int print_psnr_value_only = 0;
+  double error = 0.0;
+
+  progname = argv[0];
+
+  pgm_init(&argc, argv); wm_init();
+
+  while ((c = getopt(argc, argv, "h?i:m:o:r:pPC")) != EOF) {
+    switch (c) {
+      case 'h':
+      case '?':
+        usage();
+        break;
+      case 'i':
+        if ((orig = fopen(optarg, "rb")) == NULL) {
+          fprintf(stderr, "%s: unable to open original image file %s\n", progname, optarg);
+          exit(1);
+        }
+        strcpy(orig_name, optarg);
+        break;
+      case 'r':
+        if ((roi = fopen(optarg, "rb")) == NULL) {
+          fprintf(stderr, "%s: unable to open ROI image file %s\n", progname, optarg);
+          exit(1);
+        }
+        strcpy(roi_name, optarg);
+        break;
+      case 'm':
+        m = atoi(optarg);
+        if (m <= 0) {
+          fprintf(stderr, "%s: multiplication factor %d out of range\n", progname, m);
+          exit(1);
+        }
+        break;
+      case 'o':
+        if ((out = fopen(optarg, "wb")) == NULL) {
+          fprintf(stderr, "%s: unable to open output file %s\n", progname, optarg);
+          exit(1);
+        }
+        strcpy(output_name, optarg);
+        break;
+      case 'p':
+        print_psnr = 1;
+        break;
+      case 'P':
+        print_psnr_only = 1;
+        break;
+      case 'C':
+        print_psnr_value_only = 1;
+        print_psnr_only = 1;
+        break;
+    }
+  }
+
+  argc -= optind;
+  argv += optind;
+
+  if (argc > 1) {
+    usage();
+    exit(1);
+  }
+
+  if (argc == 1 && *argv[0] != '-')
+    if ((in = fopen(argv[0], "rb")) == NULL) {
+      fprintf(stderr, "%s: unable to open input file %s\n", progname, argv[0]);
+      exit(1);
+    }
+    else
+      strcpy(input_name, argv[0]);
+
+  if (!orig) {
+    fprintf(stderr, "%s: original image file not specified, use -i file option\n", progname);
+    exit(1);
+  }
+
+  pgm_readpgminit(in, &in_cols, &in_rows, &in_maxval, &in_format);
+
+  if (orig) {
+    pgm_readpgminit(orig, &orig_cols, &orig_rows, &orig_maxval, &orig_format);
+
+    if (in_cols != orig_cols || in_rows != orig_rows) {
+      fprintf(stderr, "%s: input image %s does not match dimensions of original image %s\n", progname, input_name, orig_name);
+      exit(1);
+    }
+  }
+
+  if (roi) {
+    pgm_readpgminit(roi, &roi_cols, &roi_rows, &roi_maxval, &roi_format);
+
+    if (in_cols != roi_cols || in_rows != roi_rows) {
+      fprintf(stderr, "%s: input image %s does not match dimensions of ROI image %s\n", progname, input_name, roi_name);
+      exit(1);
+    }
+  }
+
+  cols = in_cols;
+  rows = in_rows;
+  format = in_format;
+  maxval = in_maxval;
+
+  input_image = pgm_allocarray(cols, rows);
+  orig_image = pgm_allocarray(cols, rows);
+  roi_image = pgm_allocarray(cols, rows);
+
+  for (row = 0; row < rows; row++) {
+      pgm_readpgmrow(in, input_image[row], cols, in_maxval, in_format);
+      if (orig) 
+        pgm_readpgmrow(orig, orig_image[row], cols, orig_maxval, orig_format);
+      else
+        memset(orig_image[row], cols, 0);
+      if (roi) 
+        pgm_readpgmrow(roi, roi_image[row], cols, roi_maxval, roi_format);
+      else
+        memset(roi_image[row], cols, PGM_MAXMAXVAL);
+  }
+
+  fclose(in);
+  if (orig) fclose(orig);
+  if (roi) fclose(roi);
+
+  max = 0;
+  min = PGM_MAXMAXVAL;
+
+  for (row = 0; row < rows; row++) {
+    gray *pi = input_image[row];
+    gray *po = orig_image[row];
+    gray *pr = roi_image[row];
+
+    for (col = 0; col < cols; col++) {
+      int diff = abs(*pi - *po);
+      int inroi = (!roi || *pr > 0);
+
+      pi++;
+      po++;
+      pr++;
+
+      if (roi && !inroi)
+        continue;
+
+      roisize++;
+
+      error += sqr(diff);
+      if (diff < min) min = diff;
+      if (diff > max) max = diff;
+
+    }
+  }
+
+  for (row = 0; row < rows; row++) {
+    gray *pi = input_image[row];
+    gray *po = orig_image[row];
+    gray *pr = roi_image[row];
+
+    for (col = 0; col < cols; col++) {
+      int diff = abs(*pi - *po);
+      int inroi = (!roi || *pr > 0);
+      
+      if (!inroi) {
+        *pi = 0;
+      }
+      else {
+        if (m > 0)
+          *pi = PIXELRANGE(diff * m);
+        else
+          *pi = PIXELRANGE((double) (diff - min) / (double) (max - min) * maxval);
+      }
+
+      pi++;
+      po++;
+      pr++;
+
+    }
+  }
+
+  if (!print_psnr_only) {
+    pgm_writepgminit(out, cols, rows, maxval, 0);
+    for (row = 0; row < rows; row++)
+      pgm_writepgmrow(out, input_image[row], cols, maxval, 0);
+
+    fclose(out);
+  }
+
+  pgm_freearray(input_image, rows);
+  pgm_freearray(orig_image, rows);
+  pgm_freearray(roi_image, rows);
+
+  if (print_psnr || print_psnr_only) {
+    double mse = (roisize) ? error / (double) roisize : 0;
+    double rmse = sqrt(mse);
+    double psnr = (rmse) ? 20.0 * log(255.0 / rmse) / log(10.0) : 0;
+    FILE *print = print_psnr_only ? out : stderr;
+    if (!print_psnr_value_only) {
+      if (roi)
+        fprintf(print, "ROI size: %d\n", roisize);
+      if (mse > 0.0) 
+        fprintf(print, "PSNR: %lf dB\n", psnr);
+      else 
+        fprintf(print, "PSNR: inf\n");
+      fprintf(print, "RMSE: %lf\n", rmse);
+      fprintf(print, "MSE: %lf\n", mse);
+      fprintf(print, "dmin, dmax: %d, %d\n", min, max);
+    }
+    else
+      fprintf(print, "%lf\n", mse > 0.0 ? psnr : 100.0);
+  }
+
+  exit(0);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Meerwald/cmp_ppm.1	Sun Aug 12 13:14:34 2007 +0200
@@ -0,0 +1,100 @@
+.\"
+.\" cmp_ppm.1 - the *roff document processor man page source
+.\"
+.TH cmp_ppm 1 "98/07/08" "Watermarking, Version 1.0"
+.SH NAME
+cmp_ppm \- a program to create the difference image of two PGM images
+.SH SYNOPSIS
+.B cmp_ppm
+[
+.BI \-c \ name
+]
+[
+.B \-h
+]
+[
+.BI \-m \ number
+]
+[
+.BI \-o \ ofile
+]
+.BI \-i \ ifile
+.I file
+.SH DESCRIPTION
+.B cmp_ppm
+is a program to create the difference image of two PPM (portable pixmap)
+RGB color images. To compare PGM (portable graymap) grayscale images, use
+the
+.B cmp_pgm
+program.
+.PP
+The color components to compare are specified with the
+.BI \-c \ name
+option, where
+.I name
+is one of the following:
+.TP
+.B red
+The red color component.
+.TP
+.B green
+The green color component.
+.TP
+.B blue
+The blue color component.
+.PP
+Multiple color components are allowed. Specifying only the inital letter
+of a color component is sufficient.
+Per default
+.B cmp_ppm
+compares the luminance value of the images. This operation may be
+selected explicitly with the
+.BI \-c \ luminance
+option.
+.PP
+If
+.I file
+or
+.I ofile
+is not specified, then standard input or standard output is
+used.
+.PP
+.SH OPTIONS
+.TP
+.BI \-c \ name
+Specifies color component(s) or luminance to compare. Default: luminance.
+.TP
+.B \-h
+Print a help message.
+.TP
+.BI \-i \ ifile
+The original image. Mandatory.
+.TP
+.BI \-m \ number
+Multiplication factor to magnify differences between the to
+original and input image.
+Default value: 16.
+.TP
+.BI \-o \ ofile
+Output image file to contain the difference image in PPM format.
+.TP
+.I file
+Input image that is compared against
+.I ifile.
+Default: standard input.
+.SH OUTPUT
+The difference image in PPM format is written to standard output or,
+optionally, to
+.I ofile.
+.SH AUTHOR
+Peter Meerwald.
+Email bug reports to pmeerw@cosy.sbg.ac.at.
+.SH AVAILABILITY
+The most recent released version of
+.B cmp_ppm
+is always available
+at http://www.cosy.sbg.ac.at/~pmeerw/Watermarking or via anonymous ftp from ftp.cosy.sbg.ac.at in the
+directory /pub/people/pmeerw/Watermarking.
+.SH "SEE ALSO"
+.B cmp_ppm
+(1)
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Meerwald/cmp_wang_sig.c	Sun Aug 12 13:14:34 2007 +0200
@@ -0,0 +1,154 @@
+#include "wm.h"
+
+char *progname;
+
+void usage(void) {
+  fprintf(stderr, "usage: %s [-h] [-C] [-o file] [-v n] -s file file\n\n", progname);
+  fprintf(stderr, "\t-C\t\toutput correlation only\n");
+  fprintf(stderr, "\t-h\t\tprint usage\n");
+  fprintf(stderr, "\t-o file\t\toutput file\n");
+  fprintf(stderr, "\t-v n\t\tverbosity level\n");
+  fprintf(stderr, "\t-s file\t\toriginal signature file\n");
+  exit(0);
+}
+
+int main(int argc, char *argv[]) {
+
+  FILE *in = stdin;
+  FILE *out = stdout;
+  FILE *sig = NULL;
+
+  char signature_name[MAXPATHLEN];
+  char output_name[MAXPATHLEN] = "(stdout)";
+  char input_name[MAXPATHLEN] = "(stdin)";
+
+  int c;
+  int sig_n, in_n;
+  double sig_a, sig_b;
+  int sig_e, sig_f;
+  double s1, s2, s3;
+  char line[32];
+
+  int verbose = 0;
+  int correlation_only = 0;
+
+  progname = argv[0];
+
+  while ((c = getopt(argc, argv, "h?Co:s:v:")) != EOF) {
+    switch (c) {
+      case 'h':
+      case '?':
+        usage();
+        break;
+      case 'C':
+        correlation_only = 1;
+        break;
+      case 'o':
+        if ((out = fopen(optarg, "w")) == NULL) {
+          fprintf(stderr, "%s: unable to open output file %s\n", progname, optarg);
+          exit(1);
+        }
+        strcpy(output_name, optarg);
+        break;
+      case 's':
+        if ((sig = fopen(optarg, "r")) == NULL) {
+          fprintf(stderr, "%s: unable to open signature file %s\n", progname, optarg);
+          exit(1);
+        }
+        strcpy(signature_name, optarg);
+        break;
+     case 'v':
+        verbose = atoi(optarg);
+        if (verbose < 0) {
+          fprintf(stderr, "%s: verbosity level %d out of range\n", progname, verbose);
+          exit(1);
+        }
+        break;
+    }
+  }
+
+  argc -= optind;
+  argv += optind;
+
+  if (argc > 1) {
+    usage();
+    exit(1);
+  }
+
+  if (argc == 1 && *argv[0] != '-')
+    if ((in = fopen(argv[0], "r")) == NULL) {
+      fprintf(stderr, "%s: unable to open input file %s\n", progname, argv[0]);
+      exit(1);
+    }
+    else
+      strcpy(input_name, argv[0]);
+
+  if (!sig) {
+    fprintf(stderr, "%s: original signature file not specified, use -s file option\n", progname);
+    exit(1);
+  }
+
+  fgets(line, sizeof(line), sig);
+  if (strspn(line, "WGSG") < 4) {
+    fprintf(stderr, "%s: original signature file %s invalid\n", progname, signature_name);
+    exit(1);
+  }
+
+  fgets(line, sizeof(line), in);
+  if (strspn(line, "WGWM") < 4) {
+    fprintf(stderr, "%s: watermark file %s invalid\n", progname, input_name);
+    exit(1);
+  }
+
+  fscanf(sig, "%d\n", &sig_n);
+  fscanf(in, "%d\n", &in_n);
+  if (sig_n != in_n) {
+    fprintf(stderr, "%s: watermark length mismatch (original %d, input %d)\n", progname, sig_n, in_n);
+    exit(1);
+  }
+  if (sig_n <= 0 || sig_n > 32000) {
+    fprintf(stderr, "%s: invalid original watermark length %d\n", progname, sig_n);
+    exit(1);
+  }
+  if (in_n != sig_n) {
+    fprintf(stderr, "%s: invalid watermark length %d, does not match signature length\n", progname, in_n);
+    exit(1);
+  }
+
+  fscanf(sig, "%lf\n", &sig_a);
+  fscanf(sig, "%lf\n", &sig_b);
+  fscanf(sig, "%d\n", &sig_e);
+  fscanf(sig, "%d\n", &sig_f);
+  fscanf(sig, "%*[^\n\r]\n");
+
+  /*
+   * normalized correlation
+   * Craver, S., "Can Invisible Watermarks Resolve Rightful Ownership?", IBM Research Report, 1996, p. 5
+   */
+
+  s1 = s2 = s3 = 0.0;
+  while (in_n > 0) {
+    double sig_x, in_x;
+
+    fscanf(sig, "%lf\n", &sig_x);
+    fscanf(in, "%lf\n", &in_x);
+
+    if (verbose >= 1) {
+      fprintf(stderr, "orig %f input %f\n", sig_x, in_x);
+    }
+
+    s1 += sig_x * in_x;
+    s2 += in_x * in_x;
+    s3 += sig_x * sig_x;
+
+    in_n--;
+  }
+
+  fprintf(out, "%f\n", s1 / sqrt(s2 * s3));
+
+  fclose(sig);
+  fclose(out);
+  fclose(in);
+
+  exit(0);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Meerwald/cmp_xia_sig.c	Sun Aug 12 13:14:34 2007 +0200
@@ -0,0 +1,212 @@
+#include "wm.h"
+
+char *progname;
+
+void usage(void) {
+  fprintf(stderr, "usage: %s [-h] [-C] [-o file] [-v n] -s file file\n\n", progname);
+  fprintf(stderr, "\t-C\t\toutput correlation only\n");
+  fprintf(stderr, "\t-h\t\tprint usage\n");
+  fprintf(stderr, "\t-o file\t\toutput file\n");
+  fprintf(stderr, "\t-v n\t\tverbosity level\n");
+  fprintf(stderr, "\t-s file\t\toriginal signature file\n");
+  exit(0);
+}
+
+int main(int argc, char *argv[]) {
+
+  FILE *in = stdin;
+  FILE *out = stdout;
+  FILE *sig = NULL;
+
+  char signature_name[MAXPATHLEN];
+  char output_name[MAXPATHLEN] = "(stdout)";
+  char input_name[MAXPATHLEN] = "(stdin)";
+
+  int c, i, j, n;
+  int in_level;
+  double *cumul_watermark, *orig_watermark;
+  int *cumul_watermark_count;
+  int sig_n, in_n;
+  double sig_a;
+  int sig_l;
+  int sig_e, sig_f;
+  double s1, s2, s3;
+  double correlation, maxcorrelation;
+  char line[32];
+
+  int verbose = 0;
+  int correlation_only = 0;
+
+  progname = argv[0];
+
+  while ((c = getopt(argc, argv, "h?Co:s:v:")) != EOF) {
+    switch (c) {
+      case 'h':
+      case '?':
+        usage();
+        break;
+      case 'C':
+        correlation_only = 1;
+        break;
+      case 'o':
+        if ((out = fopen(optarg, "w")) == NULL) {
+          fprintf(stderr, "%s: unable to open output file %s\n", progname, optarg);
+          exit(1);
+        }
+        strcpy(output_name, optarg);
+        break;
+      case 's':
+        if ((sig = fopen(optarg, "r")) == NULL) {
+          fprintf(stderr, "%s: unable to open signature file %s\n", progname, optarg);
+          exit(1);
+        }
+        strcpy(signature_name, optarg);
+        break;
+     case 'v':
+        verbose = atoi(optarg);
+        if (verbose < 0) {
+          fprintf(stderr, "%s: verbosity level %d out of range\n", progname, verbose);
+          exit(1);
+        }
+        break;
+    }
+  }
+
+  argc -= optind;
+  argv += optind;
+
+  if (argc > 1) {
+    usage();
+    exit(1);
+  }
+
+  if (argc == 1 && *argv[0] != '-')
+    if ((in = fopen(argv[0], "r")) == NULL) {
+      fprintf(stderr, "%s: unable to open input file %s\n", progname, argv[0]);
+      exit(1);
+    }
+    else
+      strcpy(input_name, argv[0]);
+
+  if (!sig) {
+    fprintf(stderr, "%s: original signature file not specified, use -s file option\n", progname);
+    exit(1);
+  }
+
+  fgets(line, sizeof(line), sig);
+  if (strspn(line, "XASG") < 4) {
+    fprintf(stderr, "%s: original signature file %s invalid\n", progname, signature_name);
+    exit(1);
+  }
+
+  fgets(line, sizeof(line), in);
+  if (strspn(line, "XAWM") < 4) {
+    fprintf(stderr, "%s: watermark file %s invalid\n", progname, input_name);
+    exit(1);
+  }
+
+  fscanf(sig, "%d\n", &sig_n);
+  fscanf(in, "%d\n", &in_n);
+  if (sig_n != in_n) {
+    fprintf(stderr, "%s: watermark length mismatch (original %d, input %d)\n", progname, sig_n, in_n);
+    exit(1);
+  }
+  if (sig_n <= 0 || sig_n > 32000) {
+    fprintf(stderr, "%s: invalid original watermark length %d\n", progname, sig_n);
+    exit(1);
+  }
+  if (in_n != sig_n) {
+    fprintf(stderr, "%s: invalid watermark length %d, does not match signature length\n", progname, in_n);
+    exit(1);
+  }
+
+  fscanf(sig, "%lf\n", &sig_a);
+  fscanf(sig, "%d\n", &sig_l);
+  fscanf(sig, "%d\n", &sig_e);
+  fscanf(sig, "%d\n", &sig_f);
+  fscanf(sig, "%*[^\n\r]\n");
+
+  orig_watermark = malloc(sig_n * sizeof(double));
+  for (i = 0; i < sig_n; i++)
+    fscanf(sig, "%lf\n", &orig_watermark[i]);
+  fclose(sig);
+
+  fscanf(in, "%d\n", &in_level);
+
+  cumul_watermark = malloc(in_n * sizeof(double));
+  cumul_watermark_count = malloc(in_n * sizeof(int));
+
+  for (i = 0; i < in_n; i++) {
+    cumul_watermark_count[i] = 0;
+    cumul_watermark[i] = 0.0;
+  }
+
+  /*
+   * normalized correlation
+   * Craver, S., "Can Invisible Watermarks Resolve Rightful Ownership?", IBM Research Report, 1996, p. 5
+   */
+
+  maxcorrelation = -10000.0;
+  for (i = 0; i < in_level; i++) {
+    fscanf(in, "%d\n", &n);
+
+    s1 = s2 = s3 = 0.0;
+    for (j = 0; j < n; j++) {
+      double in_x, sig_x;
+
+      sig_x = orig_watermark[j % sig_n];
+      fscanf(in, "%lf\n", &in_x);
+
+      s1 += sig_x * in_x;
+      s2 += in_x * in_x;
+      s3 += sig_x * sig_x;
+
+      if (verbose > 2)
+        fprintf(stderr, "%s: level %d; orig %f input %f\n", progname, i, sig_x, in_x);
+
+      cumul_watermark[j % in_n] += in_x;
+      cumul_watermark_count[j % in_n]++;      
+    }
+
+    correlation = s1 / sqrt(s2 * s3);
+    if (correlation > maxcorrelation)
+      maxcorrelation = correlation;
+
+    if (!correlation_only)
+      fprintf(out, "%s: correlation subband %d: %f\n", progname, i, correlation);
+  }
+
+  s1 = s2 = s3 = 0.0;
+  for (i = 0; i < in_n; i++) {
+    double in_x, sig_x;
+
+    if (cumul_watermark_count[i] <= 0) continue;
+    in_x = cumul_watermark[i] / (double) cumul_watermark_count[i];
+    sig_x = orig_watermark[i];
+
+    s1 += sig_x * in_x;
+    s2 += in_x * in_x;
+    s3 += sig_x * sig_x;
+  }
+
+  correlation = s1 / sqrt(s2 * s3);
+  if (!correlation_only)
+    fprintf(out, "%s: cumultative correlation: %f\n", progname, correlation);
+      
+  if (correlation > maxcorrelation)
+    maxcorrelation = correlation;
+      
+  if (!correlation_only)  
+    fprintf(out, "%s: max. correlation: %f\n", progname, maxcorrelation);
+  else
+    fprintf(out, "%f\n", maxcorrelation);
+
+  fclose(out);
+  fclose(in);
+
+  free(orig_watermark);
+  free(cumul_watermark);
+  free(cumul_watermark_count);
+
+  exit(0);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Meerwald/cmp_xie_sig.c	Sun Aug 12 13:14:34 2007 +0200
@@ -0,0 +1,150 @@
+#include "wm.h"
+#include "signature.h"
+
+char *progname;
+
+void usage(void) {
+  fprintf(stderr, "usage: %s [-h] [-C] [-o file] [-v n] -s file file\n\n", progname);
+  fprintf(stderr, "\t-C\t\toutput correlation only\n");
+  fprintf(stderr, "\t-h\t\tprint usage\n");
+  fprintf(stderr, "\t-o file\t\toutput file\n");
+  fprintf(stderr, "\t-s file\t\toriginal signature file\n");
+  fprintf(stderr, "\t-v n\t\tverbosity level\n");
+  exit(0);
+}
+
+int main(int argc, char *argv[]) {
+
+  FILE *in = stdin;
+  FILE *out = stdout;
+  FILE *sig = NULL;
+
+  char signature_name[MAXPATHLEN];
+  char output_name[MAXPATHLEN] = "(stdout)";
+  char input_name[MAXPATHLEN] = "(stdin)";
+
+  int correlation_only = 0;
+
+  int c, i;
+  int corr = 0, match = 0;
+  int verbose = 0;
+  int filter = 0;
+  int method = 0;
+  int level = 0;
+  double alpha = 0.0;
+  double intensity = 0.0;
+  int subband = 0;
+  char filter_name[MAXPATHLEN] = "";
+
+  int seed;
+  char line[32];
+
+  progname = argv[0];
+
+  while ((c = getopt(argc, argv, "h?Co:s:v:")) != EOF) {
+    switch (c) {
+      case 'h':
+      case '?':
+        usage();
+        break; 
+      case 'C':
+        correlation_only = 1;
+        break;
+      case 'o':
+        if ((out = fopen(optarg, "w")) == NULL) {
+          fprintf(stderr, "%s: unable to open output file %s\n", progname, optarg);
+          exit(1);
+        }
+        strcpy(output_name, optarg);
+        break;
+      case 's':
+        if ((sig = fopen(optarg, "r")) == NULL) {
+          fprintf(stderr, "%s: unable to open signature file %s\n", progname, optarg);
+          exit(1);
+        }
+        strcpy(signature_name, optarg);
+        break;
+     case 'v':
+        verbose = atoi(optarg);
+        if (verbose < 0) {
+          fprintf(stderr, "%s: verbosity level %d out of range\n", progname, verbose);
+          exit(1);
+        }
+        break;
+    }
+  }
+
+  argc -= optind;
+  argv += optind;
+
+  if (argc > 1) {
+    usage();
+    exit(1);
+  }
+
+  if (argc == 1 && *argv[0] != '-')
+    if ((in = fopen(argv[0], "r")) == NULL) {
+      fprintf(stderr, "%s: unable to open input file %s\n", progname, argv[0]);
+      exit(1);
+    }
+    else
+      strcpy(input_name, argv[0]);
+
+  if (sig) {
+    fgets(line, sizeof(line), sig);
+    if (strspn(line, "XESG") >= 4) {
+      fscanf(sig, "%d\n", &nbit_signature1);
+      fscanf(sig, "%lf\n", &alpha);
+      fscanf(sig, "%d\n", &method);
+      fscanf(sig, "%d\n", &filter);
+      fscanf(sig, "%[^\n\r]\n", &filter_name);
+      fscanf(sig, "%d\n", &level);
+      fscanf(sig, "%d\n", &seed);
+      srandom(seed);
+      n_signature1 = NBITSTOBYTES(nbit_signature1);
+      fread(signature1, sizeof(char), n_signature1, sig);
+      fscanf(sig, "\n");
+    }
+    else {
+      fprintf(stderr, "%s: invalid signature file %s\n", progname, signature_name);
+      exit(1);
+    }
+    close(sig);
+  }
+  else {
+    fprintf(stderr, "%s: original signature file not specified, use -s file option\n", progname);
+    exit(1);
+  }
+
+  fgets(line, sizeof(line), in);
+  if (strspn(line, "XEWM") >= 4) {
+    fscanf(in, "%d\n", &nbit_signature2);
+    n_signature2 = NBITSTOBYTES(nbit_signature2);
+    fread(signature2, sizeof(char), n_signature2, in);
+    fscanf(in, "\n");    
+  }
+  else {
+    fprintf(stderr, "%s: invalid watermark file %s\n", progname, input_name);
+    exit(1);
+  }
+
+  if (verbose > 0) {
+    fprintf(stderr, "signature length: %d\n", nbit_signature1);
+    fprintf(stderr, "watermark length: %d\n", nbit_signature2);
+  }
+
+  for (i = 0; i < nbit_signature2; i++)
+    if (get_signature1_bit(i % nbit_signature1) == get_signature2_bit(i))
+      corr++, match++;
+    else
+      corr--;
+
+  if (correlation_only)
+    fprintf(out, "%lf\n", (double) corr / nbit_signature2);
+  else {
+    fprintf(out, "bit matches: %d/%d\n", match, nbit_signature2);
+    fprintf(out, "correlation: %lf\n", (double) corr / nbit_signature2);
+  }
+
+  exit(0);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Meerwald/cmp_zhu_sig.c	Sun Aug 12 13:14:34 2007 +0200
@@ -0,0 +1,210 @@
+#include "wm.h"
+
+char *progname;
+
+void usage(void) {
+  fprintf(stderr, "usage: %s [-h] [-C] [-o file] [-v n] -s file file\n\n", progname);
+  fprintf(stderr, "\t-C\t\toutput correlation only\n");
+  fprintf(stderr, "\t-h\t\tprint usage\n");
+  fprintf(stderr, "\t-o file\t\toutput file\n");
+  fprintf(stderr, "\t-v n\t\tverbosity level\n");
+  fprintf(stderr, "\t-s file\t\toriginal signature file\n");
+  exit(0);
+}
+
+int main(int argc, char *argv[]) {
+
+  FILE *in = stdin;
+  FILE *out = stdout;
+  FILE *sig = NULL;
+
+  char signature_name[MAXPATHLEN];
+  char output_name[MAXPATHLEN] = "(stdout)";
+  char input_name[MAXPATHLEN] = "(stdin)";
+
+  int c, i, j, n;
+  int in_level;
+  double *cumul_watermark, *orig_watermark;
+  int *cumul_watermark_count;
+  int sig_n, in_n;
+  double sig_a;
+  int sig_l;
+  int sig_e, sig_f;
+  char line[32];
+  double correlation, maxcorrelation;
+  double s1, s2, s3;
+
+  int verbose = 0;
+  int correlation_only = 0;
+
+  progname = argv[0];
+
+  while ((c = getopt(argc, argv, "h?Co:s:v:")) != EOF) {
+    switch (c) {
+      case 'h':
+      case '?':
+        usage();
+        break;
+      case 'C':
+        correlation_only = 1;
+        break;
+      case 'o':
+        if ((out = fopen(optarg, "w")) == NULL) {
+          fprintf(stderr, "%s: unable to open output file %s\n", progname, optarg);
+          exit(1);
+        }
+        strcpy(output_name, optarg);
+        break;
+      case 's':
+        if ((sig = fopen(optarg, "r")) == NULL) {
+          fprintf(stderr, "%s: unable to open signature file %s\n", progname, optarg);
+          exit(1);
+        }
+        strcpy(signature_name, optarg);
+        break;
+     case 'v':
+        verbose = atoi(optarg);
+        if (verbose < 0) {
+          fprintf(stderr, "%s: verbosity level %d out of range\n", progname, verbose);
+          exit(1);
+        }
+        break;
+    }
+  }
+
+  argc -= optind;
+  argv += optind;
+
+  if (argc > 1) {
+    usage();
+    exit(1);
+  }
+
+  if (argc == 1 && *argv[0] != '-')
+    if ((in = fopen(argv[0], "r")) == NULL) {
+      fprintf(stderr, "%s: unable to open input file %s\n", progname, argv[0]);
+      exit(1);
+    }
+    else
+      strcpy(input_name, argv[0]);
+
+  if (!sig) {
+    fprintf(stderr, "%s: original signature file not specified, use -s file option\n", progname);
+    exit(1);
+  }
+
+  fgets(line, sizeof(line), sig);
+  if (strspn(line, "ZHSG") < 4) {
+    fprintf(stderr, "%s: original signature file %s invalid\n", progname, signature_name);
+    exit(1);
+  }
+
+  fgets(line, sizeof(line), in);
+  if (strspn(line, "ZHWM") < 4) {
+    fprintf(stderr, "%s: watermark file %s invalid\n", progname, input_name);
+    exit(1);
+  }
+
+  fscanf(sig, "%d\n", &sig_n);
+  fscanf(in, "%d\n", &in_n);
+  if (sig_n != in_n) {
+    fprintf(stderr, "%s: watermark length mismatch (original %d, input %d)\n", progname, sig_n, in_n);
+    exit(1);
+  }
+  if (sig_n <= 0 || sig_n > 32000) {
+    fprintf(stderr, "%s: invalid original watermark length %d\n", progname, sig_n);
+    exit(1);
+  }
+  if (in_n != sig_n) {
+    fprintf(stderr, "%s: invalid watermark length %d, does not match signature length\n", progname, in_n);
+    exit(1);
+  }
+
+  fscanf(sig, "%lf\n", &sig_a);
+  fscanf(sig, "%d\n", &sig_l);
+  fscanf(sig, "%d\n", &sig_e);
+  fscanf(sig, "%d\n", &sig_f);
+  fscanf(sig, "%*[^\n\r]\n");
+
+  orig_watermark = malloc(sig_n * sizeof(double));
+  for (i = 0; i < sig_n; i++) 
+    fscanf(sig, "%lf\n", &orig_watermark[i]);
+  fclose(sig);
+
+  fscanf(in, "%d\n", &in_level);
+
+  cumul_watermark = malloc(in_n * sizeof(double));
+  cumul_watermark_count = malloc(in_n * sizeof(int));
+
+  for (i = 0; i < in_n; i++) {
+    cumul_watermark_count[i] = 0;
+    cumul_watermark[i] = 0.0;
+  }
+
+  /*
+   * normalized correlation
+   * Craver, S., "Can Invisible Watermarks Resolve Rightful Ownership?", IBM Research Report, 1996, p. 5
+   */
+  maxcorrelation = -10000.0;
+  for (i = 0; i < in_level; i++) {
+    fscanf(in, "%d\n", &n);
+
+    s1 = s2 = s3 = 0.0;
+    for (j = 0; j < n; j++) {
+      double in_x, sig_x;
+
+      sig_x = orig_watermark[j];
+      fscanf(in, "%lf\n", &in_x);
+
+      s1 += sig_x * in_x;
+      s2 += in_x * in_x;
+      s3 += sig_x * sig_x;
+
+      if (verbose > 2) 
+        fprintf(stderr, "%s: level %d; orig %f input %f\n", progname, i, sig_x, in_x);
+
+      cumul_watermark[j % in_n] += in_x;
+      cumul_watermark_count[j % in_n]++;      
+    }
+
+    correlation = s1 / sqrt(s2 * s3);
+    if (correlation > maxcorrelation)
+      maxcorrelation = correlation; 
+
+    if (!correlation_only)
+      fprintf(out, "%s: correlation level %d: %f\n", progname, i, correlation);
+  }
+
+  s1 = s2 = s3 = 0.0;
+  for (i = 0; i < in_n; i++) {
+    double in_x, sig_x;
+
+    in_x = cumul_watermark[i] / (double) cumul_watermark_count[i];
+    sig_x = orig_watermark[i];
+
+    s1 += sig_x * in_x;
+    s2 += in_x * in_x;
+    s3 += sig_x * sig_x;
+  }
+
+  correlation = s1 / sqrt(s2 * s3);
+  if (!correlation_only)
+    fprintf(out, "%s: cumultative correlation: %f\n", progname, correlation);
+
+  if (correlation > maxcorrelation)
+    maxcorrelation = correlation; 
+    
+  if (!correlation_only)
+    fprintf(out, "%s: max. correlation: %f\n", progname, maxcorrelation);
+  else
+    fprintf(out, "%f\n", maxcorrelation);
+
+  fclose(out);
+  fclose(in);
+
+  free(orig_watermark);
+  free(cumul_watermark);
+  free(cumul_watermark_count);
+
+  exit(0);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Meerwald/coeff.c	Sun Aug 12 13:14:34 2007 +0200
@@ -0,0 +1,72 @@
+#include "wm.h"
+#include "coeff.h"
+
+double **alloc_coeffs(int cols, int rows) {
+  double **p;
+  int i;
+
+  p = (double **)malloc(rows * sizeof(double *));
+  if (!p) {
+#ifdef DEBUG
+   fprintf(stderr, "alloc_coeffs(): malloc() failed\n");
+   exit(1);
+#else
+   return NULL;
+#endif
+  }
+  p[0] = (double *) malloc(rows * cols * sizeof(double));
+  if (!p[0]) {
+#ifdef DEBUG
+    fprintf(stderr, "alloc_coeffs(): malloc() failed\n");
+    exit(1);
+#else
+    free(p);
+    return NULL;
+#endif
+  }
+  for (i = 1; i < rows; i++) {
+    p[i] = &(p[0][i * cols]);
+  }
+
+  return p;
+}
+
+void free_coeffs(double **coeffs) {
+  free(coeffs[0]);
+  free(coeffs);
+}
+
+double **alloc_coeffs_8x8() {
+  return alloc_coeffs(8, 8);
+}
+
+void print_coeffs_8x8(double **coeffs) {
+ int i, j;
+
+  for (i = 0; i < 8; i++) {
+    for (j = 0; j < 8; j++)
+      fprintf(stderr, "%8.2f ", coeffs[i][j]);
+    fprintf(stderr, "\n");
+  }
+}
+
+void print_coeffs(double **coeffs, int c, int r, int w, int h) {
+  int i, j;
+  double *p;
+
+#ifdef DEBUG
+  if (!coeffs) {
+    fprintf(stderr, "print_coeffs(): NULL pixels\n");
+  }
+  if (w <= 0 || h <= 0 || c < 0 || r < 0) {
+    fprintf(stderr, "print_coeffs(): block dimension out of range\n");
+  }
+#endif
+
+  for (j = r; j < r + h; j++) {
+    p = &coeffs[j][c];
+    for (i = 0; i < w; i++)
+      fprintf(stderr, "%8.2f ", *(p++));
+    fprintf(stderr, "\n");
+  }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Meerwald/coeff.h	Sun Aug 12 13:14:34 2007 +0200
@@ -0,0 +1,12 @@
+#ifndef COEFF_H
+#define COEFF_H
+
+#include "wm.h"
+
+double **alloc_coeffs(int cols, int rows);
+double **alloc_coeffs_8x8();
+void free_coeffs(double **coeffs);
+void print_coeffs_8x8(double **coeffs);
+void print_coeffs(double **coeffs, int c, int r, int w, int h);
+
+#endif
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Meerwald/coord.c	Sun Aug 12 13:14:34 2007 +0200
@@ -0,0 +1,75 @@
+#include <stdlib.h>
+#include <stdio.h>
+#include "coord.h"
+
+struct coords *alloc_coords(int n) {
+  struct coords *c;
+
+  if (c = malloc(sizeof(struct coords)))
+    init_coords(c, n);
+#ifdef DEBUG
+  else
+    fprintf(stderr, "alloc_coords(): malloc failed\n");
+#endif
+
+  return c;
+}
+
+void free_coords(struct coords *c) {
+
+#ifdef DEBUG
+  if (!c)
+    fprintf(stderr, "free_coords(): got NULL pointer\n");
+#endif
+
+  free(c->values);
+  free(c);
+}
+
+int init_coords(struct coords *c, int n) {
+
+#ifdef DEBUG
+  if (!c)
+    fprintf(stderr, "init_coords(): got NULL poiner\n");
+
+  if (n <= 0)
+    fprintf(stderr, "init_coords(): n out of range\n");
+#endif
+
+  c->count = 0;
+  c->max = n;
+
+  if (c->values = malloc(n * sizeof(struct coord)))
+    return 0;
+  else
+    return -1;
+}
+
+int add_coord(struct coords *c, int x, int y) {
+  struct coord *v;
+  int n;
+
+#ifdef DEBUG
+  if (!c)
+    fprintf(stderr, "add_coord(): got NULL pointer\n");
+
+  if (c->count >= c->max)
+    fprintf(stderr, "add_coord(): maximum reached\n");
+#endif
+
+  v = c->values;
+
+  for (n = 0; n < c->count; v++, n++)
+    if (v->x == x && v->y == y) break;
+
+  if (n == c->count) {
+    v->x = x;
+    v->y = y;
+    c->count++;
+    return 0;
+  }
+  else
+    return -1;
+}
+
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Meerwald/coord.h	Sun Aug 12 13:14:34 2007 +0200
@@ -0,0 +1,20 @@
+#ifndef COORD_H
+#define COORD_H
+
+struct coord {
+  int x;
+  int y;
+};
+
+struct coords {
+  int count;
+  int max;
+  struct coord *values;
+};
+
+struct coords *alloc_coords(int n);
+void free_coords(struct coords *c);
+int init_coords(struct coords *c, int n);
+int add_coord(struct coords *c, int x, int y);
+
+#endif
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Meerwald/dct.c	Sun Aug 12 13:14:34 2007 +0200
@@ -0,0 +1,643 @@
+#include "wm.h"
+#include "dct.h"
+
+#define INVROOT2 0.7071067814
+#define SWAP(A, B) {double t = A; A = B; B = t;}
+
+int N;
+int M;
+
+double *dct_NxN_tmp = NULL;
+double *dct_NxN_costable = NULL;
+int dct_NxN_log2N = 0;
+
+static const unsigned int JPEG_lumin_quant_table[NJPEG][NJPEG] = {
+    {16,  11,  10,  16,  24,  40,  51,  61},
+    {12,  12,  14,  19,  26,  58,  60,  55},
+    {14,  13,  16,  24,  40,  57,  69,  56},
+    {14,  17,  22,  29,  51,  87,  80,  62},
+    {18,  22,  37,  56,  68, 109, 103,  77},
+    {24,  35,  55,  64,  81, 104, 113,  92},
+    {49,  64,  78,  87, 103, 121, 120, 101},
+    {72,  92,  95,  98, 112, 100, 103,  99}};
+
+static const unsigned int JPEG_chromin_quant_table[NJPEG][NJPEG] = {
+      {17,  18,  24,  47,  99,  99,  99,  99},
+      {18,  21,  26,  66,  99,  99,  99,  99},
+      {24,  26,  56,  99,  99,  99,  99,  99},
+      {47,  66,  99,  99,  99,  99,  99,  99},
+      {99,  99,  99,  99,  99,  99,  99,  99},
+      {99,  99,  99,  99,  99,  99,  99,  99},
+      {99,  99,  99,  99,  99,  99,  99,  99},
+      {99,  99,  99,  99,  99,  99,  99,  99}};
+
+static void initcosarray()
+{
+  int i,group,base,item,nitems,halfN;
+  double factor;
+
+  dct_NxN_log2N = -1;
+  do{
+    dct_NxN_log2N++;
+    if ((1<<dct_NxN_log2N)>N){
+      fprintf(stderr, "dct_NxN: %d not a power of 2\n", N);
+      exit(1);
+    }
+  }while((1<<dct_NxN_log2N)<N);
+  if (dct_NxN_costable) free(dct_NxN_costable);
+  dct_NxN_costable = (double*) malloc(N * sizeof(double));
+#ifdef DEBUG
+  if(!dct_NxN_costable){
+    fprintf(stderr, "Unable to allocate C array\n");
+    exit(1);
+  }
+#endif
+  halfN=N/2;
+  for(i=0;i<=halfN-1;i++) dct_NxN_costable[halfN+i]=4*i+1;
+  for(group=1;group<=dct_NxN_log2N-1;group++){
+    base= 1<<(group-1);
+    nitems=base;
+    factor = 1.0*(1<<(dct_NxN_log2N-group));
+    for(item=1; item<=nitems;item++) dct_NxN_costable[base+item-1]=factor*dct_NxN_costable[halfN+item-1];
+  }
+
+  for(i=1;i<=N-1;i++) dct_NxN_costable[i] = 1.0/(2.0*cos(dct_NxN_costable[i]*M_PI/(2.0*N)));
+}
+
+void init_dct_NxN(int width, int height) {
+#ifdef DEBUG
+  if (width != height || width <= 0) {
+    fprintf(stderr, "init_dct_NxN(): dimensions out of range\n");
+    exit(1);
+  }
+#endif
+
+  if (dct_NxN_tmp && M != height)
+    free(dct_NxN_tmp);
+
+  N = width;
+  M = height;
+
+  dct_NxN_tmp = (double *) malloc(height * sizeof(double));
+#ifdef DEBUG
+  if (!dct_NxN_tmp) {
+    fprintf(stderr, "init_dct_NxN(): failed to allocate memory\n");
+    exit(1);
+  }
+#endif
+
+  initcosarray();
+}
+
+static void bitrev(double *f, int len)
+{
+  int i,j,m;
+
+  if (len<=2) return; /* No action necessary if n=1 or n=2 */
+  j=1;
+  for(i=1; i<=len; i++){
+    if(i<j)
+      SWAP(f[j-1], f[i-1]);
+    m = len>>1;
+    while(j>m){
+      j=j-m;
+      m=(m+1)>>1;
+    }
+    j=j+m;
+  }
+}
+
+static void inv_sums(double *f)
+{
+  int stepsize,stage,curptr,nthreads,thread,step,nsteps;
+
+  for(stage=1; stage <=dct_NxN_log2N-1; stage++){
+    nthreads = 1<<(stage-1);
+    stepsize = nthreads<<1;
+    nsteps   = (1<<(dct_NxN_log2N-stage)) - 1;
+    for(thread=1; thread<=nthreads; thread++){
+      curptr=N-thread;
+      for(step=1; step<=nsteps; step++){
+        f[curptr] += f[curptr-stepsize];
+        curptr -= stepsize;
+      }
+    }
+  }
+}
+
+static void fwd_sums(double *f)
+{
+  int stepsize,stage,curptr,nthreads,thread,step,nsteps;
+
+  for(stage=dct_NxN_log2N-1; stage >=1; stage--){
+    nthreads = 1<<(stage-1);
+    stepsize = nthreads<<1;
+    nsteps   = (1<<(dct_NxN_log2N-stage)) - 1;
+    for(thread=1; thread<=nthreads; thread++){
+      curptr=nthreads +thread-1;
+      for(step=1; step<=nsteps; step++){
+        f[curptr] += f[curptr+stepsize];
+        curptr += stepsize;
+      }
+    }
+  }
+}
+
+static void scramble(double *f,int len){
+  int i,ii1,ii2;
+
+  bitrev(f,len);
+  bitrev(&f[0], len>>1);
+  bitrev(&f[len>>1], len>>1);
+  ii1=len-1;
+  ii2=len>>1;
+  for(i=0; i<(len>>2); i++){
+    SWAP(f[ii1], f[ii2]);
+    ii1--;
+    ii2++;
+  }
+}
+
+static void unscramble(double *f,int len)
+{
+  int i,ii1,ii2;
+
+  ii1 = len-1;
+  ii2 = len>>1;
+  for(i=0; i<(len>>2); i++){
+    SWAP(f[ii1], f[ii2]);
+    ii1--;
+    ii2++;
+  }
+  bitrev(&f[0], len>>1);
+  bitrev(&f[len>>1], len>>1);
+  bitrev(f,len);
+}
+
+static void inv_butterflies(double *f)
+{
+  int stage,ii1,ii2,butterfly,ngroups,group,wingspan,increment,baseptr;
+  double Cfac,T;
+
+  for(stage=1; stage<=dct_NxN_log2N;stage++){
+    ngroups=1<<(dct_NxN_log2N-stage);
+    wingspan=1<<(stage-1);
+    increment=wingspan<<1;
+    for(butterfly=1; butterfly<=wingspan; butterfly++){
+      Cfac = dct_NxN_costable[wingspan+butterfly-1];
+      baseptr=0;
+      for(group=1; group<=ngroups; group++){
+        ii1=baseptr+butterfly-1;
+        ii2=ii1+wingspan;
+        T=Cfac * f[ii2];
+        f[ii2]=f[ii1]-T;
+        f[ii1]=f[ii1]+T;
+        baseptr += increment;
+      }
+    }
+  }
+}
+
+static void fwd_butterflies(double *f)
+{
+  int stage,ii1,ii2,butterfly,ngroups,group,wingspan,increment,baseptr;
+  double Cfac,T;
+
+  for(stage=dct_NxN_log2N; stage>=1;stage--){
+    ngroups=1<<(dct_NxN_log2N-stage);
+    wingspan=1<<(stage-1);
+    increment=wingspan<<1;
+    for(butterfly=1; butterfly<=wingspan; butterfly++){
+      Cfac = dct_NxN_costable[wingspan+butterfly-1];
+      baseptr=0;
+      for(group=1; group<=ngroups; group++){
+        ii1=baseptr+butterfly-1;
+        ii2=ii1+wingspan;
+        T= f[ii2];
+        f[ii2]=Cfac *(f[ii1]-T);
+        f[ii1]=f[ii1]+T;
+        baseptr += increment;
+      }
+    }
+  }
+}
+
+static void ifct_noscale(double *f)
+{
+  f[0] *= INVROOT2;
+  inv_sums(f);
+  bitrev(f,N);
+  inv_butterflies(f);
+  unscramble(f,N);
+}
+
+static void fct_noscale(double *f)
+{
+  scramble(f,N);
+  fwd_butterflies(f);
+  bitrev(f,N);
+  fwd_sums(f);
+  f[0] *= INVROOT2;
+}
+
+void fdct_NxN(gray **pixels, double **dcts) {
+  int u,v;
+  double two_over_sqrtncolsnrows = 2.0/sqrt((double) N*M);
+
+  for (u=0; u < N; u++)
+    for (v=0; v < M; v++)
+      dcts[u][v] = ((int) pixels[u][v]-128);
+
+  for (u=0; u<=M-1; u++){
+    fct_noscale(dcts[u]);
+  }
+  for (v=0; v<=N-1; v++){
+    for (u=0; u<=M-1; u++){
+       dct_NxN_tmp[u] = dcts[u][v];
+    }
+    fct_noscale(dct_NxN_tmp);
+    for (u=0; u<=M-1; u++){
+      dcts[u][v] = dct_NxN_tmp[u]*two_over_sqrtncolsnrows;
+    }
+  }
+}
+
+void idct_NxN(double **dcts, gray **pixels) {
+ int u,v;
+ double two_over_sqrtncolsnrows = 2.0/sqrt((double) N*M);
+
+  double **tmp;
+
+  tmp = alloc_coeffs(N, N);
+  for (u=0;u<N;u++)
+    for (v=0;v<M;v++)
+      tmp[u][v] = dcts[u][v];
+
+  for (u=0; u<=M-1; u++){
+    ifct_noscale(tmp[u]);
+  }
+  for (v=0; v<=N-1; v++){
+    for (u=0; u<=M-1; u++){
+       dct_NxN_tmp[u] = tmp[u][v];
+    }
+    ifct_noscale(dct_NxN_tmp);
+    for (u=0; u<=M-1; u++){
+       tmp[u][v] = dct_NxN_tmp[u]*two_over_sqrtncolsnrows;
+    }
+  }
+
+ for (u=0;u<N;u++)
+    for (v=0;v<M;v++)
+      pixels[u][v] = PIXELRANGE(tmp[u][v] + 128.5);
+ free(tmp);
+}
+
+void fdct_inplace_NxN(double **coeffs) {
+  int u,v;
+  double two_over_sqrtncolsnrows = 2.0/sqrt((double) N*M);
+
+  for (u=0; u<=M-1; u++)
+    fct_noscale(coeffs[u]);
+
+  for (v=0; v<=N-1; v++){
+    for (u=0; u<=M-1; u++)
+       dct_NxN_tmp[u] = coeffs[u][v];
+
+    fct_noscale(dct_NxN_tmp);
+    for (u=0; u<=M-1; u++)
+      coeffs[u][v] = dct_NxN_tmp[u]*two_over_sqrtncolsnrows;
+  }
+}
+
+void idct_inplace_NxN(double **coeffs) {
+ int u,v;
+ double two_over_sqrtncolsnrows = 2.0/sqrt((double) N*M);
+
+  for (u=0; u<=M-1; u++)
+    ifct_noscale(coeffs[u]);
+
+  for (v=0; v<=N-1; v++) {
+    for (u=0; u<=M-1; u++)
+       dct_NxN_tmp[u] = coeffs[u][v];
+
+    ifct_noscale(dct_NxN_tmp);
+    for (u=0; u<=M-1; u++)
+       coeffs[u][v] = dct_NxN_tmp[u]*two_over_sqrtncolsnrows;
+  }
+
+}
+
+double **dct_NxM_costable_x = NULL;
+double **dct_NxM_costable_y = NULL;
+
+void init_dct_NxM(int cols, int rows) {
+  int i, j;
+  double cx = sqrt(2.0 / cols);
+  double cy = sqrt(2.0 / rows);
+
+#ifdef DEBUG
+  if (cols <= 0 || rows <= 0) {
+    fprintf(stderr, "init_dct_NxM(): dimensions out of range\n");
+    exit(1);
+  }
+#endif
+
+  if (dct_NxM_costable_x && N != cols) {
+    free_coeffs(dct_NxM_costable_x);
+    dct_NxM_costable_x = NULL;
+  }
+
+  if (dct_NxM_costable_y && M != rows) {
+    free_coeffs(dct_NxM_costable_y);
+    dct_NxM_costable_y = NULL;
+  }
+
+  if (!dct_NxM_costable_x)
+    dct_NxM_costable_x = alloc_coeffs(cols, cols);
+  if (!dct_NxM_costable_y)
+    dct_NxM_costable_y = alloc_coeffs(rows, rows);
+
+  N = cols;
+  M = rows;
+
+  for (i = 0; i < cols; i++) {
+    for (j = 0; j < cols; j++) {
+      dct_NxM_costable_x[i][j] = cx * cos((M_PI * ((2*i + 1) * j)) / (double) (2 * N));
+    }
+  }
+
+  for (i = 0; i < rows; i++) {
+    for (j = 0; j < rows; j++) {
+      dct_NxM_costable_y[i][j] = cy * cos((M_PI * ((2*i + 1) * j)) / (double) (2 * M));
+    }
+  }
+}
+
+void fdct_NxM(gray **pixels, double **dcts) {
+  int x, y;
+  int i, j;
+  double t;
+  double cx0 = sqrt(1.0 / N);
+  double cy0 = sqrt(1.0 / M);
+
+  t = 0.0;
+  for (x = 0; x < N; x++)
+    for (y = 0; y < M; y++)
+      t += ((int) pixels[y][x] - 128);
+  dcts[0][0] = cx0 * cy0 * t;
+
+  for (i = 1; i < N; i++) {
+    t = 0.0;
+    for (x = 0; x < N; x++)
+      for (y = 0; y < M; y++)
+        t += ((int) pixels[y][x] - 128) * dct_NxM_costable_x[x][i];
+    dcts[0][i] = cy0 * t;
+  }
+
+  for (j = 1; j < M; j++) {
+    t = 0.0;
+    for (x = 0; x < N; x++)
+      for (y = 0; y < M; y++)
+        t += ((int) pixels[y][x] - 128) * dct_NxM_costable_y[y][j];
+    dcts[j][0] = cx0 * t;
+  }
+
+  for (i = 1; i < N; i++)
+    for (j = 1; j < M; j++) {
+      t = 0.0;
+      for (x = 0; x < N; x++)
+        for (y = 0; y < M; y++)
+          t += ((int) pixels[y][x] - 128) * dct_NxM_costable_x[x][i] * dct_NxM_costable_y[y][j];
+      dcts[j][i] = t;
+    }
+}
+
+void idct_NxM(double **dcts, gray **pixels) {
+  int x, y;
+  int i, j;
+  double cx0 = sqrt(1.0 / N);
+  double cy0 = sqrt(1.0 / M);
+  double t;
+
+  for (x = 0; x < N; x++) {
+    for (y = 0; y < M; y++) {
+
+      t = cx0 * cy0 * dcts[0][0];
+
+      for (i = 1; i < N; i++)
+        t += cy0 * dcts[0][i] * dct_NxM_costable_x[x][i];
+
+      for (j = 1; j < M; j++)
+        t += cx0 * dcts[j][0] * dct_NxM_costable_y[y][j];
+
+      for (i = 1; i < N; i++)
+        for (j = 1; j < M; j++)
+          t += dcts[j][i] * dct_NxM_costable_x[x][i] * dct_NxM_costable_y[y][j];
+
+      pixels[y][x] = PIXELRANGE((int) (t + 128.5));
+    }
+  }
+}
+
+double C[NJPEG][NJPEG];
+double Ct[NJPEG][NJPEG];
+int Quantum[NJPEG][NJPEG];
+
+void init_quantum_8x8(int quality) {
+  int i;
+  int j;
+
+  for (i = 0; i < NJPEG; i++)
+    for ( j = 0 ; j < NJPEG ; j++ )
+      Quantum[ i ][ j ] = 1 + ( ( 1 + i + j )  * quality );
+}
+
+void init_quantum_JPEG_lumin(int quality) {
+  int i;
+  int j;
+
+  if (quality < 50)
+    quality = 5000 / quality;
+  else
+    quality = 200 - quality * 2;
+
+  for (i = 0; i < NJPEG; i++)
+    for (j = 0 ; j < NJPEG ; j++)
+      if (quality)
+        Quantum[i][j] = (JPEG_lumin_quant_table[i][j] * quality + 50) / 100;
+      else
+        Quantum[i][j] = JPEG_lumin_quant_table[i][j];
+}
+
+void init_quantum_JPEG_chromin(int quality) {
+  int i;
+  int j;
+
+  if (quality < 50)
+    quality = 5000 / quality;
+  else
+    quality = 200 - quality * 2;
+
+  for (i = 0; i < NJPEG; i++)
+    for (j = 0 ; j < NJPEG ; j++)
+      if (quality)
+        Quantum[i][j] = (JPEG_lumin_quant_table[i][j] * quality + 50) / 100;
+      else
+        Quantum[i][j] = JPEG_lumin_quant_table[i][j];
+}
+
+void quantize_8x8(double **transform) {
+  int i;
+  int j;
+
+  for (i = 0; i < NJPEG; i++)
+    for (j = 0; j < NJPEG; j++)
+      transform[i][j] = ROUND(transform[i][j] / Quantum[i][j]);
+}
+
+void dequantize_8x8(double **transform) {
+  int i;
+  int j;
+
+  for (i = 0; i < NJPEG; i++)
+    for (j = 0; j < NJPEG; j++)
+      transform[i][j] = ROUND(transform[i][j] * Quantum[i][j]);
+}
+
+void init_dct_8x8() {
+  int i;
+  int j;
+  double pi = atan( 1.0 ) * 4.0;
+
+  for ( j = 0 ; j < NJPEG ; j++ ) {
+    C[ 0 ][ j ] = 1.0 / sqrt( (double) NJPEG );
+    Ct[ j ][ 0 ] = C[ 0 ][ j ];
+  }
+
+  for ( i = 1 ; i < NJPEG ; i++ )
+    for ( j = 0 ; j < NJPEG ; j++ ) {
+      C[ i ][ j ] = sqrt( 2.0 / NJPEG ) * cos( pi * ( 2 * j + 1 ) * i / ( 2.0 * NJPEG ) );
+      Ct[ j ][ i ] = C[ i ][ j ];
+    }
+}
+
+/*
+ * The Forward DCT routine implements the matrix function:
+ *
+ *                     DCT = C * pixels * Ct
+ */
+
+void fdct_8x8(gray **input, double **output) {
+    double temp[NJPEG][NJPEG];
+    double temp1;
+    int i;
+    int j;
+    int k;
+
+/*  MatrixMultiply( temp, input, Ct ); */
+    for ( i = 0 ; i < NJPEG ; i++ ) {
+        for ( j = 0 ; j < NJPEG ; j++ ) {
+            temp[ i ][ j ] = 0.0;
+            for ( k = 0 ; k < NJPEG ; k++ )
+                 temp[ i ][ j ] += ( (int) input[ i ][ k ]) *
+                                   Ct[ k ][ j ];
+        }
+    }
+
+/*  MatrixMultiply( output, C, temp ); */
+    for ( i = 0 ; i < NJPEG ; i++ ) {
+        for ( j = 0 ; j < NJPEG ; j++ ) {
+            temp1 = 0.0;
+            for ( k = 0 ; k < NJPEG ; k++ )
+                temp1 += C[ i ][ k ] * temp[ k ][ j ];
+            output[ i ][ j ] = temp1;
+        }
+    }
+}
+
+void fdct_block_8x8(gray **input, int col, int row, double **output) {
+  int i, j;
+  gray *input_array[NJPEG];
+
+  for (i = 0; i < NJPEG; i++)
+    input_array[i] = &input[row + i][col];
+
+  fdct_8x8(input_array, output);
+}
+
+/*
+ * The Inverse DCT routine implements the matrix function:
+ *
+ *                     pixels = C * DCT * Ct
+ */
+
+void idct_8x8(double **input, gray **output) {
+    double temp[ NJPEG ][ NJPEG ];
+    double temp1;
+    int i;
+    int j;
+    int k;
+
+/*  MatrixMultiply( temp, input, C ); */
+    for ( i = 0 ; i < NJPEG ; i++ ) {
+        for ( j = 0 ; j < NJPEG ; j++ ) {
+            temp[ i ][ j ] = 0.0;
+            for ( k = 0 ; k < NJPEG ; k++ )
+                temp[ i ][ j ] += input[ i ][ k ] * C[ k ][ j ];
+        }
+    }
+
+/*  MatrixMultiply( output, Ct, temp ); */
+    for ( i = 0 ; i < NJPEG ; i++ ) {
+        for ( j = 0 ; j < NJPEG ; j++ ) {
+            temp1 = 0.0;
+            for ( k = 0 ; k < NJPEG ; k++ )
+                temp1 += Ct[ i ][ k ] * temp[ k ][ j ];
+            output[i][j] = PIXELRANGE(ROUND(temp1));
+        }
+    }
+}
+
+void idct_block_8x8(double **input, gray **output, int col, int row) {
+  int i, j;
+  gray *output_array[NJPEG];
+
+  for (i = 0; i < NJPEG; i++)
+    output_array[i] = &output[row + i][col];
+
+  idct_8x8(input, output_array);
+}
+
+int is_middle_frequency_coeff_8x8(int coeff) {
+  switch (coeff) {
+    case 3:
+    case 10:
+    case 17:
+    case 24:
+      return 1;
+    case 4:
+    case 11:
+    case 18:
+    case 25:
+    case 32:
+      return 2;
+    case 5:
+    case 12:
+    case 19:
+    case 26:
+    case 33:
+    case 40:
+      return 3;
+    case 13:
+    case 20:
+    case 27:
+    case 34:
+    case 41:
+      return 4;
+    case 28:
+    case 35:
+      return 5;
+    default:
+      return 0;
+  }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Meerwald/dct.h	Sun Aug 12 13:14:34 2007 +0200
@@ -0,0 +1,44 @@
+#ifndef DCT_H
+#define DCT_H
+
+#include "wm.h"
+#include "coeff.h"
+#ifdef __cplusplus
+extern "C" {
+#endif
+#include "pgm.h"
+#ifdef __cplusplus
+}
+#endif
+
+extern int N;
+extern int M;
+
+void init_dct_NxM(int width, int height);
+void fdct_NxM(gray **pixels, double **dcts);
+void idct_NxM(double **dcts, gray **pixels);
+
+void init_dct_NxN(int width, int height);
+void fdct_NxN(gray **pixels, double **dcts);
+void idct_NxN(double **dcts, gray **pixels);
+void fdct_inplace_NxN(double **coeffs);
+void idct_inplace_NxN(double **coeffs);
+
+/*
+ * 'NJPEG' defines the JPEG's DCT block size (8x8)
+ */
+#define NJPEG 8
+
+void init_quantum_8x8(int quality);
+void init_quantum_JPEG_lumin(int quality);
+void init_quantum_JPEG_chromin(int quality);
+void quantize_8x8(double **transform);
+void dequantize_8x8(double **transform);
+void init_dct_8x8();
+void fdct_8x8(gray **input, double **output);
+void fdct_block_8x8(gray **input, int col, int row, double **output);
+void idct_8x8(double **input, gray **output);
+void idct_block_8x8(double **input, gray **output, int col, int row);
+int is_middle_frequency_coeff_8x8(int coeff);
+
+#endif
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Meerwald/dwt.c	Sun Aug 12 13:14:34 2007 +0200
@@ -0,0 +1,343 @@
+#include "wm.h"
+#include "dwt.h"
+
+char filter_file[MAXPATHLEN] = "";
+AllFilters dwt_allfilters;
+FilterGH *dwt_filters = NULL;
+int dwt_method;
+int dwt_cols;
+int dwt_rows;
+int dwt_levels;
+int dwt_filter;
+
+void init_dwt(int cols, int rows, const char *filter_name, int filter, int level, int method) {
+  int i;
+
+  if (strcmp(filter_file, filter_name)) {
+    if (filter_name)
+      strcpy(filter_file, filter_name);
+    else
+      strcpy(filter_file, "filter.dat");
+    /* memory leak here - there is no function unload_filters() */
+    dwt_allfilters = load_filters(filter_file);
+    if (!dwt_allfilters) {
+      fprintf(stderr, "init_dwt(): unable to open filter definition file %s\n", filter_file);
+      return;
+    }
+  }
+
+#ifdef DEBUG
+  if (level <= 0 || level > rint(log(MIN(cols, rows))/log(2.0)) - 2) {
+    fprintf(stderr, "init_dwt(): level parameter does not match image width/height\n");
+    return;
+  }
+#endif
+
+  if (dwt_filters && level != dwt_levels) {
+    free(dwt_filters);
+    dwt_filters = NULL;
+  }
+
+  dwt_levels = level;
+
+  if (!dwt_filters)
+    dwt_filters = calloc(level + 1, sizeof(FilterGH));
+
+  for (i = 0; i < level + 1; i++)
+    dwt_filters[i] = (dwt_allfilters->filter)[filter];
+
+  dwt_filter = filter;
+  dwt_method = method;
+  dwt_cols = cols;
+  dwt_rows = rows;
+}
+
+Image_tree fdwt(gray **pixels) {
+  Image image;
+  Image_tree tree;
+  int i, j;
+
+  image = new_image(dwt_cols, dwt_rows);
+
+  for (i = 0; i < dwt_rows; i++)
+    for (j = 0; j < dwt_cols; j++)
+      set_pixel(image, j, i, pixels[i][j]);
+
+  tree = wavelettransform(image, dwt_levels, dwt_filters, dwt_method);
+  free_image(image);
+
+  return tree;
+}
+
+Image_tree fdwt_wp(gray **pixels) {
+  Image image;
+  Image_tree tree;
+  int i, j;
+
+  image = new_image(dwt_cols, dwt_rows);
+
+  for (i = 0; i < dwt_rows; i++)
+    for (j = 0; j < dwt_cols; j++)
+      set_pixel(image, j, i, pixels[i][j]);
+
+  tree = wavelettransform_wp(image, dwt_levels, dwt_filters, dwt_method);
+  free_image(image);
+
+  return tree;
+}
+
+void idwt(Image_tree dwts, gray **pixels) {
+  Image image;
+  int i, j;
+
+  image = inv_transform(dwts, dwt_filters, dwt_method + 1);
+
+  for (i = 0; i < dwt_rows; i++)
+    for (j = 0; j < dwt_cols; j++)
+      pixels[i][j] = PIXELRANGE((int) (get_pixel(image, j, i) + 0.5));
+
+  free_image(image);
+}
+
+void idwt_wp(Image_tree dwts, gray **pixels) {
+  Image image;
+  int i, j;
+
+  image = inv_transform(dwts, dwt_filters, dwt_method + 1);
+
+  for (i = 0; i < dwt_rows; i++)
+    for (j = 0; j < dwt_cols; j++)
+      pixels[i][j] = PIXELRANGE((int) (get_pixel(image, j, i) + 0.5));
+
+  free_image(image);
+}
+
+int gen_pollen_filter(double *filter, double alpha, double beta, int which) {
+  int i, j, k, filterlength;
+  double tf[6];
+
+  /* parameter alpha, beta have to be in range -Pi .. Pi */
+  if (alpha < -M_PI || alpha >= M_PI) {
+    fprintf(stderr, "alpha %f out of range\n", alpha);
+    return -1;
+  }
+
+  if (beta < -M_PI || beta >= M_PI) {
+    fprintf(stderr, "beta %f out of range\n", beta);
+    return -1;
+  }
+
+  /* generate Pollen filter coefficients, see http://www.dfw.net/~cody for details */
+  tf[0] = ((1.0 + cos(alpha) + sin(alpha)) * (1.0 - cos(beta) - sin(beta)) + 2.0 * sin(beta) * cos(alpha)) / 4.0;
+  tf[1] = ((1.0 - cos(alpha) + sin(alpha)) * (1.0 + cos(beta) - sin(beta)) - 2.0 * sin(beta) * cos(alpha)) / 4.0;
+  tf[2] = (1.0 + cos(alpha - beta) + sin(alpha - beta)) / 2.0;
+  tf[3] = (1.0 + cos(alpha - beta) - sin(alpha - beta)) / 2.0;
+  tf[4] = 1.0 - tf[0] - tf[2];
+  tf[5] = 1.0 - tf[1] - tf[3];
+
+  /* set close-to-zero filter coefficients to zero */
+  for (i = 0; i < 6; i++)
+    if (fabs(tf[i]) <  1.0e-15) tf[i] = 0.0;
+
+  /* find the first non-zero wavelet coefficient */
+  i = 0;
+  while (tf[i] == 0.0) i++;
+
+  /* find the last non-zero wavelet coefficient */
+  j = 5;
+  while (tf[j] == 0.0) j--;
+
+  filterlength = j - i + 1;
+  for (k = 0; k < filterlength; k++)
+    switch (which) {
+        case FILTERH:
+          filter[k] = tf[j--] / 2.0;
+          break;
+        case FILTERG:
+          filter[k] = (double) (((i & 0x01) * 2) - 1) * tf[i++] / 2.0;
+          break;
+        case FILTERHi:
+          filter[k] = tf[j--];
+          break;
+        case FILTERGi:
+          filter[k] = (double) (((i & 0x01) * 2) - 1) * tf[i++];
+          break;
+        default:
+          return -1;
+    }
+
+  while (k < 6)
+    filter[k++] = 0.0;
+
+  return filterlength;
+}
+
+void dwt_pollen_filter(double alpha, double beta) {
+  FilterGH filter;  
+  int i;
+
+  filter = malloc(sizeof(struct FilterGHStruct));
+#ifdef DEBUG
+  if (!filter) {
+    fprintf(stderr, "dwt_pollen_filter(): malloc failed()\n");
+    return;
+  }
+#endif
+
+  filter->type = FTOther;
+  filter->name = "pollen";
+
+  filter->g = new_filter(6);
+  filter->g->type = FTSymm;
+  filter->g->hipass = 1;
+  filter->g->len = gen_pollen_filter(filter->g->data, alpha, beta, FILTERG);
+  filter->g->start = -filter->g->len / 2;
+  filter->g->end = filter->g->len / 2 - 1;
+
+  filter->h = new_filter(6);
+  filter->h->type = FTSymm;
+  filter->h->hipass = 0;
+  filter->h->len = gen_pollen_filter(filter->h->data, alpha, beta, FILTERH);
+  filter->h->start = -filter->h->len / 2;
+  filter->h->end = filter->h->len / 2 - 1;
+
+  filter->gi = new_filter(6);
+  filter->gi->type = FTSymm;
+  filter->gi->hipass = 1;
+  filter->gi->len = gen_pollen_filter(filter->gi->data, alpha, beta, FILTERGi);
+  filter->gi->start = -filter->gi->len / 2;
+  filter->gi->end = filter->gi->len / 2 - 1;
+        
+  filter->hi = new_filter(6);
+  filter->hi->type = FTSymm;
+  filter->hi->hipass = 0;
+  filter->hi->len = gen_pollen_filter(filter->hi->data, alpha, beta, FILTERHi);
+  filter->hi->start = -filter->hi->len / 2;
+  filter->hi->end = filter->hi->len / 2 - 1;
+  
+#ifdef DEBUG
+  if (dwt_levels <= 0) {
+    fprintf(stderr, "dwt_pollen_filter(): level invalid - set to zero\n");
+    return;
+  }
+#endif
+
+#ifdef DEBUG
+  if (!dwt_filters) {
+    fprintf(stderr, "dwt_pollen_filter(): wm_dwt not initialized, call init_dwt() first\n");
+    return;
+  }
+#endif
+
+  for (i = 0; i < dwt_levels + 1; i++)
+    dwt_filters[i] = filter;
+}
+
+int gen_param_filter(double *filter, int n, double alpha[], int which) {
+  int i, j, k, filterlength;
+  double *tf, *t;
+
+  tf = malloc(2 * (n + 1) * sizeof(double));
+  t = malloc(2 * (n + 1) * sizeof(double));
+  if (!tf) {
+    fprintf(stderr, "gen_param_filter(): malloc() failed\n");
+    return -1;
+  }
+
+  tf[0] = 1.0 / sqrt(2.0);
+  tf[1] = 1.0 / sqrt(2.0);
+
+  for (k = 0; k < n; k++) {
+    for (i = 0; i < 2 * (k + 2); i++) {
+
+#define H(X) (((X) < 0 || (X) >= 2 * (k + 1)) ? 0.0 : tf[X])
+
+       t[i] = 0.5 * (H(i - 2) + H(i) +
+                     cos(alpha[k]) * (H(i - 2) - H(i)) +
+                     (i & 1 ? -1.0 : 1.0) * sin(alpha[k]) * (H(2 * (k + 2) - i - 1) - H(2 * (k + 2) - i - 3)));
+    }
+    for (i = 0; i < 2 * (k + 2); i++) tf[i] = t[i];
+  }
+
+  /* set close-to-zero filter coefficients to zero */
+  for (i = 0; i < 2 * (n + 1) ; i++)
+    if (fabs(tf[i]) <  1.0e-15) tf[i] = 0.0;
+
+  /* find the first non-zero wavelet coefficient */
+  i = 0;
+  while (tf[i] == 0.0) i++;
+        
+  /* find the last non-zero wavelet coefficient */
+  j = 2 * (n + 1) - 1;
+  while (tf[j] == 0.0) j--;
+
+  filterlength = j - i + 1;
+  for (k = 0; k < filterlength; k++)
+    switch (which) {
+        case FILTERG:
+        case FILTERGi:
+          filter[k] = (double) (((i+1 & 0x01) * 2) - 1) * tf[i++];
+          break;
+        case FILTERH:
+        case FILTERHi:
+          filter[k] = tf[j--];
+          break;
+        default: 
+          return -1;
+    }
+
+  while (k < 2 * (n + 1)) 
+    filter[k++] = 0.0;
+
+  return filterlength;
+}
+
+void dwt_param_filter(double alpha[], int n) {
+  FilterGH filter;  
+  int i;
+
+  filter = malloc(sizeof(struct FilterGHStruct));
+#ifdef DEBUG
+  if (!filter) {
+    fprintf(stderr, "dwt_param_filter(): malloc failed()\n");
+    return;
+  }
+#endif
+
+  filter->type = FTOrtho;
+  filter->name = "param";
+
+  filter->g = new_filter(2 * (n + 1));
+  filter->g->type = FTSymm;
+  filter->g->hipass = 1;
+  filter->g->len = gen_param_filter(filter->g->data, n, alpha,  FILTERG);
+  filter->g->start = -filter->g->len / 2;
+  filter->g->end = filter->g->len / 2 - 1;
+
+  filter->h = new_filter(2 * (n + 1));
+  filter->h->type = FTSymm;
+  filter->h->hipass = 0;
+  filter->h->len = gen_param_filter(filter->h->data, n, alpha,  FILTERH);
+  filter->h->start = -filter->h->len / 2;
+  filter->h->end = filter->h->len / 2 - 1;
+
+#ifdef DEBUG
+  if (dwt_levels <= 0) {
+    fprintf(stderr, "dwt_pollen_filter(): level invalid - set to zero\n");
+    return;
+  }
+#endif
+
+#ifdef DEBUG
+  if (!dwt_filters) {
+    fprintf(stderr, "dwt_pollen_filter(): wm_dwt not initialized, call init_dwt() first\n");
+    return;
+  }
+#endif
+
+  for (i = 0; i < dwt_levels + 1; i++)
+    dwt_filters[i] = filter;
+}
+
+void done_dwt() {
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Meerwald/dwt.h	Sun Aug 12 13:14:34 2007 +0200
@@ -0,0 +1,24 @@
+#ifndef DWT_H
+#define DWT_H
+
+#include "wm.h"
+#include "pgm.h"
+#include "wavelet.h"
+
+#define FILTERG 1
+#define FILTERH 2
+#define FILTERGi 3
+#define FILTERHi 4
+
+void init_dwt(int cols, int rows, const char *filter_name, int filter, int level, int method);
+Image_tree fdwt(gray **input);
+Image_tree fdwt_wp(gray **input);
+void idwt(Image_tree dwts, gray **output);
+void idwt_wp(Image_tree dwts, gray **output);
+int gen_pollen_filter(double *filter, double alpha, double beta, int which);
+void dwt_pollen_filter(double alpha, double beta);
+int gen_param_filter(double *filter, int n, double alpha[], int which);
+void dwt_param_filter(double alpha[], int n);
+void done_dwt();
+
+#endif
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Meerwald/dwt_util.c	Sun Aug 12 13:14:34 2007 +0200
@@ -0,0 +1,159 @@
+#include "wm.h"
+#include "dwt_util.h"
+#include <ctype.h>
+
+void copy_coeffs_from_dwt(double ** block_coeffs, double ** dwt_coeffs,
+int level, int band, int width, int height) {
+  int i, j;
+  int size = width >> level;
+  int h = (band > 2) ? size : 0;
+  int w = (band & 1) ? 0 : size;
+
+  for (i = 0; i < size; i++)
+    for (j = 0; j < size; j++)
+      block_coeffs[i][j] = dwt_coeffs[h + i][w + j];
+}
+
+void copy_coeffs_to_dwt(double ** dwt_coeffs, double ** block_coeffs,
+int level, int band, int width, int height) {
+  int i, j;
+  int size = width >> level;
+  int h = (band > 2) ? size : 0;
+  int w = (band & 1) ? 0 : size;
+
+  for (i = 0; i < size; i++)
+    for (j = 0; j < size; j++)
+      dwt_coeffs[h + i][w + j] = block_coeffs[i][j];
+}
+
+char *subband_name(int type) {
+  switch (type) {
+    case LL: return "LL";
+    case HL: return "HL";
+    case LH: return "LH";
+    case HH: return "HH";
+    default: return "XX";
+  }
+}
+
+int subband_in_list(char *list, int type, int level) {
+  return 1;
+}
+
+int subband_wp_in_list(char *list, char *name) {
+  return 1;
+}
+
+int calc_subband_wp_level(char *name){
+  return strlen(name);
+}
+
+void calc_subband_location(int cols, int rows, int type, int level, int *col, int *row) {
+  *col = *row = 0;
+
+  if (level <= 0 || level > find_deepest_level(cols, rows) - 1) return;
+
+  switch (type) {
+    case LL:
+      break;
+    case HL:
+      *col = 0;
+      *row = rows >> level;
+      break;
+    case LH:
+      *col =  cols >> level;
+      *row = 0;
+      break;
+    case HH:
+      *col = cols >> level;
+      *row = rows >> level;
+      break;
+    default:
+      break;
+  }
+}
+
+void calc_subband_wp_location(int cols, int rows, char *name, int *col, int *row) {
+  char *p = name;
+  int level = 0;
+  *col = *row = 0;
+
+  while (*p) {
+    level++;
+    switch (toupper(*p)) {
+      case 'A':
+        break;
+      case 'H':
+        *col += (cols >> level);
+        break;
+      case 'V':
+        *row += (rows >> level);
+        break;
+      case 'D':
+        *col += (cols >> level);
+        *row += (rows >> level);
+        break;
+      default:
+        break;
+    }
+    p++;
+  }
+}
+
+Pixel *get_dwt_data(Image_tree dwt, int level, int type) {
+  return get_dwt_image(dwt, level, type)->data;
+}
+
+Image get_dwt_image(Image_tree dwt, int level, int type) {
+  return get_dwt_subband(dwt, level, type)->image;
+}
+
+Image_tree get_dwt_subband(Image_tree dwt, int level, int type) {
+  while (--level)
+    dwt = dwt->coarse;
+
+  switch (type) {
+    case LL: 
+      return dwt->coarse;
+    case HL: 
+      return dwt->vertical;
+    case LH: 
+      return dwt->horizontal;
+    case HH: 
+      return dwt->diagonal;
+  }
+
+  return NULL;
+}
+
+Pixel get_dwt_coeff(Image_tree dwt, int level, int type, int coeff) {
+  return get_dwt_data(dwt, level, type)[coeff];
+}
+
+Pixel get_dwt_location(Image_tree dwt, int level, int type, int col, int row) {
+  return get_pixel(get_dwt_image(dwt, level, type), col, row);
+}
+
+static void calc__subband(Image_tree p, Image_tree q, double *min, double *max, double *error) {
+  int i;
+  
+  if (!p || !q) return;
+  
+  *error = 0;
+  *min = *max = fabs(p->image->data[0] - q->image->data[0]);
+  for (i = 0; i < p->image->size; i++) {
+    double diff = fabs(p->image->data[i] - q->image->data[i]);
+    
+    *error += sqr(diff);
+    if (diff < *min) *min = diff;
+    if (diff > *max) *max = diff;
+  }
+}
+
+void calc_subband(Image_tree p, Image_tree q, int type, double *min, double *max, double *error) {
+  calc__subband(p, q, min, max, error);
+}
+
+void calc_subband_wp(Image_tree p, Image_tree q, char *name, double *min, double *max, double *error) {
+  calc__subband(p, q, min, max, error);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Meerwald/dwt_util.h	Sun Aug 12 13:14:34 2007 +0200
@@ -0,0 +1,41 @@
+#ifndef DWT_UTIL_H
+#define DWT_UTIL_H
+
+#include "dwt.h"
+
+#define LL 1
+#define LH 2
+#define HL 3
+#define HH 4
+
+#define COARSE LL
+#define HORIZONTAL LH
+#define VERTICAL HL
+#define DIAGONAL HH
+
+void copy_coeffs_from_dwt(double ** block_coeffs, double ** dwt_coeffs,
+  int level, int band, int width, int height);
+
+void copy_coeffs_to_dwt(double ** dwt_coeffs, double ** block_coeffs,
+  int level, int band, int width, int height);
+
+char *subband_name(int type);
+
+int subband_in_list(char *list, int type, int level);
+int subband_wp_in_list(char *list, char *name);
+
+void calc_subband_location(int cols, int rows, int type, int level, int *col, int *row);
+void calc_subband_wp_location(int cols, int rows, char *name, int *col, int *row);
+int calc_subband_wp_level(char *name);
+
+Pixel *get_dwt_data(Image_tree dwt, int level, int type);
+Image get_dwt_image(Image_tree dwt, int level, int type);
+Image_tree get_dwt_subband(Image_tree dwt, int level, int type);
+Pixel get_dwt_coeff(Image_tree dwt, int level, int type, int coeff);
+Pixel get_dwt_location(Image_tree dwt, int level, int type, int col, int row);
+
+void calc_subband(Image_tree p, Image_tree q, int type, double *min, double *max, double *error);
+void calc_subband_wp(Image_tree p, Image_tree q, char *name, double *min, double *max, double *error);
+
+
+#endif
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Meerwald/filter.dat	Sun Aug 12 13:14:34 2007 +0200
@@ -0,0 +1,774 @@
+{
+	Name biortho nr. 1
+	Type biorthogonal
+	{
+		Type symm
+		Length 3
+		Start 0
+		End 2
+		0.353553
+		-0.707107
+		0.353553
+	}
+	{
+		Type symm
+		Length 5
+		Start -2 
+		End 2
+		-0.176777
+		0.353553
+		1.060660
+		0.353553
+		-0.176777
+	}
+	{
+		Type symm
+		Length 5
+		Start -1 
+		End 3
+		0.176777
+		0.353553
+		-1.060660
+		0.353553
+		0.176777
+	}
+	{
+		Type symm
+		Length 3
+		Start -1 
+		End 1
+		0.353553
+		0.707107
+		0.353553
+	}
+}
+
+{
+	Name biortho nr. 2
+	Type biorthogonal
+	{
+		Type symm
+		Length 7
+		Start -4
+		End 2
+		-0.064539
+		0.040689
+		0.418092
+		-0.788486
+		0.418092
+		0.040689
+		-0.064539
+	}
+	{
+		Type symm
+		Length 9
+		Start -4
+		End 4
+		0.037828
+		-0.023849
+		-0.110624
+		0.377402
+		0.852699
+		0.377402
+		-0.110624
+		-0.023849
+		0.037828
+	}
+	{
+		Type symm
+		Length 9
+		Start -5
+		End 3
+		-0.037828
+		-0.023849
+		0.110624
+		0.377402
+		-0.852699
+		0.377402
+		0.110624
+		-0.023849
+		-0.037828
+	}
+	{
+		Type symm
+		Length 7
+		Start -3
+		End 3
+		-0.064539
+		-0.040689
+		0.418092
+		0.788486
+		0.418092
+		-0.040689
+		-0.064539
+	}
+}	
+{
+	Name Daubechies 4
+	Type orthogonal
+	{
+		Type symm
+		Length 4
+		Start -1
+		End 2
+		
+		-0.129409522551
+		-0.224143868042
+		0.836516303737
+		-0.482962913144
+
+	}
+	{
+		Type symm
+		Length 4
+		Start -1
+		End 2
+
+		0.482962913144
+		0.836516303737
+		0.224143868042
+		-0.129409522551
+		
+	}
+}
+
+{
+	Name Daubechies 6
+	Type orthogonal
+	{
+		Type symm
+		Length 6
+		Start -3
+		End 2
+
+	 0.035226291882
+	 0.085441273882
+	-0.135011020010
+	-0.459877502118
+	 0.806891509311
+	-0.332670552950
+		
+
+	}
+	{
+		Type symm
+		Length 6
+		Start -1
+		End 4
+
+	 0.332670552950
+	 0.806891509311
+	 0.459877502118
+	-0.135011020010
+	-0.085441273882
+	 0.035226291882
+		
+	}
+}
+{
+	Name Daubechies 8
+	Type orthogonal
+	{
+		Type symm
+		Length 8
+		Start -1
+		End 6
+
+
+	-0.010597401785
+	-0.032883011667
+	 0.030841381836
+	 0.187034811719
+	-0.027983769417
+	-0.630880766793
+	 0.714846570553
+	-0.230377813309
+
+	}
+	{
+		Type symm
+		Length 8
+		Start -1
+		End 6
+
+	 0.230377813309
+    	 0.714846570553
+	 0.630880766793
+	-0.027983769417
+	-0.187034811719
+	 0.030841381836
+	 0.032883011667
+	-0.010597401785
+		
+	}
+}
+{
+	Name Daubechies 10
+	Type orthogonal
+	{
+		Type symm
+		Length 10
+		Start -2
+		End 7
+
+	 0.0033357252854738
+	 0.0125807519990820
+	-0.0062414902127983
+	-0.0775714938400459
+	-0.0322448695846381
+	 0.2422948870663823
+	 0.1384281459013203
+	-0.7243085284377726
+	 0.6038292697971895
+	-0.1601023979741929
+
+	}
+	{
+		Type symm
+		Length 10
+		Start -2
+		End 7
+
+	 0.1601023979741929
+	 0.6038292697971895
+	 0.7243085284377726
+	 0.1384281459013203
+	-0.2422948870663823
+	-0.0322448695846381
+	 0.0775714938400459
+	-0.0062414902127983
+	-0.0125807519990820
+	 0.0033357252854738
+		
+	}
+}
+
+{
+	Name Daubechies 12
+	Type orthogonal
+	{
+		Type symm
+		Length 12
+		Start -1
+		End 10
+
+	-0.0010773010853085
+	-0.0047772575119455
+	 0.0005538422011614
+	 0.0315820393184862
+	 0.0275228655303053
+	-0.0975016055873225
+	-0.1297668675672625
+	 0.2262646939654400
+	 0.3152503517091982
+	-0.7511339080210959
+	 0.4946238903984533
+	-0.1115407433501095
+
+	}
+	{
+		Type symm
+		Length 12
+		Start -1
+		End 10
+
+	 0.1115407433501095
+	 0.4946238903984533
+	 0.7511339080210959
+	 0.3152503517091982
+	-0.2262646939654400
+	-0.1297668675672625
+	 0.0975016055873225
+	 0.0275228655303053
+	-0.0315820393184862
+	 0.0005538422011614
+	 0.0047772575119455
+	-0.0010773010853085
+		
+	}
+}
+
+{
+	Name Daubechies 14
+	Type orthogonal
+	{
+		Type symm
+		Length 14
+		Start -1
+		End 12
+
+		0.0003537138
+		0.001801640704
+		0.000429577973
+		-0.012550998556
+		-0.016574541631
+		0.038029936935
+		0.0806112609151
+		-0.071309219267
+		-0.224036184994
+		0.143906003929
+		0.469782287405
+		-0.729132090846
+		0.396539319482
+		-0.077852054085
+
+	}
+	{
+		Type symm
+		Length 14
+		Start -1
+		End 12
+
+		0.077852054085
+		0.396539319482
+		0.729132090846
+		0.469782287405
+		-0.143906003929
+		-0.224036184994
+		0.071309219267
+		0.0806112609151
+		-0.038029936935
+		-0.016574541631
+		0.012550998556
+		0.000429577973
+		-0.001801640704
+		0.0003537138
+
+	}
+}
+
+
+{
+	Name Daubechies 20
+	Type orthogonal
+	{
+		Type symm
+		Length 20
+		Start -1
+		End 18
+
+	-0.000013264203
+	-0.000093588670
+	-0.000116466855
+	 0.000685856695
+	 0.001992405295
+	 0.001395351747
+	-0.010733175483
+	-0.003606553567
+	 0.033212674059
+	 0.029457536822
+	-0.071394147166
+	-0.093057364604
+	 0.127369340336
+	 0.195946274377
+	-0.249846424327
+	-0.281172343661
+	 0.688459039454
+	-0.527201188932
+	 0.188176800078
+	-0.026670057901
+
+	}
+	{
+		Type symm
+		Length 20
+		Start -1
+		End 18
+
+	 0.026670057901
+	 0.188176800078
+	 0.527201188932
+	 0.688459039454
+	 0.281172343661
+	-0.249846424327
+	-0.195946274377
+	 0.127369340336
+	 0.093057364604
+	-0.071394147166
+	-0.029457536822
+	 0.033212674059
+	 0.003606553567
+	-0.010733175483
+	 0.001395351747
+	 0.001992405295
+	-0.000685856695
+	-0.000116466855
+	 0.000093588670
+	-0.000013264203
+	}
+}
+
+
+{
+	Name Beylkin 18
+	Type orthogonal
+	{
+		Type symm
+		Length 18
+		Start -1
+		End 16
+
+	0.00064048532852124535
+	0.0027360316262586061
+	0.0014842347824723461
+	-0.01004041184463199
+	-0.014365807968852611
+	0.017460408696028829
+	0.042916387274192273
+	-0.01967986604432212
+	-0.088543630622924835
+	0.017520746266529649
+	0.1555387318770938
+	-0.02690030880369032
+	-0.26449723144638482
+	0.1109275983482343
+	0.44971825114946867
+	-0.69982521405660059
+	0.42421536081296141
+	-0.099305765374353927
+
+	}
+	{
+		Type symm
+		Length 18
+		Start -1
+		End 16
+
+	0.099305765374353927
+	0.42421536081296141
+	0.69982521405660059
+	0.44971825114946867
+	-0.1109275983482343
+	-0.26449723144638482
+	0.02690030880369032
+	0.1555387318770938
+	-0.017520746266529649
+	-0.088543630622924835
+	0.01967986604432212
+	0.042916387274192273
+	-0.017460408696028829
+	-0.014365807968852611
+	0.01004041184463199
+	0.0014842347824723461
+	-0.0027360316262586061
+	0.00064048532852124535
+
+	}
+}
+
+
+{
+	Name Vaidyanathan 24
+	Type orthogonal
+	{
+		Type symm
+		Length 24
+		Start -1
+		End 22
+
+	0.045799334110976718
+	-0.25018412950466218
+	0.57279779321073432
+	-0.63560105987221494
+	0.20161216177530866
+	0.26349480248845991
+	-0.19445047176647817
+	-0.13508422712948126
+	0.13197166141697772
+	0.08392888436611283
+	-0.07770975090196941
+	-0.055892523691373548
+	0.03874261929341144
+	0.035470398607283453
+	-0.014853448005230099
+	-0.019687215010072714
+	0.003153847055897004
+	0.008839103408613878
+	0.00070813750405244471
+	-0.0028438345468355646
+	-0.00094489713632194927
+	0.00045395661963721929
+	0.00034363190482102919
+	0.000062906118190737523
+
+	}
+	{
+		Type symm
+		Length 24
+		Start -1
+		End 22
+
+	-0.000062906118190737523
+	0.00034363190482102919
+	-0.00045395661963721929
+	-0.00094489713632194927
+	0.0028438345468355646
+	0.00070813750405244471
+	-0.008839103408613878
+	0.003153847055897004
+	0.019687215010072714
+	-0.014853448005230099
+	-0.035470398607283453
+	0.03874261929341144
+	0.055892523691373548
+	-0.07770975090196941
+	-0.08392888436611283
+	0.13197166141697772
+	0.13508422712948126
+	-0.19445047176647817
+	-0.26349480248845991
+	0.20161216177530866
+	0.63560105987221494
+	0.57279779321073432
+	0.25018412950466218
+	0.045799334110976718
+	}
+}
+
+
+{
+	Name Coifman 6
+	Type orthogonal
+	{
+		Type symm
+		Length 6
+		Start -1
+		End 4
+
+		0.226584276197068560
+		-0.745687558934434280
+		0.607391641385684120
+		0.077161555495773498
+		-0.12696912539620520
+		0.038580777747886749
+		
+	}
+	{
+		Type symm
+		Length 6
+		Start -1
+		End 4
+
+		0.038580777747886749
+		-0.12696912539620520
+		-0.077161555495773498
+		0.607391641385684120
+		0.745687558934434280
+		0.226584276197068560
+	}
+}
+
+
+{
+	Name Coifman 12
+	Type orthogonal
+	{
+		Type symm
+		Length 12
+		Start -1
+		End 10
+
+		-0.000720549445369115120
+		0.00182320887091009920
+		0.00561143481936598850
+		-0.0236801719468767500
+		-0.0594344186464712400
+		0.0764885990782645940
+		0.417005184423777600
+		-0.812723635449606130
+		0.386110066823092900
+		0.0673725547222998740
+		-0.0414649367819664850
+		-0.0163873364631797850
+		
+	}
+	{
+		Type symm
+		Length 12
+		Start -1
+		End 10
+
+		0.0163873364631797850
+		-0.0414649367819664850
+		-0.0673725547222998740
+		0.386110066823092900
+		0.812723635449606130
+		0.417005184423777600
+		-0.0764885990782645940
+		-0.0594344186464712400
+		0.0236801719468767500
+		0.00561143481936598850
+		-0.00182320887091009920
+		-0.000720549445369115120
+
+	}
+}
+
+
+{
+	Name Coifman 18
+	Type orthogonal
+	{
+		Type symm
+		Length 18
+		Start -1
+		End 16
+
+		-0.000034599773197402695
+		0.000070983302505704928
+		0.00046621695982014403
+		-0.00111751877082696180
+		-0.0025745176881279692
+		0.0090079761367322896
+		0.0158805448636159010
+		-0.0345550275733444640
+		-0.082301927106320283
+		0.071799821619170590
+		0.428483476377618690
+		-0.793777222625620340
+		0.405176902409616790
+		0.0611233900029556980
+		-0.0657719112814312280
+		-0.0234526961421191030
+		0.00778259642567178690
+		0.00379351286437787590
+		
+	}
+	{
+		Type symm
+		Length 18
+		Start -1
+		End 16
+
+		-0.00379351286437787590
+		0.00778259642567178690
+		0.0234526961421191030
+		-0.0657719112814312280
+		-0.0611233900029556980
+		0.405176902409616790
+		0.793777222625620340
+		0.428483476377618690
+		-0.071799821619170590
+		-0.082301927106320283
+		0.0345550275733444640
+		0.0158805448636159010
+		-0.0090079761367322896
+		-0.0025745176881279692
+		0.00111751877082696180
+		0.00046621695982014403
+		-0.000070983302505704928
+		-0.000034599773197402695
+
+	}
+}
+
+{
+	Name Biorthogonal 1,3
+	Type biorthogonal
+	{
+		Type symm
+		Length 6
+		Start -1
+		End 4
+
+		-0.08838834764832
+		-0.08838834764832
+		0.707106781
+		-0.707106781
+		0.08838834764832
+		0.08838834764832
+		
+	}
+	{
+		Type symm
+		Length 2
+		Start 1
+		End 2
+		0.707106781
+		0.707106781
+
+	}
+
+	{
+		Type symm
+		Length 2
+		Start 1
+		End 2
+		0.707106781
+		-0.707106781
+	}
+	{
+		Type symm
+		Length 6
+		Start -1
+		End 4
+
+		-0.08838834764832
+		0.08838834764832
+		0.707106781
+		0.707106781
+		0.08838834764832
+		-0.08838834764832
+
+	}
+}
+
+{
+	Name Biorthogonal 1,5
+	Type biorthogonal
+	{
+		Type symm
+		Length 10
+		Start -1
+		End 8
+
+		0.01657281518406
+		0.01657281518406
+		-0.1215339780164
+		-0.1215339780164
+		0.707106781
+		-0.707106781
+		0.1215339780164
+		0.1215339780164
+		-0.01657281518406
+		-0.01657281518406
+
+	}
+	{
+		Type symm
+		Length 2
+		Start 3
+		End 4
+
+		0.707106781
+		0.707106781
+	}
+
+	{
+		Type symm
+		Length 2
+		Start 3
+		End 4
+
+		0.707106781
+		-0.707106781
+	}
+	{
+		Type symm
+		Length 10
+		Start -1
+		End 8
+
+		0.01657281518406
+		-0.01657281518406
+		-0.1215339780164
+		0.1215339780164
+		0.707106781
+		0.707106781
+		0.1215339780164
+		-0.1215339780164
+		-0.01657281518406
+		0.01657281518406
+		
+	}
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Meerwald/frid2_common.c	Sun Aug 12 13:14:34 2007 +0200
@@ -0,0 +1,220 @@
+#include "frid2_common.h"
+#include "signature.h"
+#include "wm.h"
+
+extern char *progname;
+
+void embed_low_freq(double **dcts, int cols, int rows, double alpha, int verbose) {
+  int n;
+  int row, col, dir;
+
+  n = 0;
+  row = col = 0;
+  dir = 1;
+  while (n < nbit_signature) {
+    double d, x;
+    int embed;
+    int out;
+
+    col -= dir;
+    row += dir;
+    if (col < 0) { dir = -1; col = 0; }
+    if (col >= cols) { dir = 1; col = cols - 1; row += 2; }
+    if (row < 0) { dir = 1; row = 0; }
+    if (row >= rows) { dir = -1; row = rows - 1; col += 2; }
+
+    d = dcts[row][col];
+    if (fabs(d) <= 1.0) {
+      if (verbose > 3)
+        fprintf(stderr, "%s: bit #%d - skipped (%d/%d)\n", progname, n, col, row);
+      continue;
+    }
+
+    embed = 2 * get_signature_bit(n) - 1;
+
+    x = (d > 0.0) ? 1.0 : -1.0;
+    out = 1;
+    while (fabs(x) < fabs(d)) {
+      x *= FORWARD_STEP(alpha);
+      out =- out;
+    }
+
+    if (out != embed) {
+      if (fabs(d - x) < fabs(d - x * BACKWARD_STEP(alpha)))
+        x *= FORWARD_STEP(alpha);
+      else
+        x *= BACKWARD_STEP(alpha);        
+    }
+
+    d =  (x + x * BACKWARD_STEP(alpha)) / 2.0;
+
+    if (verbose > 3)
+      fprintf(stderr, "%s: embedding bit #%d (= %d) at (%d/%d): %f -> %f\n", progname, n, get_signature_bit(n), col, row, dcts[row][col], d);
+
+    dcts[row][col] = d;
+
+    n++;
+  }  
+}        
+
+void embed_med_freq(double **dcts, int cols, int rows, double gamma, int seed, int verbose) {
+  // select mid-frequency (30%) coefficients
+  int start = (int) (0.35 * rows * cols + 0.5);
+  int end = (int) (0.65 * rows * cols + 0.5);
+
+  double *vector;
+  int x = 0, y = 0, dir = 1;
+  int i, j;    
+
+  vector = malloc((end - start) * sizeof(double));
+  for (i = 0; i < (end - start); i++)
+    vector[i] = 0.0;
+        
+  // create pseudo-random vector
+  srandom(seed);
+  for (i = 0; i < nbit_signature; i++) {
+    if (get_signature_bit(i))
+      random();
+    for (j = 0; j < (end - start); j++)
+      vector[j] += (double) (random() & RAND_MAX) / (double) RAND_MAX - 0.5;
+    if (!get_signature_bit(i))
+      random();
+  }
+
+  for (i = 0; i < (end - start); i++)
+    vector[i] /= sqrt(nbit_signature);
+
+  for (i = 0; i < end; i++) {
+    // zig-zag scan
+    x -= dir;
+    y += dir;
+    if (x < 0) { dir = -1; x = 0; }
+    if (x >= cols) { dir = 1; x = cols - 1; y += 2; }
+    if (y < 0) { dir = 1; y = 0; }
+    if (y >= rows) { dir = -1; y = rows - 1; x += 2; }
+
+    // embed vector
+    if ((i - start) >= 0) {
+//      fprintf(stderr, "%d/%d: %f -> %f\n", x, y, dcts[y][x], dcts[y][x] + gamma * vector[i - start]);
+      dcts[y][x] += gamma * vector[i - start];
+    }
+  }        
+
+  free(vector);
+}
+
+double detect_low_freq(double **dcts, int cols, int rows, double alpha, double beta, int verbose) {
+  int n;
+  int row, col, dir;
+  double sum1, sum2;
+
+  n = 0;
+  row = col = 0;
+  dir = 1;
+  sum1 = sum2 = 0.0;
+  while (n < nbit_signature1) {
+    double d, x;
+    int detect;
+    int out;
+
+    col -= dir;
+    row += dir;
+    if (col < 0) { dir = -1; col = 0; }
+    if (col >= cols) { dir = 1; col = cols - 1; row += 2; }
+    if (row < 0) { dir = 1; row = 0; }
+    if (row >= rows) { dir = -1; row = rows - 1; col += 2; }
+
+    d = dcts[row][col];
+    if (fabs(d) <= 1.0) {
+      if (verbose > 3)
+        fprintf(stderr, "%s: bit #%d - skipped (%d/%d)\n", progname, n, col, row);
+      continue;
+    }
+
+    detect = 2 * get_signature1_bit(n) - 1;
+
+    x = (d > 0.0) ? 1.0 : -1.0;
+    out = 1;
+    while (fabs(x) < fabs(d)) {
+      x *= FORWARD_STEP(alpha);
+      out =- out;
+    }
+
+    if (verbose > 3)
+      fprintf(stderr, "%s: detected bit #%d (= %d) at (%d/%d): %f\n", progname, n, out > 0 ? 1 : 0, col, row, d);
+
+    set_signature2_bit(n, out > 0 ? 1 : 0);
+    sum1 += pow(fabs(d), beta) * out * detect;
+    sum2 += pow(fabs(d), beta);
+
+    n++;
+  }  
+
+  return sum1 / sum2;
+}
+
+double detect_med_freq(double **dcts, int cols, int rows, int seed, int verbose) {
+  int i, j, k;
+  int start= (int) (0.35 * rows * cols + 0.5);
+  int end = (int) (.65 * rows * cols + 0.5);
+
+  int sum, sum1, sum2;
+  int x = 0, y = 0, dir = 1;
+  double *vector;
+  int startx, starty, startdir;
+  double corr[2];
+  double correlation;
+
+  // locate start positions 
+  for (i = 0; i < start; i++) {
+    x -= dir;
+    y += dir;
+    if (x < 0) { dir = -1; x = 0; }
+    if (x >= cols) { dir = 1; x = cols - 1; y += 2; }
+    if (y < 0) { dir = 1; y = 0; }
+    if (y >= rows) { dir = -1; y = rows - 1; x += 2; }
+  }		
+
+  // save start positions
+  startx = x;		
+  starty = y;
+  startdir = dir;
+  srandom(seed);
+
+  vector = malloc((end - start) * sizeof(double));
+
+  for (i = 0; i < nbit_signature1; i++) {
+
+    for (j = 0; j <= (end - start); j++)
+      vector[j] = (double) (random() & RAND_MAX) / (double) RAND_MAX - 0.5;
+				
+    for (j = 0; j <= 1; j++) {
+      x = startx;
+      y = starty;
+      dir = startdir;
+      corr[j] = 0;
+
+      for (k = 0; start + k < end; k++) {   
+        x -= dir;
+        y += dir;
+        if (x < 0) { dir = -1; x = 0; }
+        if (x >= cols) { dir = 1; x = cols - 1; y += 2; }
+        if (y < 0) { dir = 1; y = 0; }
+        if (y >= rows) { dir = -1; y = rows - 1; x += 2; }
+        corr[j] += dcts[y][x] * vector[k + j];
+      }
+    }	
+
+    set_signature2_bit(i,  (corr[0] >= corr[1]) ? 0 : 1);
+  }
+
+  sum = 0; sum1 = 0; sum2 = 0;
+  for (i = 0; i < nbit_signature1; i++) {
+    sum += get_signature1_bit(i) * get_signature2_bit(i);
+    sum1 += get_signature1_bit(i) *  get_signature1_bit(i);
+    sum2 += get_signature2_bit(i) * get_signature2_bit(i);
+  }
+  correlation = (double) sum / (sqrt(sum1) * sqrt(sum2));
+
+  return correlation;		
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Meerwald/frid2_common.h	Sun Aug 12 13:14:34 2007 +0200
@@ -0,0 +1,12 @@
+#ifndef FRID2_COMMON_H
+#define FRID2_COMMON_H
+
+#define FORWARD_STEP(A) ((1.0 + A) / (1.0 - A))
+#define BACKWARD_STEP(A) ((1.0 - A) / (1.0 + A))
+
+void embed_low_freq(double **dcts, int cols, int rows, double alpha, int verbose);
+void embed_med_freq(double **dcts, int cols, int rows, double gamma, int seed, int verbose);
+double detect_low_freq(double **dcts, int cols, int rows, double alpha, double beta, int verbose);
+double detect_med_freq(double **dcts, int cols, int rows, int seed, int verbose);
+
+#endif
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Meerwald/gen_bruyn_sig.1	Sun Aug 12 13:14:34 2007 +0200
@@ -0,0 +1,89 @@
+.\"
+.\" gen_bruyn_sig.1 - the *roff document processor man page source
+.\"
+.TH gen_bruyn_sig 1 "98/06/30" "Watermarking, Version 1.0"
+.SH NAME
+gen_bruyn_sig \- an man page source template
+.SH SYNOPSIS
+.B gen_bruyn_sig
+[
+.B \-abcdef
+]
+[
+.BI \-d opt
+]
+[
+.BI \-o file
+]
+[
+.IR files \|.\|.\|.\|
+]
+.SH DESCRIPTION
+.B gen_bruyn_sig
+is a program.
+.PP
+the
+.B \-d
+option is one of the following:
+.TP
+.B opt1 for option 1
+.TP
+.B opt2 for option 2
+.TP
+.B opt3 for option 3
+.LP
+I hope you can guess the purpose of the program.
+.LP
+Can you?
+.P
+.SH OPTIONS
+.TP
+.B \-a
+option a
+.TP
+.B \-b
+option b
+.TP
+.B \-c
+option c
+.TP
+.B \-d
+option d
+.TP
+.B \-e
+option e
+.TP
+.B \-f
+option f
+.PP
+These are all the options, now on with some environment variables:
+.TP
+.SM
+.B ENV_VAR1
+environment variable 1
+.TP
+.SM
+.B ENV_VAR2
+environment variable 2
+.TP
+.SM
+.B ENV_VAR3
+environment variable 2
+.SH FILES
+.SH AUTHOR
+Peter Meerwald <pmeerw@cosy.sbg.ac.at>
+.SH NOTES
+.SH BUGS
+Email bug reports to pmeerw@cosy.sbg.ac.at.
+.SH COPYRIGHT
+Copyright \(co 1998 Peter Meerwald
+.SH AVAILABILITY
+The most recent released version of
+.B gen_bruyn_sig
+is always available
+at http://www.cosy.sbg.ac.at/~pmeerw/Watermarking or via anonymous ftp from ftp.cosy.sbg.ac.at in the
+directory /pub/people/pmeerw/Watermarking.
+.SH "SEE ALSO"
+.BR program1,
+.BR program2,
+.BR program3
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Meerwald/gen_bruyn_sig.c	Sun Aug 12 13:14:34 2007 +0200
@@ -0,0 +1,231 @@
+#include "wm.h"
+#include "signature.h"
+#include "bruyn_common.h"
+
+char *progname;
+
+void usage(void) {
+  fprintf(stderr, "usage: %s [-b n] [-k] [-n n] [-o file] [-pP n] [-q n] [-s file] [-S n] [-tT n] file\n\n", progname);
+  fprintf(stderr, "\t-b n\t\tblock size (default 8)\n");
+  fprintf(stderr, "\t-h\t\tprint usage\n");
+  fprintf(stderr, "\t-k\t\tdisable block skipping\n");
+  fprintf(stderr, "\t-n n\t\twatermark bit length\n");
+  fprintf(stderr, "\t-o file\t\toutput file\n");
+  fprintf(stderr, "\t-p n\t\tpattern type for zone 1 (default 1, 1.." NPATTERN_USAGE ")\n");
+  fprintf(stderr, "\t-P n\t\tpattern type for zone 2 (default 2, 1.." NPATTERN_USAGE ")\n");
+  fprintf(stderr, "\t-q n\t\tsignature strength (default 7.0)\n");
+  fprintf(stderr, "\t-s file\t\tuse signature file's embedding information\n");
+  fprintf(stderr, "\t-S n\t\tseed\n");
+  fprintf(stderr, "\t-t n\t\tthreshold for noise (default " THRESHOLD_NOISE_USAGE ")\n");
+  fprintf(stderr, "\t-T n\t\tthreshold for slope (default " THRESHOLD_SLOPE_USAGE ")\n");
+  exit(0);
+}
+
+int main(int argc, char *argv[]) {
+  FILE *in = stdin;
+  FILE *out = stdout;
+  FILE *sig = NULL;
+
+  char output_name[MAXPATHLEN] = "(stdout)";
+  char input_name[MAXPATHLEN] = "(stdin)";
+  char signature_name[MAXPATHLEN];
+
+  int c;
+  int i;
+  int b = 8;
+  int n = 0;
+  int nb;
+  int s = 0;
+  int p1 = 1;
+  int p2 = 2;
+  double t1 = THRESHOLD_NOISE;
+  double t2 = THRESHOLD_SLOPE;
+  double q = 7.0;
+  int skipping = 0;
+
+  progname = argv[0];
+  wm_init();
+
+  while ((c = getopt(argc, argv, "b:h?n:o:p:P:q:s:S:t:T:k")) != EOF) {
+    switch (c) {
+      case 'b':
+        b = atoi(optarg);
+        if (b <= 0) {
+          fprintf(stderr, "%s: block size %d out of range\n", progname, b);
+          exit(1);
+        }
+        break;
+      case 'k':
+        skipping = 1;
+        break;
+      case 'h':
+      case '?':
+        usage();
+        break;
+      case 'n':
+        n = atoi(optarg);
+        if (n < 1 || n > 1000) {
+          fprintf(stderr, "%s: watermark length %d out of range\n", progname, n);
+          exit(1);
+        }
+        break;
+      case 'o':
+        if ((out = fopen(optarg, "wb")) == NULL) {
+          fprintf(stderr, "%s: unable to open output file %s\n", progname, optarg);
+          exit(1);
+        }
+        strcpy(output_name, optarg);
+        break;
+      case 'p':
+        p1 = atoi(optarg);
+        if (p1 <= 0 || p1 > NPATTERN) {
+          fprintf(stderr, "%s: pattern type out of range\n", progname);
+          exit(1);
+        }
+        break;
+      case 'P':
+        p2 = atoi(optarg);
+        if (p2 <= 0 || p2 > NPATTERN) {
+          fprintf(stderr, "%s: pattern type out of range\n", progname);
+          exit(1);
+        }
+        break;
+      case 'q':
+        q = atof(optarg);
+        if (q <= 0.0) {
+          fprintf(stderr, "%s: signature strength factor %f out of range\n", progname, q);
+          exit(1);
+        }
+        break;
+      case 't':
+        t1 = atof(optarg);
+        if (t1 <= 0) {
+          fprintf(stderr, "%s: noise threshold %f out of range\n", progname, t1);
+        }
+        break;
+      case 'T':
+        t2 = atof(optarg);
+        if (t2 <= 0) {
+          fprintf(stderr, "%s: slope threshold %f out of range\n", progname, t2);
+        }
+        break;
+      case 's':
+        if ((sig = fopen(optarg, "r")) == NULL) {
+          fprintf(stderr, "%s: unable to open signature file %s\n", progname, optarg);
+          exit(1);
+        }
+        strcpy(signature_name, optarg);
+        break;
+      case 'S':
+        s = atoi(optarg);
+        break;
+    }
+  }
+
+  argc -= optind;
+  argv += optind;
+
+  if (argc > 1) {
+    usage();
+    exit(1);
+  }
+
+  if (b % 2 > 0 || b <= 2) {
+    fprintf(stderr, "%s: block size has to be even and greater than 2\n");
+    exit(1);
+  }
+
+  if (argc == 1 && *argv[0] != '-')
+  if ((in = fopen(argv[0], "rb")) == NULL) {
+    fprintf(stderr, "%s: unable to open input file %s\n", progname, argv[0]);
+    exit(1);
+  }
+  else
+    strcpy(input_name, argv[0]);
+
+  // read signature file and set options
+  // command line options override signature file options
+  if (sig) {
+    char line[128];
+    fgets(line, sizeof(line), sig);
+    if (strspn(line, "BRSG") >= 4) {
+      if (n == 0)
+        fscanf(sig, "%d\n", &n);
+      else
+        fscanf(sig, "%*d\n");
+      if (skipping == 0)
+        fscanf(sig, "%d\n", &skipping);
+      else
+        fscanf(sig, "%*d\n");
+      if (p1 == 0)
+        fscanf(sig, "%d\n", &p1);
+      else
+        fscanf(sig, "%*d\n");
+      if (p2 == 0)
+        fscanf(sig, "%d\n", &p2);
+      else
+        fscanf(sig, "%*d\n");
+      if (q == 0.0)
+        fscanf(sig, "%lf\n", &q);
+      else
+        fscanf(sig, "%*lf\n");
+      if (t1 == 0.0)
+        fscanf(sig, "%lf\n", &t1);
+      else
+        fscanf(sig, "%*lf\n");
+      if (t2 == 0.0)
+        fscanf(sig, "%lf\n", &t2);
+      else
+        fscanf(sig, "%*lf\n");
+      if (b == 0)
+        fscanf(sig, "%d\n", &b);
+      else
+        fscanf(sig, "%*d\n");
+    }
+    else {
+      fprintf(stderr, "%s: invalid signature file %s\n", progname, signature_name);
+      exit(1);
+    }
+    fclose(sig);
+  }
+
+  if (s)
+    srandom(s);
+  else
+    srandom(time(NULL) * getpid());
+
+  if (n > 0) {
+    nb = fread(signature, sizeof(char), i = NBITSTOBYTES(n), in);
+    if (nb < i) {
+      fprintf(stderr, "%s: failed to read all %d signature bits from %s\n", progname, n, input_name);
+      exit(1);
+    }
+  }
+  else {
+    if (fscanf(in, "%128[^\n\r]", signature) == EOF) {
+      fprintf(stderr, "%s: failed to read signature bits from %s\n", progname, input_name);
+      exit(1);
+    }
+    nb = strlen(signature);
+    n = NBYTESTOBITS(nb);
+    fprintf(stderr, "%s: got %d signature bits\n", progname, n);
+  }
+
+
+  fprintf(out, "BRSG\n");
+  fprintf(out, "%d\n", n);
+  fprintf(out, "%d\n", skipping);
+  fprintf(out, "%d\n", p1);
+  fprintf(out, "%d\n", p2);
+  fprintf(out, "%f\n", q);
+  fprintf(out, "%f\n", t1);
+  fprintf(out, "%f\n", t2);
+  fprintf(out, "%d\n", b);
+  fprintf(out, "%d\n", random());
+  fwrite(signature, sizeof(char), nb, out);
+  fprintf(out, "\n");
+
+  fclose(out);
+
+  exit(0);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Meerwald/gen_corvi_sig.1	Sun Aug 12 13:14:34 2007 +0200
@@ -0,0 +1,161 @@
+.\"
+.\" gen_corvi_sig.1 - the *roff document processor man page source
+.\"
+.TH gen_corvi_sig 1 "98/07/17" "Watermarking, Version 1.0"
+.SH NAME
+.B gen_corvi_sig
+\- a program to generate a signature for
+the
+.B wm_corvi_e
+watermarking program
+.SH SYNOPSIS
+.B gen_corvi_sig
+[
+.BI \-a \ number
+]
+[
+.BI \-d \ number
+]
+[
+.BI \-e \ number
+]
+[
+.BI \-f \ number
+]
+[
+.BI \-F \ ffile
+]
+[
+.BI \-g \ number
+]
+.br
+[
+.B \-h
+]
+[
+.BI \-m \ number
+]
+[
+.BI \-n \ number
+]
+[
+.BI \-o \ file
+]
+[
+.BI \-q \ number
+]
+[
+.BI \-s \ number
+]
+.SH DESCRIPTION
+.B gen_corvi_sig
+is a program to generate a signature to be
+embedded with the
+.B wm_corvi_e
+watermarking program and extracted with the
+.B wm_corvi_d
+program. The
+.B cmp_corvi_sig
+program is used to compare and test an
+extracted signature with the original signature.
+.PP
+Please refer to Marco Corvi's paper "Wavlet-based image watermarking
+for copyright protection", to get an idea of the algorithm.
+.PP
+.SH OPTIONS
+.TP
+.BI \-a \ number
+Alpha factor that determines embedding strength of the signature. Default
+value 0.3.
+.TP
+.BI \-d \ number
+Deviation for the normal distributed signature values, default 1.0.
+.TP
+.BI \-e \ number
+The filtering method for the forward wavelet transform. Default value
+1.
+.TP
+.BI \-F \ ffile
+The filter definition file. Default
+.I filter.dat.
+.TP
+.BI \-f \ number
+Use the
+.I number
+filter from the filter definition file,
+.I ffile. Default: 1.
+.TP
+.BI \-g \ number
+The filtering method for the inverse wavelet transform. Default value
+2.
+.TP
+.B \-h
+Print a help message.
+.TP
+.BI \-m \ number
+Mean of the normal distributed signature values, default 0.0.
+.TP
+.BI \-n \ number
+Length of the watermark. Default value 100.
+.TP
+.BI \-o \ file
+Output signature to the specified
+.I file
+instead of standard output.
+.TP
+.BI \-q \ number
+Quantization/quality factor. Default value 3.
+.TP
+.BI \-s \ number
+Specify a seed value to initialize the pseudo-random number
+generator; if not specified, time and pid (process id) are used
+to initialize the pseudo-random number generator.
+.PP
+.SH OUTPUT
+The output file has the following format:
+.TP
+.B CVSG
+Magic to identify file type.
+.TP
+.I number
+The length of the signature in bits.
+.TP
+.I number
+The alpha factor (embedding strength).
+.TP
+.I number
+The quantization/quality factor.
+.TP
+.I number
+The wavelet forward transform filtering method.
+.TP
+.I number
+The wavelet filter number.
+.TP
+.I file
+The wavelet filter definition file name.
+.TP 
+.I number
+The wavelet inverse transform filtering method.
+.TP
+.I numbers
+The actual normal distributed signature values, one per line.
+.PP
+.SH AUTHOR
+Peter Meerwald.
+Email bug reports to pmeerw@cosy.sbg.ac.at.
+.SH AVAILABILITY
+The most recent released version of
+.B gen_corvi_sig
+is always available
+at http://www.cosy.sbg.ac.at/~pmeerw/Watermarking or via anonymous ftp from ftp.cosy.sbg.ac.at in the
+directory /pub/people/pmeerw/Watermarking.
+.SH "SEE ALSO"
+.BR wm_corvi_e
+(1),
+.BR wm_corvi_d
+(1),
+.BR wm_corvi_s
+(1),
+.BR cmp_corvi_sig
+(1)
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Meerwald/gen_corvi_sig.c	Sun Aug 12 13:14:34 2007 +0200
@@ -0,0 +1,143 @@
+#include "wm.h"
+
+char *progname;
+
+void usage(void) {
+  fprintf(stderr, "usage: %s [-a n] [-d n] [-e n] [-f n] [-F file] [-m n] [-n n] [-o file] [-s n]\n\n", progname);
+  fprintf(stderr, "\t-a n\t\talpha factor (default 0.1)\n");
+  fprintf(stderr, "\t-d n\t\tdeviation (default 1.0)\n");
+  fprintf(stderr, "\t-e n\t\twavelet filtering method (default 2)\n");
+  fprintf(stderr, "\t-f n\t\tfilter number (default 1)\n");
+  fprintf(stderr, "\t-F file\t\tfilter definition file (default 'filter.dat')\n");
+  fprintf(stderr, "\t-h\t\tprint usage\n");
+  fprintf(stderr, "\t-m n \t\tmean value (default 0.0)\n");
+  fprintf(stderr, "\t-n n\t\twatermark length (default 1000)\n");
+  fprintf(stderr, "\t-o file\t\toutput file\n");
+  fprintf(stderr, "\t-s n\t\tseed\n");
+  exit(0);
+}
+
+int main(int argc, char *argv[]) {
+  FILE *out = stdout;
+
+  char output_name[MAXPATHLEN] = "(stdout)";
+
+  int c;
+  int i;
+  int n = 1000;
+  int s = 0;
+  int e = 2;
+  int f = 1;
+  char F[MAXPATHLEN] = "filter.dat";
+  double a = 0.1;
+  double m = 0.0;
+  double d = 1.0;
+
+  progname = argv[0];
+
+  while ((c = getopt(argc, argv, "a:d:e:f:F:h?m:n:o:s:")) != EOF) {
+    switch (c) {
+      case 'a':
+        a = atof(optarg);
+        if (a <= 0.0) {
+          fprintf(stderr, "%s: alpha factor %f out of range\n", progname, a);
+          exit(1);
+        }
+        break;
+      case 'd':
+        d = atof(optarg);
+        if (d <= 0.0) {
+          fprintf(stderr, "%s: deviation %f out of range\n", progname, d);
+          exit(1);
+        }
+        break;
+      case 'e':
+        e = atoi(optarg);
+        if (e < 0) {
+          fprintf(stderr, "%s: wavelet filtering method %d out of range\n", progname, e);
+        }
+        break;
+      case 'f':
+        f = atoi(optarg);
+        if (f <= 0) {
+          fprintf(stderr, "%s: filter number %d out of range\n", progname, f);
+          exit(1);
+        }
+        break;
+      case 'F':
+        strcpy(F, optarg);
+        break;
+      case 'h':
+      case '?':
+        usage();
+        break;
+      case 'm':
+        m = atof(optarg);
+        break;
+      case 'n':
+        n = atoi(optarg);
+        if (n < 1 || n > 32000) {
+          fprintf(stderr, "%s: watermark length %d out of range\n", progname, n);
+          exit(1);
+        }
+        break;
+      case 'o':
+        if ((out = fopen(optarg, "w")) == NULL) {
+          fprintf(stderr, "%s: unable to open output file %s\n", progname, optarg);
+          exit(1);
+        }
+        strcpy(output_name, optarg);
+        break;
+      case 's':
+        s = atoi(optarg);
+        break;
+    }
+  }
+
+  argc -= optind;
+  argv += optind;
+
+  if (argc > 0) {
+    usage();
+    exit(1);
+  }
+
+  if (s)
+    srandom(s);
+  else
+    srandom(time(NULL) * getpid());
+
+  fprintf(out, "CVSG\n");
+  fprintf(out, "%d\n", n);
+  fprintf(out, "%f\n", a);
+  fprintf(out, "%d\n", e);
+  fprintf(out, "%d\n", f);
+  fprintf(out, "%s\n", F);
+
+  n >>= 1;
+  while (n > 0) {
+    double x;
+    double x1, x2;
+
+    /*
+     * Algorithm P (Polar method for normal deviates),
+     * Knuth, D., "The Art of Computer Programming", Vol. 2, 3rd Edition, p. 122
+     */
+    do {
+      x1 = 2.0 * ((random() & RAND_MAX) / ((double) RAND_MAX + 1.0)) - 1.0;
+      x2 = 2.0 * ((random() & RAND_MAX) / ((double) RAND_MAX + 1.0)) - 1.0;
+      x = x1 * x1 + x2 * x2;
+    } while (x >= 1.0);
+    x1 *= sqrt((-2.0) * log(x) / x);
+    x2 *= sqrt((-2.0) * log(x) / x);
+
+    fprintf(out, "%f\n", m + d * x1);
+    fprintf(out, "%f\n", m + d * x2);
+
+    n--;
+  }
+
+  fclose(out);
+
+  exit(0);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Meerwald/gen_cox_sig.1	Sun Aug 12 13:14:34 2007 +0200
@@ -0,0 +1,115 @@
+.\"
+.\" gen_cox_sig.1 - the *roff document processor man page source
+.\"
+.TH gen_cox_sig 1 "98/06/30" "Watermarking, Version 1.0"
+.SH NAME
+.B gen_cox_sig 
+\- a program to generate a signature for
+the 
+.B wm_cox_e 
+watermarking program
+.SH SYNOPSIS
+.B gen_cox_sig
+[
+.BI \-a \ number
+]
+[
+.BI \-d \ number
+]
+[
+.B \-h
+]
+[
+.BI \-m \ number
+]
+[
+.BI \-n \ number
+]
+[
+.BI \-o \ file
+]
+[
+.BI \-q \ number
+]
+[
+.BI \-s \ number
+]
+.SH DESCRIPTION
+.B gen_cox_sig
+is a program to generate a signature to be
+embedded with the 
+.B wm_cox_e 
+watermarking program and extracted with the 
+.B wm_cox_d 
+program. The
+.B cmp_cox_sig 
+program is used to compare and test an
+extracted signature with the original signature.
+.PP
+Please refer to Ingemar J. Cox's paper "Secure Spread Spectrum
+Watermarking for Multimedia", 1995, to get an idea about the algorithm.
+.PP
+.SH OPTIONS
+.TP
+.BI \-a \ number
+Alpha factor that determines embedding strength of the signature. Default
+value 0.3.
+.TP
+.BI \-d \ number
+Deviation for the normal distributed signature values, default 1.0.
+.TP
+.B \-h
+Print a help message.
+.TP
+.BI \-m \ number
+Mean of the normal distributed signature values, default 0.0.
+.TP
+.BI \-n \ number
+Length of the watermark. Default value 100.
+.TP
+.BI \-o \ file
+Output signature to the specified 
+.I file
+instead of standard output.
+.TP
+.BI \-q \ number
+Quantization/quality factor. Default value 3.
+.TP
+.BI \-s \ number
+Specify a seed value to initialize the pseudo-random number 
+generator; if not specified, time and pid (process id) are used
+to initialize the pseudo-random number generator.
+.PP
+.SH OUTPUT
+The output file has the following format:
+.TP
+.B CXSG
+Magic to identify file type.
+.TP
+.I number
+The length of the signature in bits. 
+.TP
+.I number
+The alpha factor (embedding strength).
+.TP
+.I number
+The quantization/quality factor.
+.TP
+.I numbers
+The actual normal distributed signature values, one per line.
+.PP
+.SH AUTHOR
+Peter Meerwald. Email bug reports to pmeerw@cosy.sbg.ac.at.
+.SH AVAILABILITY
+The most recent released version of
+.B gen_cox_sig
+is always available
+at http://www.cosy.sbg.ac.at/~pmeerw/Watermarking or via anonymous ftp from ftp.cosy.sbg.ac.at in the
+directory /pub/people/pmeerw/Watermarking.
+.SH "SEE ALSO"
+.BR wm_cox_e
+(1),
+.BR wm_cox_d
+(1),
+.BR cmp_cox_sig
+(1)
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Meerwald/gen_cox_sig.c	Sun Aug 12 13:14:34 2007 +0200
@@ -0,0 +1,158 @@
+#include "wm.h"
+
+char *progname;
+
+void usage(void) {
+  fprintf(stderr, "usage: %s [-a n] [-d n] [-m n] [-n n] [-o file] [-s file] [-S n]\n\n", progname);
+  fprintf(stderr, "\t-a n\t\talpha factor (default 0.3)\n");
+  fprintf(stderr, "\t-d n\t\tdeviation (default 1.0)\n");
+  fprintf(stderr, "\t-h\t\tprint usage\n");
+  fprintf(stderr, "\t-m n \t\tmean value (default 0.0)\n");
+  fprintf(stderr, "\t-n n\t\twatermark length (default 100)\n");
+  fprintf(stderr, "\t-o file\t\toutput file\n");
+  fprintf(stderr, "\t-s file\t\tuse signature file's embedding information\n");
+  fprintf(stderr, "\t-S n\t\tseed\n");
+  exit(0);
+}
+
+int main(int argc, char *argv[]) {
+  FILE *out = stdout;
+  FILE *sig = NULL;
+
+  char output_name[MAXPATHLEN] = "(stdout)";
+  char signature_name[MAXPATHLEN];
+
+  int c;
+  int i;
+  int n = 100;
+  int s = 0;
+  double a = 0.3;
+  double m = 0.0;
+  double d = 1.0;
+
+  progname = argv[0];
+
+  while ((c = getopt(argc, argv, "a:d:h?m:n:o:s:S:")) != EOF) {
+    switch (c) {
+      case 'a':
+        a = atof(optarg);
+        if (a <= 0.0) {
+          fprintf(stderr, "%s: alpha factor %f out of range\n", progname, a);
+          exit(1);
+        }
+        break;
+      case 'd':
+        d = atof(optarg);
+        if (d <= 0.0) {
+          fprintf(stderr, "%s: deviation %f out of range\n", progname, d);
+          exit(1);
+        }
+        break;
+      case 'h':
+      case '?':
+        usage();
+        break;
+      case 'm':
+        m = atof(optarg);
+        break;
+      case 'n':
+        n = atoi(optarg);
+        if (n < 1 || n > 32000) {
+          fprintf(stderr, "%s: watermark length %d out of range\n", progname, n);
+          exit(1);
+        }
+        break;
+      case 'o':
+        if ((out = fopen(optarg, "w")) == NULL) {
+          fprintf(stderr, "%s: unable to open output file %s\n", progname, optarg);
+          exit(1);
+        }
+        strcpy(output_name, optarg);
+        break;
+      case 's':
+        if ((sig = fopen(optarg, "r")) == NULL) {
+          fprintf(stderr, "%s: unable to open signature file %s\n", progname, optarg);
+          exit(1);
+        }
+        strcpy(signature_name, optarg);
+        break;      
+      case 'S':
+        s = atoi(optarg);
+        break;
+    }
+  }
+
+  argc -= optind;
+  argv += optind;
+
+  if (argc > 0) {
+    usage();
+    exit(1);
+  }
+
+    if (sig) {
+    char line[32];
+    fgets(line, sizeof(line), sig);
+    if (strspn(line, "CXSG") >= 4) {
+      if (n == 0)
+        fscanf(sig, "%d\n", &n);
+      else
+        fscanf(sig, "%*d\n");
+      if (a == 0.0)
+        fscanf(sig, "%lf\n", &a);
+      else
+        fscanf(sig, "%*lf\n");
+      if (m == 0.0)
+        fscanf(sig, "%lf\n", &m);
+      else
+        fscanf(sig, "%*lf\n");
+      if (d == 0.0)
+        fscanf(sig, "%lf\n", &d);
+      else
+        fscanf(sig, "%*lf\n");
+    }
+    else {
+      fprintf(stderr, "%s: invalid signature file %s\n", progname, signature_name);
+      exit(1);
+    }
+    close(sig);
+  }
+
+  if (s)
+    srandom(s);
+  else
+    srandom(time(NULL) * getpid());
+
+  fprintf(out, "CXSG\n");
+  fprintf(out, "%d\n", n);
+  fprintf(out, "%f\n", a);
+  fprintf(out, "%f\n", m);
+  fprintf(out, "%f\n", d);
+
+  n >>= 1;
+  while (n > 0) {
+    double x;
+    double x1, x2;
+
+    /*
+     * Algorithm P (Polar method for normal deviates),
+     * Knuth, D., "The Art of Computer Programming", Vol. 2, 3rd Edition, p. 122
+     */
+    do {
+      x1 = 2.0 * ((random() & RAND_MAX) / ((double) RAND_MAX + 1.0)) - 1.0;
+      x2 = 2.0 * ((random() & RAND_MAX) / ((double) RAND_MAX + 1.0)) - 1.0;
+      x = x1 * x1 + x2 * x2;
+    } while (x >= 1.0);
+    x1 *= sqrt((-2.0) * log(x) / x);
+    x2 *= sqrt((-2.0) * log(x) / x);
+
+    fprintf(out, "%f\n", m + d * x1);
+    fprintf(out, "%f\n", m + d * x2);
+
+    n--;
+  }
+
+  fclose(out);
+
+  exit(0);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Meerwald/gen_dugad_sig.c	Sun Aug 12 13:14:34 2007 +0200
@@ -0,0 +1,227 @@
+#include "wm.h"
+
+char *progname;
+
+void usage(void) {
+  fprintf(stderr, "usage: %s [-a n] [-e n] [-f n] [-F file] [-l n] [-n n] [-o file] [-s file] [-S n] [-t n] [-T n]\n\n", progname);
+  fprintf(stderr, "\t-a n\t\talpha factor (default 0.2)\n");
+  fprintf(stderr, "\t-d n\t\tdeviation (default 1.0)\n");
+  fprintf(stderr, "\t-e n\t\twavelet filtering method (default 2)\n");
+  fprintf(stderr, "\t-f n\t\tfilter number (default 1)\n");
+  fprintf(stderr, "\t-F file\t\tfilter definition file (default 'filter.dat')\n");
+  fprintf(stderr, "\t-h\t\tprint usage\n");
+  fprintf(stderr, "\t-l n\t\tdecomposition levels (default 3)\n");
+  fprintf(stderr, "\t-m n \t\tmean value (default 0.0)\n");
+  fprintf(stderr, "\t-n n\t\twatermark length (default 1000)\n");
+  fprintf(stderr, "\t-o file\t\toutput file\n");
+  fprintf(stderr, "\t-s file\t\tsignature to embed in input image\n");
+  fprintf(stderr, "\t-S n\t\tseed\n");
+  fprintf(stderr, "\t-t n\t\tcasting threshold (default 40.0)\n");
+  fprintf(stderr, "\t-T n\t\tdetection threshold (default 50.0)\n");
+  exit(0);
+}
+
+int main(int argc, char *argv[]) {
+  FILE *out = stdout;
+  FILE *sig = NULL;
+
+  char output_name[MAXPATHLEN] = "(stdout)";
+  char signature_name[MAXPATHLEN];
+
+  int c;
+  int i;
+  int n = 1000;
+  int s = 0;
+  int e = 2;
+  int f = 1;
+  int l = 3;
+  char F[MAXPATHLEN] = "filter.dat";
+  double a = 0.2;
+  double t1 = 40.0;
+  double t2 = 50.0;
+  double m = 0.0;
+  double d = 1.0;
+
+  progname = argv[0];
+
+  while ((c = getopt(argc, argv, "a:b:d:e:f:F:h?l:m:n:o:s:S:t:T:")) != EOF) {
+    switch (c) {
+      case 'a':
+        a = atof(optarg);
+        if (a <= 0.0) {
+          fprintf(stderr, "%s: alpha factor %f out of range\n", progname, a);
+          exit(1);
+        }
+        break;
+      case 'd':
+        d = atof(optarg);
+        if (d <= 0.0) {
+          fprintf(stderr, "%s: deviation %f out of range\n", progname, d);
+          exit(1);
+        }
+        break;
+
+      case 'e':
+        e = atoi(optarg);
+        if (e < 0) {
+          fprintf(stderr, "%s: wavelet filtering method %d out of range\n", progname, e);
+        }
+        break;
+      case 'f':
+        f = atoi(optarg);
+        if (f <= 0) {
+          fprintf(stderr, "%s: filter number %d out of range\n", progname, f);
+          exit(1);
+        }
+        break;
+      case 'F':
+        strcpy(F, optarg);
+        break;
+      case 'h':
+      case '?':
+        usage();
+        break;
+      case 'l':      
+        l = atoi(optarg);
+        if (l <= 0) {
+          fprintf(stderr, "%s: decomposition level %d out of range\n", l);
+          exit(1);
+        }
+        break;
+      case 'm':
+        m = atof(optarg);
+        break;
+      case 'n':
+        n = atoi(optarg);
+        if (n < 1 || n > 32000) {
+          fprintf(stderr, "%s: watermark length %d out of range\n", progname, n);
+          exit(1);
+        }
+        break;
+      case 'o':
+        if ((out = fopen(optarg, "w")) == NULL) {
+          fprintf(stderr, "%s: unable to open output file %s\n", progname, optarg);
+          exit(1);
+        }
+        strcpy(output_name, optarg);
+        break;
+      case 's':
+        if ((sig = fopen(optarg, "r")) == NULL) {
+          fprintf(stderr, "%s: unable to open signature file %s\n", progname, optarg);
+          exit(1);
+        }
+        strcpy(signature_name, optarg);
+        break;
+      case 'S':
+        s = atoi(optarg);
+        break;
+      case 't':
+        t1 = atof(optarg);
+        if (t1 <= 0.0) {
+          fprintf(stderr, "%s: casting threshold %f out of range\n", progname, t1);
+          exit(1);
+        }
+        break;
+      case 'T':
+        t2 = atof(optarg);
+        if (t2 <= 0.0) {
+          fprintf(stderr, "%s: detection threshold %f out of range\n", progname, t2);
+          exit(1);
+        }
+        break;
+    }
+  }
+
+  argc -= optind;
+  argv += optind;
+
+  if (argc > 0) {
+    usage();
+    exit(1);
+  }
+
+ if (sig) {
+    char line[32];
+    fgets(line, sizeof(line), sig);
+    if (strspn(line, "DGSG") >= 4) {
+      if (n == 0)
+        fscanf(sig, "%d\n", &n);
+      else
+        fscanf(sig, "%*d\n");
+      if (l == 0)
+        fscanf(sig, "%d\n", &l);
+      else
+        fscanf(sig, "%*d\n");
+      if (a == 0.0)
+        fscanf(sig, "%lf\n", &a);
+      else
+        fscanf(sig, "%*lf\n");
+      if (t1 == 0.0)
+        fscanf(sig, "%lf\n", &t1);
+      else
+        fscanf(sig, "%*lf\n");
+      if (t2 == 0.0)
+        fscanf(sig, "%lf\n", &t2);
+      else
+        fscanf(sig, "%*lf\n");
+      if (e < 0)
+        fscanf(sig, "%d\n", &e);
+      else
+        fscanf(sig, "%*d\n");
+      if (f == 0)
+        fscanf(sig, "%d\n", &f);
+      else
+        fscanf(sig, "%*d\n");
+      if (!strcmp(F, ""))
+        fscanf(sig, "%[^\n\r]\n", &F);
+      else
+        fscanf(sig, "%*[^\n\r]\n");
+    }
+    else {
+      fprintf(stderr, "%s: invalid signature file %s\n", progname, signature_name);
+      exit(1);
+    }
+  }
+
+  if (s)
+    srandom(s);
+  else
+    srandom(time(NULL) * getpid());
+
+  fprintf(out, "DGSG\n");
+  fprintf(out, "%d\n", n);
+  fprintf(out, "%d\n", l);
+  fprintf(out, "%f\n", a);
+  fprintf(out, "%f\n", t1);
+  fprintf(out, "%f\n", t2);
+  fprintf(out, "%d\n", e);
+  fprintf(out, "%d\n", f);
+  fprintf(out, "%s\n", F);
+
+  n >>= 1;
+  while (n > 0) {
+    double x;
+    double x1, x2;
+         
+    /*
+     * Algorithm P (Polar method for normal deviates),
+     * Knuth, D., "The Art of Computer Programming", Vol. 2, 3rd Edition, p. 122
+     */
+    do {
+      x1 = 2.0 * ((random() & RAND_MAX) / ((double) RAND_MAX + 1.0)) - 1.0;
+      x2 = 2.0 * ((random() & RAND_MAX) / ((double) RAND_MAX + 1.0)) - 1.0;
+      x = x1 * x1 + x2 * x2; 
+    } while (x >= 1.0);
+    x1 *= sqrt((-2.0) * log(x) / x);
+    x2 *= sqrt((-2.0) * log(x) / x);
+        
+    fprintf(out, "%f\n", m + d * x1);
+    fprintf(out, "%f\n", m + d * x2);
+      
+    n--;
+  }
+
+  fclose(out);
+
+  exit(0);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Meerwald/gen_frid2_sig.c	Sun Aug 12 13:14:34 2007 +0200
@@ -0,0 +1,149 @@
+#include "wm.h"
+#include "signature.h"
+
+char *progname;
+
+void usage(void) {
+  fprintf(stderr, "usage: %s [-a n] [-g n] [-o file] [-s n] file\n\n", progname);
+  fprintf(stderr, "\t-a n\t\talpha factor (default 0.25)\n");
+  fprintf(stderr, "\t-g n\t\tgamma factor (default 1.0)\n");
+  fprintf(stderr, "\t-s n\t\tseed (default 0)\n");
+  fprintf(stderr, "\t-h\t\tprint usage\n");
+  fprintf(stderr, "\t-n n\t\twatermark length (default 100)\n");
+  fprintf(stderr, "\t-o file\t\toutput file\n");
+  fprintf(stderr, "\t-s file\t\tuse signature file's embedding information\n");
+  fprintf(stderr, "\t-S n\t\tseed\n");
+  exit(0);
+}
+
+int main(int argc, char *argv[]) {
+  FILE *in = stdin;
+  FILE *out = stdout;
+  FILE *sig = NULL;
+
+  char output_name[MAXPATHLEN] = "(stdout)";
+  char input_name[MAXPATHLEN] = "(stdin)";
+  char signature_name[MAXPATHLEN];
+
+  int c;
+  int i;
+  int n = 100, nb;
+  double a = 0.25;
+  double g = 1.0;
+  int s = 0;
+
+  progname = argv[0];
+
+#ifdef __EMX__
+  _fsetmode(in, "b");
+  _fsetmode(out, "b");
+#endif
+
+  while ((c = getopt(argc, argv, "a:g:h?n:o:s:S:")) != EOF) {
+    switch (c) {
+      case 'a':
+        a = atof(optarg);
+        if (a <= 0.0) {
+          fprintf(stderr, "%s: alpha factor %f out of range\n", progname, a);
+          exit(1);
+        }
+        break;
+      case 'g':
+        g = atof(optarg);
+        if (g <= 0.0) {
+          fprintf(stderr, "%s: gamma factor %f out of range\n", progname, a);
+          exit(1);
+        }
+        break;
+      case 'h':
+      case '?':
+        usage();
+        break;
+      case 'n':
+        n = atoi(optarg);
+        if (n < 1 || n > 1000) {
+          fprintf(stderr, "%s: watermark length %d out of range\n", progname, n);
+          exit(1);
+        }
+        break;
+      case 'o':
+        if ((out = fopen(optarg, "w")) == NULL) {
+          fprintf(stderr, "%s: unable to open output file %s\n", progname, optarg);
+          exit(1);
+        }
+        strcpy(output_name, optarg);
+        break;
+      case 's':   
+        if ((sig = fopen(optarg, "r")) == NULL) {
+          fprintf(stderr, "%s: unable to open signature file %s\n", progname, optarg);
+          exit(1);
+        }
+        strcpy(signature_name, optarg);
+        break;
+      case 'S':
+        s = atoi(optarg);
+        break;
+    }
+  }
+
+  argc -= optind;
+  argv += optind;
+
+  if (argc > 1) {
+    usage();
+    exit(1);
+  }
+
+  if (argc == 1 && *argv[0] != '-')
+  if ((in = fopen(argv[0], "rb")) == NULL) {
+    fprintf(stderr, "%s: unable to open input file %s\n", progname, argv[0]);
+    exit(1);   
+  }
+  else
+    strcpy(input_name, argv[0]);
+
+  if (!s)
+    s = time(NULL) * getpid();
+  srandom(s);
+
+  if (sig) {
+    char line[128];
+    fgets(line, sizeof(line), sig);
+    if (strspn(line, "FR2SG") >= 5) {
+    }
+    else {
+      fprintf(stderr, "%s: invalid signature file %s\n", progname, signature_name);
+      exit(1);
+    }
+    fclose(sig);
+  }
+
+  if (n > 0) {   
+    nb = fread(signature, sizeof(char), i = NBITSTOBYTES(n), in);
+    if (nb < i) {
+      fprintf(stderr, "%s: failed to read all %d signature bits from %s\n", progname, n, input_name);
+      exit(1);
+    }
+  }
+  else {
+    if (fscanf(in, "%128[^\n\r]", signature) == EOF) {
+      fprintf(stderr, "%s: failed to read signature bits from %s\n", progname, input_name);
+      exit(1);
+    }
+    nb = strlen(signature);
+    n = NBYTESTOBITS(nb);
+    fprintf(stderr, "%s: got %d signature bits\n", progname, n);
+  }
+
+  fprintf(out, "FR2SG\n");
+  fprintf(out, "%d\n", n);
+  fprintf(out, "%f\n", a);
+  fprintf(out, "%f\n", g);
+  fprintf(out, "%d\n", s);
+  fwrite(signature, sizeof(char), nb, out);
+  fprintf(out, "\n");
+
+  fclose(out);
+
+  exit(0);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Meerwald/gen_kim_sig.c	Sun Aug 12 13:14:34 2007 +0200
@@ -0,0 +1,212 @@
+#include "wm.h"
+
+char *progname;
+
+void usage(void) {
+  fprintf(stderr, "usage: %s [-a n] [-A n] [-d n] [-e n] [-f n] [-F file] [-l n] [-m n] [-n n] [-o file] [-s file] [-S n]\n\n", progname);
+  fprintf(stderr, "\t-a n\t\talpha factor for detail subbands (default 0.1)\n");
+  fprintf(stderr, "\t-A n\t\talpha factor for approximation subband (default 0.02)\n");
+  fprintf(stderr, "\t-d n\t\tdeviation (default 1.0)\n");
+  fprintf(stderr, "\t-e n\t\twavelet filtering method (default 2)\n");
+  fprintf(stderr, "\t-f n\t\tfilter number (default 1)\n");
+  fprintf(stderr, "\t-F file\t\tfilter definition file (default 'filter.dat')\n");
+  fprintf(stderr, "\t-h\t\tprint usage\n");
+  fprintf(stderr, "\t-l n\t\tdecomposition level (default 4)\n");
+  fprintf(stderr, "\t-m n \t\tmean value (default 0.0)\n");
+  fprintf(stderr, "\t-n n\t\twatermark length (default 1000)\n");
+  fprintf(stderr, "\t-o file\t\toutput file\n");
+  fprintf(stderr, "\t-s file\t\tuse signature file's embedding information\n");
+  fprintf(stderr, "\t-S n\t\tseed\n");
+  exit(0);
+}
+
+int main(int argc, char *argv[]) {
+  FILE *out = stdout;
+  FILE *sig = NULL;
+
+  char output_name[MAXPATHLEN] = "(stdout)";
+  char signature_name[MAXPATHLEN];
+
+  int c;
+  int i;
+  int n = 1000;
+  int s = 0;
+  int e = 2;
+  int f = 1;
+  char F[MAXPATHLEN] = "filter.dat";
+  double a = 0.1;
+  double A = 0.02;
+  int l = 4;
+  double m = 0.0;
+  double d = 1.0;
+
+  progname = argv[0];
+
+  while ((c = getopt(argc, argv, "a:A:l:d:e:f:F:h?m:n:o:s:S:")) != EOF) {
+    switch (c) {
+      case 'a':
+        a = atof(optarg);
+        if (a <= 0.0) {
+          fprintf(stderr, "%s: alpha factor %f out of range\n", progname, a);
+          exit(1);
+        }
+        break;
+      case 'A':
+        A = atof(optarg);
+        if (A <= 0.0) {
+          fprintf(stderr, "%s: alpha factor %f out of range\n", progname, a);
+          exit(1);
+        }
+        break;
+      case 'l':
+        l = atoi(optarg);
+        if (l <= 0) {
+          fprintf(stderr, "%s: decomposition level %d out of range\n", progname, l);
+          exit(1);
+        }
+        break;
+      case 'd':
+        d = atof(optarg);
+        if (d <= 0.0) {
+          fprintf(stderr, "%s: deviation %f out of range\n", progname, d);
+          exit(1);
+        }
+        break;
+      case 'e':
+        e = atoi(optarg);
+        if (e < 0) {
+          fprintf(stderr, "%s: wavelet filtering method %d out of range\n", progname, e);
+        }
+        break;
+      case 'f':
+        f = atoi(optarg);
+        if (f <= 0) {
+          fprintf(stderr, "%s: filter number %d out of range\n", progname, f);
+          exit(1);
+        }
+        break;
+      case 'F':
+        strcpy(F, optarg);
+        break;
+      case 'h':
+      case '?':
+        usage();
+        break;
+      case 'm':
+        m = atof(optarg);
+        break;
+      case 'n':
+        n = atoi(optarg);
+        if (n < 1 || n > 32000) {
+          fprintf(stderr, "%s: watermark length %d out of range\n", progname, n);
+          exit(1);
+        }
+        break;
+      case 'o':
+        if ((out = fopen(optarg, "w")) == NULL) {
+          fprintf(stderr, "%s: unable to open output file %s\n", progname, optarg);
+          exit(1);
+        }
+        strcpy(output_name, optarg);
+        break;
+      case 's':
+        if ((sig = fopen(optarg, "r")) == NULL) {
+          fprintf(stderr, "%s: unable to open signature file %s\n", progname, optarg);
+          exit(1);
+        }
+        strcpy(signature_name, optarg);
+        break;
+      case 'S':
+        s = atoi(optarg);
+        break;
+    }
+  }
+
+  argc -= optind;
+  argv += optind;
+
+  if (argc > 0) {
+    usage();
+    exit(1);
+  }
+
+  if (sig) {
+    char line[32];
+    fgets(line, sizeof(line), sig);
+    if (strspn(line, "KISG") >= 4) {
+      if (n == 0)
+        fscanf(sig, "%d\n", &n);
+      else
+        fscanf(sig, "%*d\n");
+      if (a == 0.0)
+        fscanf(sig, "%lf\n", &a);
+      else
+        fscanf(sig, "%*lf\n");
+      if (A == 0.0)
+        fscanf(sig, "%lf\n", &A);
+      else
+        fscanf(sig, "%*lf\n");
+      if (l == 0)
+        fscanf(sig, "%d\n", &l);
+      else
+        fscanf(sig, "%*d\n");
+      if (e < 0)
+        fscanf(sig, "%d\n", &e);
+      else
+        fscanf(sig, "%*d\n");
+      if (f == 0)
+        fscanf(sig, "%d\n", &f);
+      else
+        fscanf(sig, "%*d\n");
+      if (!strcmp(F, ""))
+        fscanf(sig, "%[^\n\r]\n", &F);
+      else
+        fscanf(sig, "%*[^\n\r]\n");
+    }
+    else {
+      fprintf(stderr, "%s: invalid signature file %s\n", progname, signature_name);
+      exit(1);
+    }
+  }
+
+  if (s)
+    srandom(s);
+  else
+    srandom(time(NULL) * getpid());
+
+  fprintf(out, "KISG\n");
+  fprintf(out, "%d\n", n);
+  fprintf(out, "%f\n", a);
+  fprintf(out, "%f\n", A);
+  fprintf(out, "%d\n", l);
+  fprintf(out, "%d\n", e);
+  fprintf(out, "%d\n", f);
+  fprintf(out, "%s\n", F);
+
+  n >>= 1;
+  while (n > 0) {
+    double x;
+    double x1, x2;
+
+    /*
+     * Algorithm P (Polar method for normal deviates),
+     * Knuth, D., "The Art of Computer Programming", Vol. 2, 3rd Edition, p. 122
+     */
+    do {
+      x1 = 2.0 * ((random() & RAND_MAX) / ((double) RAND_MAX + 1.0)) - 1.0;
+      x2 = 2.0 * ((random() & RAND_MAX) / ((double) RAND_MAX + 1.0)) - 1.0;
+      x = x1 * x1 + x2 * x2;
+    } while (x >= 1.0);
+    x1 *= sqrt((-2.0) * log(x) / x);
+    x2 *= sqrt((-2.0) * log(x) / x);
+
+    fprintf(out, "%f\n", m + d * x1);
+    fprintf(out, "%f\n", m + d * x2);
+
+    n--;
+  }
+
+  fclose(out);
+
+  exit(0);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Meerwald/gen_koch_sig.1	Sun Aug 12 13:14:34 2007 +0200
@@ -0,0 +1,110 @@
+.\"
+.\" gen_koch_sig.1 - the *roff document processor man page source
+.\"
+.TH gen_koch_sig 1 "98/06/30" "Watermarking, Version 1.0"
+.SH NAME
+.B gen_koch_sig
+\- a program to generate a signature for
+the
+.B wm_koch_e
+watermarking program
+.SH SYNOPSIS
+.B gen_koch_sig
+[
+.B \-h
+]
+[
+.BI \-n \ number
+]
+[
+.BI \-o \ file
+]
+[
+.BI \-q \ number
+]
+[
+.BI \-s \ number
+]
+[
+.IR file
+]
+.SH DESCRIPTION
+.B gen_koch_sig
+is a program to generate a signature to be
+embedded with the
+.B wm_koch_e
+watermarking program and extracted with the
+.B wm_koch_d
+program. The
+.B cmp_koch_sig
+program is used to compare and test an
+extracted signature with the original signature.
+.PP
+Please refer to E. Koch's paper "Towards Robust and Hidden
+Image Copyright", 1995, to get an idea about the algorithm.
+.PP
+.SH OPTIONS
+.TP
+.B \-h
+Print a help message.
+.TP
+.BI \-n \ number
+Limit the signature length to
+.I number
+bits (0 <
+.I number
+<= 1024) unless reading from standard input. When reading from
+standard input, the signature is terminated by the first
+carriage return character.
+.TP
+.BI \-o \ file
+Output signature to the specified
+.I file
+instead of standard output.
+.TP
+.BI \-q \ number
+Quality/robustness factor used to embed signature into image.
+Default value: 3.0.
+.TP
+.BI \-s \ number
+Specify a seed value to initialize the pseudo-random number
+generator; if not specified, time and pid (process id) are used
+to initialize the pseudo-random number generator.
+.TP
+.IR file
+Input file to read raw signature data from. Default: standard
+input.
+.PP
+.SH OUTPUT
+The output file has the following format:
+.TP
+.B KCSG
+Magic to identify file type.
+.TP
+.I number
+The length of the signature in bits.
+.TP
+.I number
+The quality/robustness factor.
+.TP
+.I number
+The seed value for the pseudo-random number generator.
+.TP
+.I string
+The actual signature bytes.
+.PP
+.SH AUTHOR
+Peter Meerwald. Email bug reports to pmeerw@cosy.sbg.ac.at.
+.SH AVAILABILITY
+The most recent released version of
+.B gen_koch_sig
+is always available
+at http://www.cosy.sbg.ac.at/~pmeerw/Watermarking or via anonymous ftp from ftp.cosy.sbg.ac.at in the
+directory /pub/people/pmeerw/Watermarking.
+.SH "SEE ALSO"
+.BR wm_koch_e
+(1),
+.BR wm_koch_d
+(1),
+.BR cmp_koch_sig
+(1)
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Meerwald/gen_koch_sig.c	Sun Aug 12 13:14:34 2007 +0200
@@ -0,0 +1,157 @@
+#include "wm.h"
+#include "signature.h"
+
+char *progname;
+
+void usage(void) {
+  fprintf(stderr, "usage: %s [-l n] [-n n] [-o file] [-q n] [-s file] [-S n] file\n\n", progname);
+  fprintf(stderr, "\t-h\t\tprint usage\n");
+  fprintf(stderr, "\t-l n\t\tsignature strength factor (default 5.0)\n");
+  fprintf(stderr, "\t-n n\t\twatermark bit length\n");
+  fprintf(stderr, "\t-o file\t\toutput file\n");
+  fprintf(stderr, "\t-q n\t\tquantization (JPEG quality) factor (default 90)\n");
+  fprintf(stderr, "\t-s file\t\tuse signature file's embedding information\n");
+  fprintf(stderr, "\t-S n\t\tseed\n");
+  exit(0);
+}
+
+int main(int argc, char *argv[]) {
+  FILE *in = stdin;
+  FILE *out = stdout;
+  FILE *sig = NULL;
+
+  char output_name[MAXPATHLEN] = "(stdout)";
+  char input_name[MAXPATHLEN] = "(stdin)";
+  char signature_name[MAXPATHLEN];
+
+  int c;
+  int i;
+  int n = 0;
+  int nb;
+  int s = 0;
+  int q = 90;
+  double l = 5.0;
+
+  progname = argv[0]; wm_init();
+
+  while ((c = getopt(argc, argv, "h?l:n:o:q:s:S:")) != EOF) {
+    switch (c) {
+      case 'h':
+      case '?':
+        usage();
+        break;
+      case 'l':
+        l = atof(optarg);
+        if (l <= 0.0) {
+          fprintf(stderr, "%s: signature strength factor %f out of range\n", progname, l);
+          exit(1);
+        }
+        break;
+      case 'n':
+        n = atoi(optarg);
+        if (n < 1 || n > 1000) {
+          fprintf(stderr, "%s: watermark length %d out of range\n", progname, n);
+          exit(1);
+        }
+        break;
+      case 'o':
+        if ((out = fopen(optarg, "wb")) == NULL) {
+          fprintf(stderr, "%s: unable to open output file %s\n", progname, optarg);
+          exit(1);
+        }
+        strcpy(output_name, optarg);
+        break;
+      case 'q':
+        q = atoi(optarg);
+        if (q <= 0 || q > 100) {
+          fprintf(stderr, "%s: quantization factor %f out of range\n", progname, q);
+          exit(1);
+        }
+        break;
+      case 's':
+        if ((sig = fopen(optarg, "r")) == NULL) {
+          fprintf(stderr, "%s: unable to open signature file %s\n", progname, optarg);
+          exit(1);
+        }
+        strcpy(signature_name, optarg);
+        break;
+      case 'S':
+        s = atoi(optarg);
+        break;
+    }
+  }
+
+  argc -= optind;
+  argv += optind;
+
+  if (argc > 1) {
+    usage();
+    exit(1);
+  }
+
+  if (argc == 1 && *argv[0] != '-')
+  if ((in = fopen(argv[0], "rb")) == NULL) {
+    fprintf(stderr, "%s: unable to open input file %s\n", progname, argv[0]);
+    exit(1);
+  }
+  else
+    strcpy(input_name, argv[0]);
+
+  if (s)
+    srandom(s);
+  else
+    srandom(time(NULL) * getpid());
+
+  if (sig) {
+    char line[128];
+    fgets(line, sizeof(line), sig);
+    if (strspn(line, "KCSG") >= 4) {
+      if (n == 0)
+        fscanf(sig, "%d\n", &n);
+      else
+        fscanf(sig, "%*d\n");
+      if (l == 0.0)
+        fscanf(sig, "%lf\n", &l);
+      else
+        fscanf(sig, "%*lf\n");
+      if (q == 0)
+        fscanf(sig, "%d\n", &q);
+      else
+        fscanf(sig, "%*d\n");
+    }
+    else {
+      fprintf(stderr, "%s: invalid signature file %s\n", progname, signature_name);
+      exit(1);
+    }
+    fclose(sig);
+  }
+
+  if (n > 0) {
+    nb = fread(signature, sizeof(char), i = NBITSTOBYTES(n), in);
+    if (nb < i) {
+      fprintf(stderr, "%s: failed to read all %d signature bits from %s\n", progname, n, input_name);
+      exit(1);
+    }
+  }
+  else {
+    if (fscanf(in, "%128[^\n\r]", signature) == EOF) {
+      fprintf(stderr, "%s: failed to read signature bits from %s\n", progname, input_name);
+      exit(1);
+    }
+    nb = strlen(signature);
+    n = NBYTESTOBITS(nb);
+    fprintf(stderr, "%s: got %d signature bits\n", progname, n);
+  }
+
+  fprintf(out, "KCSG\n");
+  fprintf(out, "%d\n", n);
+  fprintf(out, "%f\n", l);
+  fprintf(out, "%d\n", q);
+  fprintf(out, "%d\n", random());
+  fwrite(signature, sizeof(char), nb, out);
+  fprintf(out, "\n");
+
+  fclose(out);
+
+  exit(0);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Meerwald/gen_kutter_sig.1	Sun Aug 12 13:14:34 2007 +0200
@@ -0,0 +1,131 @@
+.\"
+.\" gen_kutter_sig.1 - the *roff document processor man page source
+.\"
+.TH gen_kutter_sig 1 "98/06/30" "Watermarking, Version 1.0"
+.SH NAME
+.B gen_kutter_sig 
+\- a program to generate a signature for
+the 
+.B wm_kutter_e 
+watermarking program
+.SH SYNOPSIS
+.B gen_kutter_sig
+[
+.B \-h
+]
+[
+.BI \-n \ number
+]
+[
+.BI \-o \ file
+]
+[
+.BI \-p \ number
+]
+[
+.BI \-q \ number
+]
+[
+.BI \-r \ number
+]
+.br
+[
+.BI \-s \ number
+]
+[
+.I file
+]
+.SH DESCRIPTION
+.B gen_kutter_sig
+is a program to generate a signature to be
+embedded with the 
+.B wm_kutter_e 
+watermarking program and extracted with the 
+.B wm_kutter_d 
+program. The
+.B cmp_kutter_sig 
+program is used to compare and test an
+extracted signature with the original signature.
+.PP
+Please refer to M. Kutter's paper "Digital Signature of Color Images
+using Amplitude Modulation", 1997, to get an idea about the algorithm.
+.PP
+.SH OPTIONS
+.TP
+.B \-h
+Print a help message.
+.TP
+.BI \-n \ number
+Limit the signature length to
+.I number
+bits (0 <
+.I number
+<= 1024) unless reading from standard input. When reading from
+standard input, the signature is terminated by the first
+carriage return character.
+.TP
+.BI \-o \ file
+Output signature to the specified 
+.TP
+.BI \-p \ number
+Density parameter in the range 0.0 <
+.I number
+<= 1.0. Default value 0.01.
+.TP
+.BI \-q \ number
+Signature strength. Default value 0.1.
+.TP
+.BI \-r \ number
+Signature bit repetition factor. Specifies how often a single
+signature bit is embedded. Default value 8.
+.I file
+instead of standard output.
+.TP
+.BI \-s \ number
+Specify a seed value to initialize the pseudo-random number 
+generator; if not specified, time and pid (process id) are used
+to initialize the pseudo-random number generator.
+.TP
+.I file
+Input file to read raw signature data from. Default: standard
+input.
+.PP
+.SH OUTPUT
+The output file has the following format:
+.TP
+.B KTSG
+Magic to identify file type.
+.TP
+.I number
+The length of the signature in bits. 
+.TP
+.I number
+The density parameter.
+.TP 
+.I number
+The signature strength.
+.TP
+.I number
+The bit repetition parameter.
+.TP
+.I number
+The seed value for the pseudo-random number generator.
+.TP
+.I string
+The actual signature bytes.
+.PP
+.SH AUTHOR
+Peter Meerwald. Email bug reports to pmeerw@cosy.sbg.ac.at.
+.SH AVAILABILITY
+The most recent released version of
+.B gen_kutter_sig
+is always available
+at http://www.cosy.sbg.ac.at/~pmeerw/Watermarking or via anonymous ftp from ftp.cosy.sbg.ac.at in the
+directory /pub/people/pmeerw/Watermarking.
+.SH "SEE ALSO"
+.BR wm_kutter_e
+(1),
+.BR wm_kutter_d
+(1),
+.BR cmp_kutter_sig
+(1)
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Meerwald/gen_wang_sig.c	Sun Aug 12 13:14:34 2007 +0200
@@ -0,0 +1,198 @@
+#include "wm.h"
+
+char *progname;
+
+void usage(void) {
+  fprintf(stderr, "usage: %s [-a n] [-b n] [-d n] [-e n] [-f n] [-F file] [-m n] [-n n] [-o file] [-s file] [-S n]\n\n", progname);
+  fprintf(stderr, "\t-a n\t\talpha factor (default 0.3)\n");
+  fprintf(stderr, "\t-b n\t\tbeta factor (default 1.0)\n");
+  fprintf(stderr, "\t-d n\t\tdeviation (default 1.0)\n");
+  fprintf(stderr, "\t-e n\t\twavelet filtering method (default 2)\n");
+  fprintf(stderr, "\t-f n\t\tfilter number (default 1)\n");
+  fprintf(stderr, "\t-F file\t\tfilter definition file (default 'filter.dat')\n");
+  fprintf(stderr, "\t-h\t\tprint usage\n");
+  fprintf(stderr, "\t-m n \t\tmean value (default 0.0)\n");
+  fprintf(stderr, "\t-n n\t\twatermark length (default 1000)\n");
+  fprintf(stderr, "\t-o file\t\toutput file\n");
+  fprintf(stderr, "\t-s file\t\tuse signature file's embedding information\n");
+  fprintf(stderr, "\t-S n\t\tseed\n");
+  exit(0);
+}
+
+int main(int argc, char *argv[]) {
+  FILE *out = stdout;
+  FILE *sig = NULL;
+
+  char output_name[MAXPATHLEN] = "(stdout)";
+  char signature_name[MAXPATHLEN];
+
+  int c;
+  int i;
+  int n = 1000;
+  int s = 0;
+  int e = 2;
+  int f = 1;
+  char F[MAXPATHLEN] = "filter.dat";
+  double a = 0.3;
+  double b = 1.0;
+  double m = 0.0;
+  double d = 1.0;
+
+  progname = argv[0];
+
+  while ((c = getopt(argc, argv, "a:b:d:e:f:F:h?m:n:o:s:S:")) != EOF) {
+    switch (c) {
+      case 'a':
+        a = atof(optarg);
+        if (a <= 0.0) {
+          fprintf(stderr, "%s: alpha factor %f out of range\n", progname, a);
+          exit(1);
+        }
+        break;
+      case 'b':
+        b = atof(optarg);
+        if (b <= 0.0) {
+          fprintf(stderr, "%s: beta factor %f out of range\n", progname, b);
+          exit(1);
+        }
+        break;
+      case 'd':
+        d = atof(optarg);
+        if (d <= 0.0) {
+          fprintf(stderr, "%s: deviation %f out of range\n", progname, d);
+          exit(1);
+        }
+        break;
+      case 'e':
+        e = atoi(optarg);
+        if (e < 0) {
+          fprintf(stderr, "%s: wavelet filtering method %d out of range\n", progname, e);
+        }
+        break;
+      case 'f':
+        f = atoi(optarg);
+        if (f <= 0) {
+          fprintf(stderr, "%s: filter number %d out of range\n", progname, f);
+          exit(1);
+        }
+        break;
+      case 'F':
+        strcpy(F, optarg);
+        break;
+      case 'h':
+      case '?':
+        usage();
+        break;
+      case 'm':
+        m = atof(optarg);
+        break;
+      case 'n':
+        n = atoi(optarg);
+        if (n < 1 || n > 32000) {
+          fprintf(stderr, "%s: watermark length %d out of range\n", progname, n);
+          exit(1);
+        }
+        break;
+      case 'o':
+        if ((out = fopen(optarg, "w")) == NULL) {
+          fprintf(stderr, "%s: unable to open output file %s\n", progname, optarg);
+          exit(1);
+        }
+        strcpy(output_name, optarg);
+        break;
+      case 's':
+        if ((sig = fopen(optarg, "r")) == NULL) {
+          fprintf(stderr, "%s: unable to open signature file %s\n", progname, optarg);
+          exit(1);
+        }
+        strcpy(signature_name, optarg);
+        break;
+      case 'S':
+        s = atoi(optarg);
+        break;
+    }
+  }
+
+  argc -= optind;
+  argv += optind;
+
+  if (argc > 0) {
+    usage();
+    exit(1);
+  }
+
+  if (sig) {
+    char line[32];
+    fgets(line, sizeof(line), sig);
+    if (strspn(line, "WGSG") >= 4) {
+      if (n == 0)
+        fscanf(sig, "%d\n", &n);
+      else
+        fscanf(sig, "%*d\n");
+      if (a == 0.0)
+        fscanf(sig, "%lf\n", &a);
+      else
+        fscanf(sig, "%*lf\n");
+      if (b == 0.0)
+        fscanf(sig, "%lf\n", &b);
+      else
+        fscanf(sig, "%*lf\n");
+      if (e < 0)
+        fscanf(sig, "%d\n", &e);
+      else
+        fscanf(sig, "%*d\n");
+      if (f == 0)
+        fscanf(sig, "%d\n", &f);
+      else
+        fscanf(sig, "%*d\n");
+      if (!strcmp(F, ""))
+        fscanf(sig, "%[^\n\r]\n", &F);
+      else
+        fscanf(sig, "%*[^\n\r]\n");
+    }
+    else {
+      fprintf(stderr, "%s: invalid signature file %s\n", progname, signature_name);
+      exit(1);
+    }
+  }
+
+  if (s)
+    srandom(s);
+  else
+    srandom(time(NULL) * getpid());
+
+  fprintf(out, "WGSG\n");
+  fprintf(out, "%d\n", n);
+  fprintf(out, "%f\n", a);
+  fprintf(out, "%f\n", b);
+  fprintf(out, "%d\n", e);
+  fprintf(out, "%d\n", f);
+  fprintf(out, "%s\n", F);
+
+  n >>= 1;
+  while (n > 0) {
+    double x;
+    double x1, x2;
+
+    /*
+     * Algorithm P (Polar method for normal deviates),
+     * Knuth, D., "The Art of Computer Programming", Vol. 2, 3rd Edition, p. 122
+     */
+    do {
+      x1 = 2.0 * ((random() & RAND_MAX) / ((double) RAND_MAX + 1.0)) - 1.0;
+      x2 = 2.0 * ((random() & RAND_MAX) / ((double) RAND_MAX + 1.0)) - 1.0;
+      x = x1 * x1 + x2 * x2;
+    } while (x >= 1.0);
+    x1 *= sqrt((-2.0) * log(x) / x);
+    x2 *= sqrt((-2.0) * log(x) / x);
+
+    fprintf(out, "%f\n", m + d * x1);
+    fprintf(out, "%f\n", m + d * x2);
+
+    n--;
+  }
+
+  fclose(out);
+
+  exit(0);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Meerwald/gen_xia_sig.c	Sun Aug 12 13:14:34 2007 +0200
@@ -0,0 +1,198 @@
+#include "wm.h"
+
+char *progname;
+
+void usage(void) {
+  fprintf(stderr, "usage: %s [-a n] [-d n] [-e n] [-f n] [-F file] [-l n] [-m n] [-n n] [-o file] [-s file] [-S n]\n\n", progname);
+  fprintf(stderr, "\t-a n\t\talpha factor (default 0.2)\n");
+  fprintf(stderr, "\t-d n\t\tdeviation (default 1.0)\n");
+  fprintf(stderr, "\t-e n\t\twavelet filtering method (default 2)\n");
+  fprintf(stderr, "\t-f n\t\tfilter number (default 1)\n");
+  fprintf(stderr, "\t-F file\t\tfilter definition file (default 'filter.dat')\n");
+  fprintf(stderr, "\t-h\t\tprint usage\n");
+  fprintf(stderr, "\t-l n\t\tdecomposition level (default 2)\n");
+  fprintf(stderr, "\t-m n \t\tmean value (default 0.0)\n");
+  fprintf(stderr, "\t-n n\t\twatermark length (default 1000)\n");
+  fprintf(stderr, "\t-o file\t\toutput file\n");
+  fprintf(stderr, "\t-s file\t\tuse signature file's embedding information\n");
+  fprintf(stderr, "\t-S n\t\tseed\n");
+  exit(0);
+}
+
+int main(int argc, char *argv[]) {
+  FILE *out = stdout;
+  FILE *sig = NULL;
+
+  char output_name[MAXPATHLEN] = "(stdout)";
+  char signature_name[MAXPATHLEN];
+
+  int c;
+  int i;
+  int n = 1000;
+  int s = 0;
+  int e = 2;
+  int f = 1;
+  char F[MAXPATHLEN] = "filter.dat";
+  double a = 0.2;
+  int l = 2;
+  double m = 0.0;
+  double d = 1.0;
+
+  progname = argv[0];
+
+  while ((c = getopt(argc, argv, "a:l:d:e:f:F:h?m:n:o:s:S:")) != EOF) {
+    switch (c) {
+      case 'a':
+        a = atof(optarg);
+        if (a <= 0.0) {
+          fprintf(stderr, "%s: alpha factor %f out of range\n", progname, a);
+          exit(1);
+        }
+        break;
+      case 'l':
+        l = atoi(optarg);
+        if (l <= 0) {
+          fprintf(stderr, "%s: decomposition level %d out of range\n", progname, l);
+          exit(1);
+        }
+        break;
+      case 'd':
+        d = atof(optarg);
+        if (d <= 0.0) {
+          fprintf(stderr, "%s: deviation %f out of range\n", progname, d);
+          exit(1);
+        }
+        break;
+      case 'e':
+        e = atoi(optarg);
+        if (e < 0) {
+          fprintf(stderr, "%s: wavelet filtering method %d out of range\n", progname, e);
+        }
+        break;
+      case 'f':
+        f = atoi(optarg);
+        if (f <= 0) {
+          fprintf(stderr, "%s: filter number %d out of range\n", progname, f);
+          exit(1);
+        }
+        break;
+      case 'F':
+        strcpy(F, optarg);
+        break;
+      case 'h':
+      case '?':
+        usage();
+        break;
+      case 'm':
+        m = atof(optarg);
+        break;
+      case 'n':
+        n = atoi(optarg);
+        if (n < 1 || n > 32000) {
+          fprintf(stderr, "%s: watermark length %d out of range\n", progname, n);
+          exit(1);
+        }
+        break;
+      case 'o':
+        if ((out = fopen(optarg, "w")) == NULL) {
+          fprintf(stderr, "%s: unable to open output file %s\n", progname, optarg);
+          exit(1);
+        }
+        strcpy(output_name, optarg);
+        break;
+      case 's':
+        if ((sig = fopen(optarg, "r")) == NULL) {
+          fprintf(stderr, "%s: unable to open signature file %s\n", progname, optarg);
+          exit(1);
+        }
+        strcpy(signature_name, optarg);
+        break;
+      case 'S':
+        s = atoi(optarg);
+        break;
+    }
+  }
+
+  argc -= optind;
+  argv += optind;
+
+  if (argc > 0) {
+    usage();
+    exit(1);
+  }
+
+  if (sig) {
+    char line[32];
+    fgets(line, sizeof(line), sig);
+    if (strspn(line, "XASG") >= 4) {
+      if (n == 0)
+        fscanf(sig, "%d\n", &n);
+      else
+        fscanf(sig, "%*d\n");
+      if (a == 0.0)
+        fscanf(sig, "%lf\n", &a);
+      else
+        fscanf(sig, "%*lf\n");
+      if (l == 0)
+        fscanf(sig, "%d\n", &l);
+      else
+        fscanf(sig, "%*d\n");
+      if (e < 0)
+        fscanf(sig, "%d\n", &e);
+      else
+        fscanf(sig, "%*d\n");
+      if (f == 0)
+        fscanf(sig, "%d\n", &f);
+      else
+        fscanf(sig, "%*d\n");
+      if (!strcmp(F, ""))
+        fscanf(sig, "%[^\n\r]\n", &F);
+      else
+        fscanf(sig, "%*[^\n\r]\n");
+    }
+    else {
+      fprintf(stderr, "%s: invalid signature file %s\n", progname, signature_name);
+      exit(1);
+    }
+  }
+
+  if (s)
+    srandom(s);
+  else
+    srandom(time(NULL) * getpid());
+
+  fprintf(out, "XASG\n");
+  fprintf(out, "%d\n", n);
+  fprintf(out, "%f\n", a);
+  fprintf(out, "%d\n", l);
+  fprintf(out, "%d\n", e);
+  fprintf(out, "%d\n", f);
+  fprintf(out, "%s\n", F);
+
+  n >>= 1;
+  while (n > 0) {
+    double x;
+    double x1, x2;
+
+    /*
+     * Algorithm P (Polar method for normal deviates),
+     * Knuth, D., "The Art of Computer Programming", Vol. 2, 3rd Edition, p. 122
+     */
+    do {
+      x1 = 2.0 * ((random() & RAND_MAX) / ((double) RAND_MAX + 1.0)) - 1.0;
+      x2 = 2.0 * ((random() & RAND_MAX) / ((double) RAND_MAX + 1.0)) - 1.0;
+      x = x1 * x1 + x2 * x2;
+    } while (x >= 1.0);
+    x1 *= sqrt((-2.0) * log(x) / x);
+    x2 *= sqrt((-2.0) * log(x) / x);
+
+    fprintf(out, "%f\n", m + d * x1);
+    fprintf(out, "%f\n", m + d * x2);
+
+    n--;
+  }
+
+  fclose(out);
+
+  exit(0);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Meerwald/gen_xie_sig.c	Sun Aug 12 13:14:34 2007 +0200
@@ -0,0 +1,203 @@
+#include "wm.h"
+#include "signature.h"
+
+char *progname;
+
+void usage(void) {
+  fprintf(stderr, "usage: %s [-a n] [-e n] [-f n] [-F file] [-l n] [-n n] [-o file] [-s file] [-S n] [-v n] file\n\n", progname);
+  fprintf(stderr, "\t-a n\t\tembedding strength (default 0.5)\n");
+  fprintf(stderr, "\t-e n\t\twavelet filtering method (default 2)\n");
+  fprintf(stderr, "\t-f n\t\tfilter number (default 1)\n");
+  fprintf(stderr, "\t-F file\t\tfilter definition file (default 'filter.dat')\n");
+  fprintf(stderr, "\t-h\t\tprint usage\n");
+  fprintf(stderr, "\t-l n\t\tembedding level (default 5)\n");
+  fprintf(stderr, "\t-n n\t\twatermark bit length\n");
+  fprintf(stderr, "\t-o file\t\toutput file\n");
+  fprintf(stderr, "\t-s file\t\tuse signature file's embedding information\n");
+  fprintf(stderr, "\t-S n\t\tseed\n");
+  fprintf(stderr, "\t-v n\t\tverbosity level\n");
+  exit(0);
+}
+
+int main(int argc, char *argv[]) {
+  FILE *in = stdin;
+  FILE *out = stdout;
+  FILE *sig = NULL;
+
+  char output_name[MAXPATHLEN] = "(stdout)";
+  char input_name[MAXPATHLEN] = "(stdin)";
+  char signature_name[MAXPATHLEN];
+
+  int verbose = 0;
+  int c;
+  int i;
+  double a = 0.5;
+  int l = 5;
+  int n = 0, nb;
+  int s = 0;
+  int e = 2;
+  int f = 1;
+  char F[MAXPATHLEN] = "filter.dat";
+
+  progname = argv[0];
+  wm_init();
+
+  while ((c = getopt(argc, argv, "a:e:f:F:h?l:n:o:s:S:v:")) != EOF) {
+    switch (c) {
+      case 'a':
+        a = atof(optarg);
+        if (a <= 0.0) {
+          fprintf(stderr, "%s: embedding strength %f out of range\n", progname, a);
+          exit(1);
+        }
+        break;
+      case 'e':
+        e = atoi(optarg);
+        if (e < 0) {
+          fprintf(stderr, "%s: wavelet filtering method %d out of range\n", progname, e);
+        }
+        break;
+      case 'f':
+        f = atoi(optarg);
+        if (f <= 0) {
+          fprintf(stderr, "%s: filter number %d out of range\n", progname, f);
+          exit(1);
+        }
+        break;
+      case 'F':
+        strcpy(F, optarg);
+        break;
+      case 'h':
+      case '?':
+        usage();
+        break;
+      case 'l':
+        l = atoi(optarg);
+        if (l < 1) {
+          fprintf(stderr, "%s: embedding level out of range\n", progname);
+          exit(1);
+        }
+        break;
+      case 'n':
+        n = atoi(optarg);
+        if (n < 1 || n > 1000) {
+          fprintf(stderr, "%s: watermark length %d out of range\n", progname, n);
+          exit(1);
+        }
+        break;
+      case 'o':
+        if ((out = fopen(optarg, "wb")) == NULL) {
+          fprintf(stderr, "%s: unable to open output file %s\n", progname, optarg);
+          exit(1);
+        }
+        strcpy(output_name, optarg);
+        break;
+     case 's':
+        if ((sig = fopen(optarg, "r")) == NULL) {
+          fprintf(stderr, "%s: unable to open signature file %s\n", progname, optarg);
+          exit(1);
+        }
+        strcpy(signature_name, optarg);
+        break;
+      case 'S':
+        s = atoi(optarg);
+        break;
+      case 'v':
+        verbose = atoi(optarg);
+        if (verbose < 0) {
+          fprintf(stderr, "%s: verbosity level %d out of range", progname, verbose);
+          exit(1);
+        }
+        break;
+    }
+  }
+
+  argc -= optind;
+  argv += optind;
+
+  if (argc > 1) {
+    usage();
+    exit(1);
+  }
+
+  if (argc == 1 && *argv[0] != '-')
+  if ((in = fopen(argv[0], "rb")) == NULL) {
+    fprintf(stderr, "%s: unable to open input file %s\n", progname, argv[0]);
+    exit(1);
+  }
+  else
+    strcpy(input_name, argv[0]);
+
+  if (sig) {
+    char line[32];
+    fgets(line, sizeof(line), sig);
+    if (strspn(line, "XESG") >= 4) {
+      if (n == 0)
+        fscanf(sig, "%d\n", &n);
+      else
+        fscanf(sig, "%*d\n");
+      if (a == 0.0)
+        fscanf(sig, "%lf\n", &a);
+      else
+        fscanf(sig, "%*lf\n");
+      if (e < 0)
+        fscanf(sig, "%d\n", &e);
+      else
+        fscanf(sig, "%*d\n");
+      if (f == 0)
+        fscanf(sig, "%d\n", &f);
+      else
+        fscanf(sig, "%*d\n");
+      if (!strcmp(F, ""))
+        fscanf(sig, "%[^\n\r]\n", &F);
+      else
+        fscanf(sig, "%*[^\n\r]\n");
+      if (l == 0)
+        fscanf(sig, "%d\n", &l);
+      else
+        fscanf(sig, "%*d\n");
+    }
+   else {
+      fprintf(stderr, "%s: invalid signature file %s\n", progname, signature_name);
+      exit(1);
+    }
+    close(sig);
+  }
+
+  if (s)
+    srandom(s);
+  else
+    srandom(time(NULL) * getpid());
+
+  if (n > 0) {
+    nb = fread(signature, sizeof(char), i = NBITSTOBYTES(n), in);
+    if (nb < i) {
+      fprintf(stderr, "%s: failed to read all %d signature bits from %s\n", progname, n, input_name);
+      exit(1);
+    }
+  }
+  else {
+    if (fscanf(in, "%128[^\n\r]", signature) == EOF) {
+      fprintf(stderr, "%s: failed to read signature bits from %s\n", progname, input_name);
+      exit(1);
+    }
+    nb = strlen(signature);
+    n = NBYTESTOBITS(nb);
+    fprintf(stderr, "%s: got %d signature bits\n", progname, n);
+  }
+
+  fprintf(out, "XESG\n");
+  fprintf(out, "%d\n", n);
+  fprintf(out, "%f\n", a);
+  fprintf(out, "%d\n", e);
+  fprintf(out, "%d\n", f);
+  fprintf(out, "%s\n", F);
+  fprintf(out, "%d\n", l);
+  fprintf(out, "%d\n", random());
+  fwrite(signature, sizeof(char), nb, out);
+  fprintf(out, "\n");
+
+  fclose(out);
+
+  exit(0);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Meerwald/gen_zhu_sig.c	Sun Aug 12 13:14:34 2007 +0200
@@ -0,0 +1,198 @@
+#include "wm.h"
+
+char *progname;
+
+void usage(void) {
+  fprintf(stderr, "usage: %s [-a n] [-d n] [-e n] [-f n] [-F file] [-l n] [-m n] [-n n] [-o file] [-s file] [-S n]\n\n", progname);
+  fprintf(stderr, "\t-a n\t\talpha factor (default 0.2)\n");
+  fprintf(stderr, "\t-d n\t\tdeviation (default 1.0)\n");
+  fprintf(stderr, "\t-e n\t\twavelet filtering method (default 2)\n");
+  fprintf(stderr, "\t-f n\t\tfilter number (default 1)\n");
+  fprintf(stderr, "\t-F file\t\tfilter definition file (default 'filter.dat')\n");
+  fprintf(stderr, "\t-h\t\tprint usage\n");
+  fprintf(stderr, "\t-l n\t\tdecomposition level (default 7)\n");
+  fprintf(stderr, "\t-m n\t\tmean value (default 0.0)\n");
+  fprintf(stderr, "\t-n n\t\twatermark length (default 1000)\n");
+  fprintf(stderr, "\t-o file\t\toutput file\n");
+  fprintf(stderr, "\t-s file\t\tuse signature file's embedding information\n");
+  fprintf(stderr, "\t-S n\t\tseed\n");
+  exit(0);
+}
+
+int main(int argc, char *argv[]) {
+  FILE *out = stdout;
+  FILE *sig = NULL;
+
+  char output_name[MAXPATHLEN] = "(stdout)";
+  char signature_name[MAXPATHLEN];
+
+  int c;
+  int i;
+  int n = 1000;
+  int s = 0;
+  int e = 2;
+  int f = 1;
+  char F[MAXPATHLEN] = "filter.dat";
+  double a = 0.2;
+  double m = 0.0;
+  double d = 1.0;
+  int l = 7;
+
+  progname = argv[0];
+
+  while ((c = getopt(argc, argv, "a:d:e:f:F:h?l:m:n:o:s:S:")) != EOF) {
+    switch (c) {
+      case 'a':
+        a = atof(optarg);
+        if (a <= 0.0) {
+          fprintf(stderr, "%s: alpha factor %f out of range\n", progname, a);
+          exit(1);
+        }
+        break;
+      case 'l':
+        l = atoi(optarg);
+        if (l <= 0) {
+          fprintf(stderr, "%s: decomposition level %d out of range\n", progname, l);
+          exit(1);
+        }
+        break;
+      case 'd':
+        d = atof(optarg);
+        if (d <= 0.0) {
+          fprintf(stderr, "%s: deviation %f out of range\n", progname, d);
+          exit(1);
+        }
+        break;
+      case 'e':
+        e = atoi(optarg);
+        if (e < 0) {
+          fprintf(stderr, "%s: wavelet filtering method %d out of range\n", progname, e);
+        }
+        break;
+      case 'f':
+        f = atoi(optarg);
+        if (f <= 0) {
+          fprintf(stderr, "%s: filter number %d out of range\n", progname, f);
+          exit(1);
+        }
+        break;
+      case 'F':
+        strcpy(F, optarg);
+        break;
+      case 'h':
+      case '?':
+        usage();
+        break;
+      case 'm':
+        m = atof(optarg);
+        break;
+      case 'n':
+        n = atoi(optarg);
+        if (n < 1 || n > 32000) {
+          fprintf(stderr, "%s: watermark length %d out of range\n", progname, n);
+          exit(1);
+        }
+        break;
+      case 'o':
+        if ((out = fopen(optarg, "w")) == NULL) {
+          fprintf(stderr, "%s: unable to open output file %s\n", progname, optarg);
+          exit(1);
+        }
+        strcpy(output_name, optarg);
+        break;
+      case 's':
+        if ((sig = fopen(optarg, "r")) == NULL) {
+          fprintf(stderr, "%s: unable to open signature file %s\n", progname, optarg);
+          exit(1);
+        }
+        strcpy(signature_name, optarg);
+        break;
+      case 'S':
+        s = atoi(optarg);
+        break;
+    }
+  }
+
+  argc -= optind;
+  argv += optind;
+
+  if (argc > 0) {
+    usage();
+    exit(1);
+  }
+
+  if (sig) {
+    char line[32];
+    fgets(line, sizeof(line), sig);
+    if (strspn(line, "ZHSG") >= 4) {
+      if (n == 0)
+        fscanf(sig, "%d\n", &n);
+      else
+        fscanf(sig, "%*d\n");
+      if (a == 0.0)
+        fscanf(sig, "%lf\n", &a);
+      else
+        fscanf(sig, "%*lf\n");
+      if (l == 0)
+        fscanf(sig, "%d\n", &l);
+      else
+        fscanf(sig, "%*d\n");
+      if (e < 0)
+        fscanf(sig, "%d\n", &e);
+      else
+        fscanf(sig, "%*d\n");
+      if (f == 0)
+        fscanf(sig, "%d\n", &f);
+      else
+        fscanf(sig, "%*d\n");
+      if (!strcmp(F, ""))
+        fscanf(sig, "%[^\n\r]\n", &F);
+      else
+        fscanf(sig, "%*[^\n\r]\n");
+    }
+    else {
+      fprintf(stderr, "%s: invalid signature file %s\n", progname, signature_name);
+      exit(1);
+    }
+  }
+
+  if (s)
+    srandom(s);
+  else
+    srandom(time(NULL) * getpid());
+
+  fprintf(out, "ZHSG\n");
+  fprintf(out, "%d\n", n);
+  fprintf(out, "%f\n", a);
+  fprintf(out, "%d\n", l);
+  fprintf(out, "%d\n", e);
+  fprintf(out, "%d\n", f);
+  fprintf(out, "%s\n", F);
+
+  n >>= 1;
+  while (n > 0) {
+    double x;
+    double x1, x2;
+
+    /*
+     * Algorithm P (Polar method for normal deviates),
+     * Knuth, D., "The Art of Computer Programming", Vol. 2, 3rd Edition, p. 122
+     */
+    do {
+      x1 = 2.0 * ((random() & RAND_MAX) / ((double) RAND_MAX + 1.0)) - 1.0;
+      x2 = 2.0 * ((random() & RAND_MAX) / ((double) RAND_MAX + 1.0)) - 1.0;
+      x = x1 * x1 + x2 * x2;
+    } while (x >= 1.0);
+    x1 *= sqrt((-2.0) * log(x) / x);
+    x2 *= sqrt((-2.0) * log(x) / x);
+
+    fprintf(out, "%f\n", m + d * x1);
+    fprintf(out, "%f\n", m + d * x2);
+
+    n--;
+  }
+
+  fclose(out);
+
+  exit(0);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Meerwald/gray.c	Sun Aug 12 13:14:34 2007 +0200
@@ -0,0 +1,117 @@
+#include "wm.h"
+#include "gray.h"
+
+gray **alloc_grays_8x8() {
+  return alloc_grays(8, 8);
+}
+
+gray **alloc_grays(int cols, int rows) {
+  gray **p;
+  int i;
+
+  p = (gray **)malloc(rows * sizeof(gray *));
+  if (!p) {
+#ifdef DEBUG
+    fprintf(stderr, "alloc_grays(): malloc() failed\n");
+    exit(1);
+#else
+    return NULL;
+#endif
+  }
+
+  p[0] = (gray *)malloc(rows * cols * sizeof(gray));
+  if (!p[0]) {
+#ifdef DEBUG
+    fprintf(stderr, "alloc_grays(): malloc() failed\n");
+    exit(1);
+#else
+    free(p);
+    return NULL;
+#endif
+  }
+
+  for (i = 1; i < rows; i++) {
+    p[i] = &(p[0][i * cols]);
+  }
+
+  return p;
+}
+
+void free_grays(gray **grays) {
+  free(grays[0]);
+  free(grays);
+}
+
+void copy_grays_to_block(gray ** block_grays, gray ** image_grays, int c, int r, int w, int h) {
+  int i, j;
+
+#ifdef DEBUG
+  if (!image_grays) {
+    fprintf(stderr, "copy_grays_to_block(): NULL image pixels\n");
+  }
+  if (!block_grays) {
+    fprintf(stderr, "copy_grays_to_block(): NULL block pixels\n");
+  }
+  if (w <= 0 || h <= 0 || c < 0 || r < 0) {
+    fprintf(stderr, "copy_grays_to_block(): block dimension out of range\n");
+  }
+#endif
+  
+  for (i = 0; i < w; i++) {
+    for (j = 0; j < h; j++)
+      block_grays[j][i] = image_grays[r + j][c + i];
+  }
+}
+
+void copy_grays_from_block(gray ** image_grays, gray ** block_grays, int
+c, int r, int w, int h) {
+  int i, j;
+
+#ifdef DEBUG
+  if (!image_grays) {
+    fprintf(stderr, "copy_grays_from_block(): NULL image pixels\n");
+  }
+  if (!block_grays) {
+    fprintf(stderr, "copy_grays_from_block(): NULL block pixels\n");
+  }
+  if (w <= 0 || h <= 0 || c < 0 || r < 0) {
+    fprintf(stderr, "copy_grays_from_block(): block dimension out of range\n");
+  }
+#endif
+  
+  for (i = 0; i < w; i++) {
+    for (j = 0; j < h; j++)
+      image_grays[r + j][c + i] = block_grays[j][i];
+  }
+}
+
+void print_grays(gray **grays, int c, int r, int w, int h) {
+  int i, j;
+  gray *p;
+
+#ifdef DEBUG
+  if (!grays) {
+    fprintf(stderr, "print_grays(): NULL pixels\n");
+  }
+  if (w <= 0 || h <= 0 || c < 0 || r < 0) {
+    fprintf(stderr, "print_grays(): block dimension out of range\n");
+  }
+#endif
+
+  for (j = r; j < r + h; j++) {
+    p = &grays[j][c];
+    for (i = 0; i < w; i++)
+      fprintf(stderr, "%3d ", *(p++));
+    fprintf(stderr, "\n");
+  }
+}
+
+void print_grays_8x8(gray **grays) {
+  int i, j;
+
+  for (i = 0; i < 8; i++) {
+    for (j = 0; j < 8; j++)
+      fprintf(stderr, "%3d ", grays[i][j]);
+    fprintf(stderr, "\n");
+  }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Meerwald/gray.h	Sun Aug 12 13:14:34 2007 +0200
@@ -0,0 +1,14 @@
+#ifndef GRAY_H
+#define GRAY_H
+
+#include "wm.h"
+#include "pgm.h"
+
+gray **alloc_grays(int cols, int rows);
+gray **alloc_grays_8x8();
+void free_grays(gray **grays);
+void copy_grays_to_block(gray ** block_grays, gray ** image_grays, int col, int row, int width, int height);
+void copy_grays_from_block(gray ** image_grays, gray ** block_grays, int col, int row, int width, int height);
+void print_grays(gray **grays, int col, int row, int width, int height);
+void print_grays_8x8(gray **grays);
+#endif
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Meerwald/kim.wm	Sun Aug 12 13:14:34 2007 +0200
@@ -0,0 +1,1357 @@
+KIWM
+1355
+0.962332
+0.556667
+0.082221
+-0.633609
+0.096048
+-0.194063
+0.123496
+0.122363
+0.146482
+0.391184
+-0.526367
+-1.877353
+-1.372872
+-0.561188
+-0.281722
+1.638267
+-1.229134
+0.160058
+0.472432
+0.221371
+0.702672
+0.048673
+0.989222
+-1.919514
+-0.754875
+2.555153
+0.588800
+-0.230591
+-1.268933
+-0.432563
+-1.148047
+1.357527
+-2.171152
+-1.224077
+0.738547
+-0.744086
+-2.065068
+-0.247288
+-0.340216
+-0.375178
+-1.423221
+1.810807
+-0.424804
+2.377079
+-0.327323
+-1.021380
+-0.523512
+-1.836423
+1.165727
+-0.504592
+0.809199
+-0.000000
+1.526998
+-0.849962
+0.150998
+0.012201
+0.636885
+-0.887091
+0.951992
+-0.141332
+0.012882
+2.134151
+0.530619
+1.086284
+-0.077457
+0.151248
+0.472596
+0.111207
+-1.814436
+-2.183967
+-1.219403
+-0.151640
+-1.809015
+1.220303
+0.306635
+1.195953
+1.020683
+-0.162146
+-0.570420
+0.670643
+-0.546657
+0.675466
+0.344063
+0.911147
+-0.604959
+-0.143986
+0.344271
+1.647242
+-0.985017
+0.780793
+0.449889
+-1.545793
+1.597551
+-0.851752
+-0.218907
+-0.716190
+0.190646
+-0.992265
+0.994210
+-1.308444
+-0.773073
+0.102998
+0.223968
+-0.382646
+-1.252377
+0.813933
+-0.915755
+0.056218
+-0.203382
+-0.111543
+-1.336821
+0.449946
+1.740969
+-1.707382
+0.731193
+-1.303742
+-0.710640
+0.984013
+-0.410900
+-0.564259
+1.234480
+1.160097
+-1.103943
+-1.142045
+0.576878
+-0.181864
+-0.485015
+-0.192903
+0.018258
+-0.995477
+0.341180
+1.766650
+1.924044
+1.247036
+-1.184311
+0.340864
+-0.765852
+0.711104
+-2.257150
+0.171806
+1.255734
+0.946823
+1.014442
+0.549990
+0.444585
+0.345394
+-1.583237
+-0.365796
+0.241952
+0.292189
+-0.979635
+-0.107870
+-0.380929
+-1.064084
+-2.073624
+0.134566
+1.408207
+0.438263
+-1.423864
+1.025784
+0.770359
+-1.198515
+1.465579
+0.090389
+-0.429007
+-0.786517
+0.238290
+0.266943
+0.496165
+0.945898
+1.238995
+-0.187096
+0.899346
+0.505563
+0.305432
+-0.277959
+0.643918
+-1.165478
+-0.146899
+0.240230
+0.333667
+-0.572118
+0.177290
+-0.534499
+0.743019
+-0.684625
+-1.649618
+0.354437
+1.560532
+0.368007
+0.649749
+0.955202
+2.480710
+0.446286
+1.202847
+-1.204399
+-2.191566
+-0.010944
+0.722918
+-0.892965
+-0.881475
+-1.050047
+-0.434134
+2.116337
+-0.356573
+1.175708
+0.234469
+-0.739920
+-0.648118
+0.539135
+-1.775614
+-1.661253
+-0.412639
+-0.790764
+0.177378
+-0.074719
+0.069769
+2.054109
+-0.965241
+0.289114
+-0.280887
+-0.403755
+1.128699
+-1.975665
+1.304009
+1.933895
+0.215058
+-0.492331
+2.718813
+-0.803870
+0.413460
+1.072356
+1.442729
+1.270637
+1.203333
+0.393772
+-1.326521
+-0.776050
+-0.574517
+-0.705867
+-1.437651
+-0.640251
+0.885677
+-0.471762
+1.668912
+-0.813074
+0.914347
+-1.185763
+-0.986176
+-0.915537
+-0.369830
+-0.276946
+-0.448809
+-0.346480
+-2.005974
+1.595203
+0.163654
+-0.293149
+-1.153530
+-1.774225
+0.893254
+-1.062011
+0.629967
+-1.271504
+-0.322958
+0.261003
+-0.032646
+0.267219
+-0.892035
+-0.462762
+-0.549258
+1.183236
+1.197246
+-1.693596
+0.502211
+-1.319969
+0.007531
+-0.696435
+0.907949
+1.601883
+-0.488034
+0.157065
+0.256474
+1.080514
+-1.005948
+0.823408
+0.367914
+0.859020
+0.508878
+1.009951
+0.676905
+1.410009
+-0.931537
+1.861433
+0.123460
+-0.350943
+0.821319
+0.590396
+0.681364
+-0.685216
+0.516104
+0.552966
+-0.608172
+-0.146709
+0.109984
+0.253258
+-2.250772
+1.062844
+0.931289
+1.731681
+0.159618
+-1.106649
+0.225650
+1.377349
+0.647308
+-0.413768
+2.115625
+0.263609
+0.988429
+1.796713
+-0.754644
+-1.024075
+-0.884133
+1.317469
+1.854804
+-0.597290
+-0.192368
+-0.194233
+-2.206987
+1.450779
+-0.758369
+-0.797507
+-0.528943
+0.557464
+0.095253
+-0.648942
+0.049879
+-1.025507
+0.363632
+-0.404161
+-0.556897
+-1.104042
+-0.727984
+-0.500627
+-0.510666
+0.001622
+0.969936
+-0.228339
+1.479599
+0.888408
+-0.228277
+0.657491
+1.071187
+0.211604
+-0.014905
+0.342410
+0.766951
+1.608364
+0.327121
+-0.893321
+0.505270
+-0.553077
+-1.695186
+-0.146973
+-1.348171
+-0.556646
+0.974448
+2.579097
+0.374829
+1.932532
+1.216651
+0.173396
+-0.253070
+0.362591
+-0.794043
+-0.843569
+0.509245
+1.285380
+1.327135
+0.901422
+1.716964
+-1.230809
+0.485979
+-1.417534
+-0.454355
+-0.199235
+-0.317006
+0.722096
+-1.569581
+1.433715
+-1.445786
+1.543912
+-1.516668
+0.172061
+0.097022
+-0.649209
+0.364013
+-0.190471
+0.312249
+1.935630
+0.921477
+-0.580349
+1.832545
+0.087918
+0.398211
+-0.091384
+0.682236
+0.137163
+0.152337
+-0.572804
+0.493609
+-1.947580
+1.569860
+0.232433
+0.231307
+1.495536
+-0.240642
+1.083944
+-0.177901
+-1.087129
+-1.588726
+-1.327508
+0.070794
+-1.956181
+-0.905052
+1.408029
+1.018116
+0.111809
+0.997380
+1.613238
+0.595723
+-1.036768
+1.082797
+1.144363
+-1.461671
+-1.187270
+0.522118
+0.562675
+-0.392964
+0.355249
+0.506514
+-0.008255
+1.534232
+-1.399326
+0.697663
+-0.824827
+-1.095458
+1.181808
+-1.400085
+1.075670
+-0.776688
+-1.791683
+0.405204
+-0.064481
+1.173024
+0.042371
+-1.456490
+1.365541
+-1.936723
+-0.633273
+0.018991
+-0.559432
+-1.938210
+0.346755
+0.958718
+-0.687103
+-0.802676
+-0.075698
+0.699671
+1.030273
+-1.485057
+-2.241910
+-0.774622
+-0.327114
+-2.311965
+1.164833
+1.335756
+-1.300271
+1.294052
+0.077326
+0.077266
+0.159941
+-0.000000
+-1.626692
+-1.138459
+1.974884
+-0.845371
+1.029784
+-0.353462
+0.162361
+1.274496
+-0.529787
+-1.350163
+0.647513
+1.251816
+-1.047685
+-0.627875
+-0.262224
+-1.139110
+0.040953
+0.571867
+-0.561651
+-0.231005
+0.354954
+0.368241
+1.868675
+-0.165666
+-1.499194
+-0.470659
+-0.243620
+-0.627829
+-0.422844
+-1.410118
+0.261456
+0.979537
+0.027163
+-0.116895
+-0.240002
+-2.097195
+-0.712792
+0.103366
+-0.108797
+0.583712
+0.700059
+-0.180130
+0.642766
+-0.691701
+-0.922612
+-0.906579
+0.237463
+-0.912041
+0.459539
+-1.552557
+0.977236
+0.865687
+-0.232066
+0.562247
+0.057908
+-0.105468
+-0.494112
+0.933916
+0.055251
+0.356051
+1.073339
+0.833233
+-0.218228
+0.817913
+1.134855
+-1.293821
+-0.003103
+0.383705
+2.600835
+-0.293719
+1.321608
+1.348991
+0.265581
+-0.111605
+0.570303
+-0.720707
+0.712688
+0.171599
+-0.805356
+-1.204556
+0.092175
+1.937029
+-0.248083
+1.130669
+2.216255
+-0.208008
+-0.598859
+-0.475199
+-0.703773
+1.061720
+-0.366410
+0.736291
+-2.175200
+-0.618288
+0.366664
+0.022255
+2.448268
+0.972673
+0.773316
+-0.929258
+-1.448055
+1.326897
+-0.033220
+1.400053
+0.085527
+1.475316
+-2.523901
+-0.562970
+0.077428
+1.305169
+-1.845645
+0.536509
+0.913856
+-1.998615
+1.785089
+0.085965
+-0.153676
+-0.684244
+-0.264492
+0.634034
+0.706441
+-0.182099
+-0.056047
+-0.008010
+0.448742
+-0.823136
+1.823259
+-1.949795
+-0.001492
+0.570050
+0.920788
+-2.458473
+1.744821
+-0.199208
+-0.163441
+-1.972016
+0.783169
+1.484371
+0.838996
+0.199467
+2.068226
+1.118419
+-0.082664
+0.875158
+0.153034
+0.334282
+0.626632
+1.057521
+-0.330643
+0.547296
+0.129792
+-2.459100
+-1.150473
+-2.271778
+0.929821
+0.587366
+1.249803
+-0.815444
+-0.114226
+-1.591833
+1.457586
+-0.145794
+0.608559
+-0.889411
+1.604052
+-1.260099
+-2.189924
+0.857393
+-0.465808
+-1.767197
+0.010157
+-1.356003
+0.875180
+-0.088985
+-0.728166
+-0.500725
+0.790471
+1.129603
+-0.805891
+-0.545498
+-0.375471
+1.647759
+0.102118
+-0.511146
+0.403103
+0.021988
+0.517253
+0.629728
+-1.376084
+-2.325633
+-0.542278
+2.060301
+-0.658047
+-0.294551
+0.054392
+0.030098
+0.055687
+-0.041833
+0.172909
+0.381885
+0.499665
+-0.274878
+0.300686
+0.426879
+0.571290
+-0.151969
+0.093513
+0.822162
+-1.447117
+-0.437842
+-0.077609
+0.346521
+-0.506714
+-1.165304
+-0.410199
+-0.697889
+0.714022
+-0.838594
+1.011880
+-0.146804
+-0.021718
+-0.958048
+0.044506
+-0.632981
+-0.148508
+-0.800510
+0.297188
+-0.573323
+-1.199200
+-0.135732
+-1.073606
+-0.587947
+0.139860
+0.244110
+0.056004
+-0.987948
+0.261046
+-0.762227
+-0.473150
+-0.901566
+-1.345361
+-0.416543
+0.107324
+0.070963
+-0.991099
+1.121917
+-0.198889
+0.979131
+-0.706490
+0.318302
+-1.006848
+-0.045405
+-0.819774
+-1.734816
+0.263146
+0.559066
+-1.324734
+-1.503505
+-0.317212
+-1.213582
+-0.472405
+-0.398811
+-0.084117
+0.042810
+0.018063
+0.126446
+-0.300849
+-1.438995
+1.059823
+0.905066
+-1.191017
+-0.412561
+1.401556
+1.682639
+1.235175
+1.510889
+-0.478064
+0.787609
+-0.248825
+1.095951
+-2.025804
+-0.073810
+1.297199
+0.205603
+-1.625678
+0.037104
+2.478620
+0.260394
+-1.412734
+0.379282
+-1.097277
+0.345453
+0.562203
+-0.967125
+0.723834
+-0.536682
+0.511301
+-0.241997
+1.809698
+-0.856378
+-0.686157
+1.065629
+1.237332
+-0.483861
+-1.124981
+1.145046
+-2.257304
+-1.398478
+0.380329
+0.388370
+1.364487
+-1.661558
+-0.932519
+2.584794
+-0.834474
+0.507069
+-0.075090
+-0.500025
+-0.796710
+-0.328448
+0.040379
+1.668595
+0.031868
+1.093909
+-0.839879
+-0.773817
+-0.214583
+-0.148545
+0.029929
+0.558572
+3.001701
+-1.234879
+0.298178
+-0.063330
+0.221258
+0.505887
+1.093529
+-0.133752
+0.472158
+-0.784292
+1.898582
+-0.797994
+0.838201
+1.079857
+-0.555587
+-1.174358
+0.439672
+1.019777
+-0.251591
+1.938149
+1.961025
+1.393031
+1.157179
+0.143640
+0.162219
+-1.654668
+-0.391720
+-0.850136
+-0.843736
+-1.098856
+-0.426070
+1.031232
+0.185338
+-2.378791
+0.785136
+-0.472527
+1.356798
+-0.048270
+-1.219499
+-0.000014
+0.000000
+1.653761
+0.926627
+-0.183265
+0.541314
+-0.792713
+1.132386
+0.061920
+0.377768
+-1.729287
+1.409065
+1.362526
+1.237328
+0.275936
+-0.173801
+-0.792286
+0.898927
+0.841566
+0.455687
+-0.787783
+-0.918078
+-0.051485
+1.545538
+-0.548565
+-1.232519
+0.485778
+-1.145190
+-1.205461
+-0.376026
+1.146577
+0.163427
+-0.170428
+-0.254409
+1.727431
+2.004142
+0.573157
+-0.580318
+0.039385
+-1.473294
+0.578885
+-0.531143
+0.242427
+0.134932
+-0.063548
+0.108608
+-0.703366
+0.046938
+-0.195253
+1.128167
+-1.244153
+0.013840
+1.426704
+2.175085
+0.852291
+-0.629366
+1.205126
+1.587903
+-0.225055
+0.730826
+0.199188
+0.262757
+-2.026036
+2.548802
+0.067432
+0.337652
+-1.200474
+0.390289
+0.724912
+-0.728293
+-0.400125
+1.057730
+0.284512
+1.356845
+1.262961
+0.715332
+0.219038
+0.838986
+-0.079223
+1.207940
+-0.864689
+-1.403007
+0.702135
+0.304981
+-0.715290
+-0.179093
+-0.654140
+-0.592485
+-0.203102
+0.641075
+-1.160231
+0.137886
+0.044852
+0.814669
+0.474713
+0.578984
+1.339580
+-0.704257
+2.218421
+-0.053910
+-0.300057
+-1.115984
+-0.283288
+0.837244
+-0.649886
+0.544806
+0.390755
+-0.678420
+0.774365
+0.230305
+-1.233942
+-0.558171
+0.641170
+-0.212701
+0.839399
+-0.145086
+-1.133135
+0.950919
+-0.019963
+-0.666213
+-1.468022
+0.043254
+0.592090
+-0.503930
+0.136585
+0.713911
+1.020836
+0.163338
+-0.167977
+1.189986
+-0.925863
+0.942145
+1.931373
+2.410760
+1.502377
+0.480816
+-0.410125
+-1.754269
+1.771161
+1.138513
+-0.439610
+0.519642
+-0.514121
+-0.184253
+-0.554452
+-0.906019
+-0.051763
+-0.466834
+1.056017
+0.486042
+-0.013974
+-0.604122
+-0.034387
+-0.391313
+0.137949
+0.178621
+0.168726
+0.384911
+-0.516506
+-1.858138
+-1.272083
+-0.586784
+-0.210750
+1.565293
+-1.193789
+0.067808
+0.444774
+0.225569
+0.816752
+0.193715
+1.009110
+-1.966002
+-0.749950
+2.619986
+0.541126
+-0.248174
+-1.334370
+-0.546271
+-1.129650
+1.312073
+-2.186958
+-1.225178
+0.738282
+-0.704350
+-1.990512
+-0.263080
+-0.337961
+-0.339003
+-1.395911
+1.713285
+-0.442898
+2.271419
+-0.311727
+-1.007631
+-0.454274
+-1.939454
+1.047500
+-0.438382
+0.775041
+-0.190614
+1.490205
+-0.673372
+0.086851
+0.023908
+0.633164
+-0.955483
+0.991228
+-0.159539
+-0.110448
+2.114254
+0.576117
+1.021641
+-0.057840
+0.038827
+0.374448
+0.047520
+-1.832008
+-2.191160
+-1.225659
+-0.199752
+-1.994375
+1.179066
+0.276245
+1.145432
+0.949971
+-0.201142
+-0.592021
+0.602002
+-0.591986
+0.557764
+0.199068
+0.914678
+-0.628383
+-0.096795
+0.353055
+1.701438
+-1.104040
+0.784143
+0.372677
+-1.422581
+1.660286
+-0.982775
+-0.033252
+-0.673421
+-0.059739
+-0.976178
+0.966688
+-1.323452
+-0.745806
+0.242133
+0.232929
+-0.375061
+-1.086295
+0.801582
+-0.984452
+0.057480
+-0.259334
+-0.075078
+-1.292897
+0.439195
+1.845204
+-1.743856
+0.681346
+-1.269916
+-0.651877
+0.956892
+-0.489734
+-0.455425
+1.345978
+1.346358
+-1.034300
+-1.108306
+0.543621
+-0.178666
+-0.435083
+-0.285505
+0.152209
+-0.866159
+0.335573
+1.937581
+2.009012
+1.124180
+-1.110009
+0.391862
+-0.627807
+0.756705
+-2.222022
+0.259731
+1.221079
+0.895368
+1.039731
+0.558807
+0.409755
+0.325785
+-1.521218
+-0.461542
+0.212405
+0.135540
+-0.999926
+0.050023
+-0.441320
+-0.959328
+-2.117983
+0.127653
+1.397314
+0.465269
+-1.442558
+1.032142
+0.687093
+-1.157764
+1.454994
+0.176766
+-0.450301
+-0.845662
+0.254797
+0.300438
+0.499923
+0.841109
+1.189231
+-0.389316
+0.903121
+0.429228
+0.354709
+-0.278802
+0.569597
+-1.250894
+-0.078873
+0.262799
+0.408799
+-0.662547
+0.073364
+-0.539975
+0.697825
+-0.729300
+-1.667902
+0.404374
+1.508858
+0.457223
+0.600935
+0.926265
+2.371768
+0.400843
+1.152092
+-1.210325
+-2.236770
+-0.077011
+0.647857
+-0.916284
+-0.896387
+-1.059701
+-0.405193
+2.059824
+-0.378898
+1.139001
+0.299734
+-0.873416
+-0.713086
+0.475052
+-1.833489
+-1.521881
+-0.503475
+-0.813902
+0.342933
+0.084518
+0.203218
+2.225871
+-0.914185
+0.372621
+-0.461066
+-0.214351
+1.058619
+-1.990932
+1.379988
+1.978481
+0.049753
+-0.511893
+2.783136
+-0.771894
+0.388456
+1.012734
+1.413472
+1.307668
+1.082720
+0.367148
+-1.286758
+-0.747318
+-0.591471
+-0.768500
+-1.361262
+-0.508793
+0.848881
+-0.516767
+1.606654
+-0.789966
+0.873479
+-1.178956
+-0.846285
+-1.063528
+-0.347458
+-0.341720
+-0.493649
+-0.392845
+-2.026197
+1.678537
+0.178448
+-0.364740
+-1.083970
+-1.719471
+0.822012
+-1.028957
+0.494546
+-1.368308
+-0.254854
+0.239639
+0.071094
+0.280322
+-0.778433
+-0.358841
+-0.505919
+1.215691
+1.244249
+-1.763283
+0.489019
+-1.180686
+-0.114219
+-0.610462
+0.899572
+1.549260
+-0.510368
+0.117466
+0.146705
+1.075438
+-1.016334
+0.764884
+0.444672
+0.821124
+0.554229
+0.990804
+0.580272
+1.350343
+-1.034901
+1.859178
+0.151922
+-0.406281
+0.820652
+0.546970
+0.646543
+-0.565058
+0.587740
+0.639578
+-0.695414
+-0.156158
+0.000908
+0.390031
+-2.275600
+1.163262
+0.848753
+1.717367
+0.171598
+-1.172301
+0.228746
+1.469253
+0.589259
+-0.438635
+2.210261
+0.403187
+0.824944
+1.817292
+-0.788960
+-1.063290
+-0.752655
+1.362129
+1.906240
+-0.617246
+-0.150002
+-0.208212
+-2.255388
+1.377619
+-0.894031
+-0.745722
+-0.610713
+0.487531
+0.065207
+-0.690747
+0.045275
+-1.024638
+0.248709
+-0.470497
+-0.488711
+-0.968175
+-0.819445
+-0.474832
+-0.506707
+0.042432
+0.932488
+-0.232458
+1.559593
+0.777438
+-0.123535
+0.689403
+0.970863
+0.164986
+0.159591
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Meerwald/kim_common.c	Sun Aug 12 13:14:34 2007 +0200
@@ -0,0 +1,60 @@
+#include "wm.h"
+#include "kim_common.h"
+
+
+// find the largest absolute coefficient of a subband
+double find_subband_largest_coeff(Image_tree s, int subband, int verbose) {
+  int i, j;
+  double max;
+
+  max = 0.0;
+  for (i = 5; i < s->image->height-5; i++)
+    for (j = 5; j < s->image->width-5; j++) {
+      double coeff;
+
+      coeff = fabs(get_pixel(s->image, i, j));
+      if (coeff > max) 
+        max = coeff;
+    }
+
+  if (verbose > 8)
+    fprintf(stderr, "  subband %f\n", max);
+
+  return max;
+}
+
+// find largest absolute coefficient of the detail subbands (LH, HL, HH) of 
+// a decomposition level
+double find_level_largest_coeff(Image_tree p, int verbose) {
+  double h, v, d;
+
+  h = find_subband_largest_coeff(p->horizontal, HORIZONTAL, verbose);
+  v = find_subband_largest_coeff(p->vertical, VERTICAL, verbose);
+  d = find_subband_largest_coeff(p->diagonal, DIAGONAL, verbose);
+
+  return MAX(h, MAX(v, d));
+}
+
+// calculate the significance threshold given the maximum absolute
+// coefficient at a decomposition level
+double calc_level_threshold(double max_coeff, int verbose) {
+  double threshold;
+
+  threshold = pow(2.0, floor(log(max_coeff) / log(2.0)) - 1.0);
+
+  if (verbose > 7)
+    fprintf(stderr, "  max %f, threshold %f\n", max_coeff, threshold);
+
+  return threshold;
+}
+
+// calculate an appropriate embedding strength for a given decomposition level
+// and a base alpha strength
+double calc_level_alpha_detail(double alpha, int maxlevels, int level, int verbose) {
+  double level_alpha;
+
+  level_alpha = alpha / pow(2.0, level - 1);
+
+  return level_alpha;
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Meerwald/kim_common.h	Sun Aug 12 13:14:34 2007 +0200
@@ -0,0 +1,13 @@
+#ifndef KIM_COMMON_H
+#define KIM_COMMON_H
+
+#include "dwt.h"
+#include "dwt_util.h"
+
+double find_subband_largest_coeff(Image_tree p, int subband, int verbose);
+double find_level_largest_coeff(Image_tree p, int verbose);
+
+double calc_level_threshold(double max_coeff, int verbose);
+double calc_level_alpha_detail(double alpha, int maxlevels, int level, int verbose);
+
+#endif
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Meerwald/signature.c	Sun Aug 12 13:14:34 2007 +0200
@@ -0,0 +1,95 @@
+#include "signature.h"
+
+void init_signature_bits() {
+  bzero(signature, sizeof(signature));
+}
+
+void init_signature1_bits() {
+  bzero(signature1, sizeof(signature1));
+}
+
+void init_signature2_bits() {
+  bzero(signature2, sizeof(signature2));
+}
+
+int get_signature_bit(int n) {
+  int byte = n >> 3;
+  int bit = n & 7;
+
+#ifdef DEBUG
+  if (byte < 0 || byte >= NSIGNATURE)
+    fprintf(stderr, "get_signature_bit(): index out of range\n");
+#endif
+
+  return (signature[byte] & (1 << bit)) >> bit;
+}
+
+int get_signature1_bit(int n) {
+  int byte = n >> 3;
+  int bit = n & 7;
+
+#ifdef DEBUG
+  if (byte < 0 || byte >= NSIGNATURE)
+    fprintf(stderr, "get_signature1_bit(): index out of range\n");
+#endif
+
+  return (signature1[byte] & (1 << bit)) >> bit;
+}
+
+int get_signature2_bit(int n) {
+  int byte = n >> 3;
+  int bit = n & 7;
+
+#ifdef DEBUG
+  if (byte < 0 || byte >= NSIGNATURE)
+    fprintf(stderr, "get_signature2_bit(): index out of range\n");
+#endif
+
+  return (signature2[byte] & (1 << bit)) >> bit;
+}
+
+void set_signature_bit(int n, int v) {
+  int byte = n >> 3;
+  int bit = n & 7;
+
+#ifdef DEBUG
+  if (byte < 0 || byte >= NSIGNATURE)
+    fprintf(stderr, "get_signature_bit(): index out of range\n");
+#endif
+
+  if (v)
+    signature[byte] |= (1 << bit);
+  else
+    signature[byte] &= ~(1 << bit);
+}
+
+void set_signature1_bit(int n, int v) {
+  int byte = n >> 3;
+  int bit = n & 7;
+
+#ifdef DEBUG
+  if (byte < 0 || byte >= NSIGNATURE)
+    fprintf(stderr, "get_signature1_bit(): index out of range\n");
+#endif
+
+  if (v)
+    signature1[byte] |= (1 << bit);
+  else
+    signature1[byte] &= ~(1 << bit);
+}
+
+void set_signature2_bit(int n, int v) {
+  int byte = n >> 3;
+  int bit = n & 7;
+
+#ifdef DEBUG
+  if (byte < 0 || byte >= NSIGNATURE)
+    fprintf(stderr, "get_signature2_bit(): index out of range\n");
+#endif
+
+  if (v)
+    signature2[byte] |= (1 << bit);
+  else
+    signature2[byte] &= ~(1 << bit);
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Meerwald/signature.h	Sun Aug 12 13:14:34 2007 +0200
@@ -0,0 +1,32 @@
+#ifndef SIGNATURE_H
+#define SIGNATURE_H
+
+#include "wm.h"
+
+#define NSIGNATURE 4096
+#define NBITSIGNATURE (NSIGNATURE * 8)
+
+int n_signature;
+int nbit_signature;
+int n_signature1;
+int nbit_signature1;
+int n_signature2;
+int nbit_signature2;
+
+char signature[NSIGNATURE];
+char signature1[NSIGNATURE];
+char signature2[NSIGNATURE];
+
+void init_signature_bits();
+int get_signature_bit(int n);
+void set_signature_bit(int n, int v);
+
+void init_signature1_bits();
+int get_signature1_bit(int n);
+void set_signature1_bit(int n, int v);
+
+void init_signature2_bits();
+int get_signature2_bit(int n);
+void set_signature2_bit(int n, int v);
+
+#endif
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Meerwald/sort.c	Sun Aug 12 13:14:34 2007 +0200
@@ -0,0 +1,184 @@
+#include "sort.h"
+
+#define SWAP_GRAY(A, B) {gray t = A; A = B; B = t;}
+
+/*
+ * quicksort-alike, from the EMX library (emx/src/lib/misc/qsort.c)
+ *   by Eberhard Mattes
+ *
+ *   sort() is not stable, the order of equal elements is not defined
+ */
+
+void _sort_grays(gray *l, gray *r) {
+  gray *i;
+  gray *j;
+  gray *x;
+
+redo:
+  i = l;
+  j = r;
+  x = l + sizeof(gray) * (((r-l) / sizeof(gray)) / 2);
+
+  do {
+    while (i != x && *i < *x)
+      i++;
+    while (j != x && *j > *x)
+      j--;
+    if (i < j) {
+      SWAP_GRAY(*i, *j);
+      if (x == i)
+        x = j;
+      else if (x == j)
+        x = i;
+    }
+    if (i <= j) {
+      i++;
+      if (j > l)
+        j--;
+    }
+  } while (i <= j);
+
+  if (j-l < r-i) {
+    if (l < j)
+      _sort_grays(l, j);
+    if (i < r) {
+      l = i;
+      goto redo;
+    }
+  }
+  else {
+    if (i < r)
+      _sort_grays(i, r);
+    if (l < j) {
+      r = j;
+      goto redo;
+    }
+  }
+}
+
+void sort_grays(gray a[], int n) {
+  if (n > 1)
+    _sort_grays(&a[0], &a[n-1]);
+}
+
+/*
+ * select_largest(), from the Numeric Recipes in C, Chapter 8, p. 344,
+ *   see http://www.nr.com
+ *
+ *   returns in largest[0..m-1] the largest m elements of array[0..n-1]
+ *   with largest[0] guaranteed to be the mth largest element; largest[] is
+ *   not sorted; the array[] is not altered; this function should be used
+ *   only when m << n
+ */
+
+void select_largest_grays(gray array[], int n, int m, gray largest[]) {
+  int i, j, k;
+
+  if (m <= 0 || m > n/2)
+    return;
+
+  for (i = 0; i < m; i++)
+    largest[i] = array[i];
+  sort_grays(largest, m);
+
+  for (i = m; i < n; i++) {
+    if (array[i] > largest[0]) {
+      largest[0] = array[i];
+      j = 0;
+      k = 1;
+      while (k < m) {
+        if (k < m-1 && largest[k] > largest[k+1])
+          k++;
+        if (largest[j] <= largest[k])
+          break;
+        SWAP_GRAY(largest[k], largest[j]);
+        j = k;
+        k = k << 1;
+      }
+    }
+  }
+}
+
+#define SWAP_DOUBLE(A, B) {double t = A; A = B; B = t;}
+
+void _sort_coeffs(double *l, double *r) {
+  double *i;
+  double *j;
+  double *x;
+
+redo:
+  i = l;
+  j = r;
+  x = l + sizeof(double) * (((r-l) / sizeof(double)) / 2);
+
+  do {
+    while (i != x && *i < *x)
+      i++;
+    while (j != x && *j > *x)
+      j--;
+    if (i < j) {
+      SWAP_DOUBLE(*i, *j);
+      if (x == i)
+        x = j;
+      else if (x == j)
+        x = i;
+    }
+    if (i <= j) {
+      i++;
+      if (j > l)
+        j--;
+    }
+  } while (i <= j);
+
+  if (j-l < r-i) {
+    if (l < j)
+      _sort_coeffs(l, j);
+    if (i < r) {
+      l = i;
+      goto redo;
+    }
+  }
+  else {
+    if (i < r)
+      _sort_coeffs(i, r);
+    if (l < j) {
+      r = j;
+      goto redo;
+    }
+  }
+}
+
+void sort_coeffs(double a[], int n) {
+  if (n > 1)
+    _sort_coeffs(&a[0], &a[n-1]);
+}
+
+void select_largest_coeffs(double array[], int n, int m, double largest[]) {
+  int i, j, k;
+
+  if (m <= 0 || m > n/2)
+    return;
+
+  for (i = 0; i < m; i++)
+    largest[i] = array[i];
+  sort_coeffs(largest, m);
+
+  for (i = m; i < n; i++) {
+    if (array[i] > largest[0]) {
+      largest[0] = array[i];
+      j = 0;
+      k = 1;
+      while (k < m) {
+        if (k < m-1 && largest[k] > largest[k+1])
+          k++;
+        if (largest[j] <= largest[k])
+          break;
+        SWAP_DOUBLE(largest[k], largest[j]);
+        j = k;
+        k = k << 1;
+      }
+    }
+  }
+}
+
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Meerwald/sort.h	Sun Aug 12 13:14:34 2007 +0200
@@ -0,0 +1,13 @@
+#ifndef SORT_H
+#define SORT_H
+
+#include "wm.h"
+#include "pgm.h"
+
+void sort_grays(gray a[], int n);
+void select_largest_grays(gray array[], int n, int m, gray largest[]);
+
+void sort_coeffs(double a[], int n);
+void select_largest_coeffs(double array[], int n, int m, double largest[]);
+
+#endif
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Meerwald/wang_common.c	Sun Aug 12 13:14:34 2007 +0200
@@ -0,0 +1,176 @@
+#include "dwt_util.h"
+#include "wang_common.h"
+
+void init_subbands(Image_tree tree) {
+  int levels = 0;
+  int i;
+  Image_tree p = tree;
+
+  // determine # of detail subbands
+  while (p->coarse != NULL) {
+    levels++;
+    p = p->coarse;
+  }
+
+  // there are 3 detail subbands per level
+  n_subbands = 3 * levels;
+
+  // allocate memory for subband data
+  subbands = malloc(n_subbands * sizeof(Subband_data));
+
+  p = tree;
+  i = 0;
+  while (p->coarse != NULL) {
+    subbands[i++] = alloc_subband(HORIZONTAL, p->horizontal);
+    subbands[i++] = alloc_subband(VERTICAL, p->vertical);
+    subbands[i++] = alloc_subband(DIAGONAL, p->diagonal);
+    
+    p = p->coarse;
+  }
+
+}
+
+Subband_data alloc_subband(int type, Image_tree tree) {
+  int i;
+  Subband_data p = malloc(sizeof(struct Subband_data_struct));
+
+  p->T = 0.0;
+  p->beta = 0.0;
+  p->Cmax = 0.0;
+  p->tree = tree;
+  p->level = tree->level;
+  p->width = tree->image->width;
+  p->height = tree->image->height;
+  p->size = p->height * p->width;
+  p->image = tree->image;
+  p->type = type;
+  
+  p->selected = malloc(p->height * sizeof(char *));
+  p->selected[0] = calloc(p->size, sizeof(char));
+  for (i = 1; i < p->height; i++)
+    p->selected[i] = &(p->selected[0][i * p->width]); 
+
+  return p;
+}
+
+void set_subband_beta(Subband_data subband, double beta) {
+  subband->beta = beta;
+}
+
+void set_subbands_beta(double beta) {
+  int i;
+
+  for (i = 0; i < n_subbands; i++)
+    set_subband_beta(subbands[i], beta);
+}
+
+void set_subbands_type_beta(int type, double beta) {
+  int i;
+
+  for (i = 0; i < n_subbands; i++)
+    if (subbands[i]->type == type)
+      set_subband_beta(subbands[i], beta);
+}
+
+void calc_subband_threshold(Subband_data subband) {
+  double max;
+  int i, j;
+
+  max = fabs(get_pixel(subband->image, 0, 0));
+  for (i = 0; i < subband->height; i++)
+    for (j = 0; j < subband->width; j++) {
+      Pixel p = fabs(get_pixel(subband->image, i, j));
+      if (p > max)
+        max = p;
+    }
+
+  subband->Cmax = max;
+  subband->T = max / 2.0;
+}
+
+void calc_subbands_threshold() {
+  int i;
+
+  for (i = 0; i < n_subbands; i++)
+    calc_subband_threshold(subbands[i]);
+}
+
+Subband_data select_subband() {
+  int max = 0;
+  int i;
+
+  for (i = 0; i < n_subbands; i++)
+    if ((subbands[i]->beta * subbands[i]->T) > (subbands[max]->beta * subbands[max]->T))
+      max = i;
+
+  return subbands[max];
+}
+
+int subband_coeff_isselected(Subband_data subband, int coeff) {
+  return subband->selected[0][coeff];
+}
+
+Pixel get_subband_coeff(Subband_data subband, int coeff) {
+  return subband->image->data[coeff];
+}
+
+void set_subband_coeff(Subband_data subband, int coeff, Pixel data) {
+  subband->image->data[coeff] = data;
+}
+
+int select_subband_coeff_from(Subband_data subband, int from) {
+  int i;
+
+  for (i = from; i < subband->size; i++)
+    if (!subband_coeff_isselected(subband, i) &&
+      get_subband_coeff(subband, i) > subband->T)
+      return i;
+
+  return -1;
+}
+
+int select_subband_coeff(Subband_data subband) {
+  select_subband_coeff_from(subband, 0);
+}
+
+void mark_subband_coeff(Subband_data subband, int coeff) {
+  subband->selected[0][coeff] = 1; 
+}
+
+void free_subband(Subband_data subband) {
+  free(subband->selected[0]);
+  free(subband->selected);
+  free(subband);
+}
+
+void free_subbands() {
+  int i;
+  
+  for (i = 0; i < n_subbands; i++) 
+    free_subband(subbands[i]);
+
+  free(subbands);
+}
+
+#define LARGE DBL_MAX
+
+Pixel figure_orig_coeff(double T, double alpha, double beta, Pixel coeff) {
+  int p, p_min = 0;
+  double dist_min = LARGE;
+  double sign = (coeff >= 0) ? 1.0 : -1.0;
+
+  for (p = 1; p < 1.0 / (2.0 * alpha); p++) {
+    double dist, delta;
+
+    delta = (1.0 + 2.0 * p * alpha) * T;
+    dist = fabs(delta - fabs(coeff));
+
+    if (dist < dist_min) {
+      dist_min = dist;
+      p_min = p;
+    }
+  }  
+
+  if (!p_min) p_min = 1;
+  return sign * (1.0 + 2.0 * p_min * alpha) * T;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Meerwald/wang_common.h	Sun Aug 12 13:14:34 2007 +0200
@@ -0,0 +1,46 @@
+#ifndef WANG_COMMON_H
+#define WANG_COMMON_H
+
+#include "dwt.h"
+
+typedef struct Subband_data_struct {
+  double T;
+  double Cmax;
+  double beta;
+  Image_tree tree;
+  int level;
+  int type;
+  int width;
+  int height;
+  int size;
+  Image image;
+  char** selected;
+} *Subband_data;
+
+Subband_data *subbands;
+int n_subbands;
+
+void init_subbands(Image_tree tree);
+Subband_data alloc_subband(int type, Image_tree tree);
+void free_subband(Subband_data subband);
+void free_subbands();
+
+void set_subband_beta(Subband_data subband, double beta);
+void set_subbands_beta(double beta);
+void set_subbands_type_beta(int type, double beta);
+
+void calc_subband_threshold(Subband_data subband);
+void calc_subbands_threshold();
+
+int subband_coeff_isselected(Subband_data subband, int coeff);
+Pixel get_subband_coeff(Subband_data subband, int coeff);
+void set_subband_coeff(Subband_data subband, int coeff, Pixel data);
+
+Subband_data select_subband();
+int select_subband_coeff_from(Subband_data subband, int from);
+int select_subband_coeff(Subband_data subband);
+void mark_subband_coeff(Subband_data subband, int coeff);
+
+Pixel figure_orig_coeff(double T, double alpha, double beta, Pixel coeff);
+
+#endif
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Meerwald/wavelet.c	Sun Aug 12 13:14:34 2007 +0200
@@ -0,0 +1,2999 @@
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <math.h>
+#include "wavelet.h"
+#include <ctype.h>
+
+static int read_char(FILE *fp);
+static int read_int(FILE *fp);
+
+IntImage new_intimage(int width, int height)
+{
+	IntImage image;
+
+	image = (IntImage) calloc(1,sizeof(struct IntImage_struct));
+	if (image==NULL) goto error;
+	image->data = (IntPixel*) calloc(width*height,sizeof(IntPixel));
+	if (image->data==NULL) goto error;
+	image->width = width;
+	image->height = height;
+	image->size = width*height;
+	image->bpp = 0;
+	image->min_val = (IntPixel) 0;
+	image->max_val = (IntPixel) 0;
+
+	return image;
+
+	error:
+	err_SimpleMessage(err_GetErrorMessage(Error_NotEnoughMemory));	
+	return NULL;
+}
+
+Image new_image(int width, int height)
+{
+	Image image;
+
+	image = (Image) calloc(1,sizeof(struct Image_struct));
+	if (image==NULL) goto error;
+	image->data = (Pixel*) calloc(width*height,sizeof(Pixel));
+	if (image->data==NULL) goto error;
+	image->width = width;
+	image->height = height;
+	image->size = width*height;
+	image->bpp = 0;
+	image->min_val = (Pixel) 0;
+	image->max_val = (Pixel) 0;
+
+	return image;
+
+	error:
+	err_SimpleMessage(err_GetErrorMessage(Error_NotEnoughMemory));	
+	return NULL;
+}
+
+
+void free_intimage(IntImage img)
+{
+	if (img) {
+          if (img->data) free(img->data);
+          free(img);
+	}
+}
+
+void free_image(Image img)
+{
+	if (img) {
+          if (img->data) free(img->data);
+          free(img);
+	}
+}
+
+/************************************************************************
+ *	Functionname:		load_intimage
+ * --------------------------------------------------------------------
+ *	PARAMETER:
+ *	file:		filename of image
+ *	max_val:	scaling of grey values to [0..max_val]
+ *
+ *	RETURN:
+ *	Image that shoud be loaded, if not possible return NULL
+ * --------------------------------------------------------------------
+ * 	DESCRIPTION:
+ *	This function loads an IntImage (PGM, ASCII or binary
+ *	encoded (P5 or P3 format) ) from a file.
+ ************************************************************************/
+
+IntImage load_intimage(char *file, int max_val)
+{	
+	IntImage	img;
+	FILE		*fp;
+	IntPixel	*data;
+	int		width, height, i, max, ch1, ch2;
+		
+	fp=fopen(file,"rb");
+	if (fp==NULL) goto error;
+	
+	ch1=getc(fp);
+	ch2=getc(fp);
+	if (ch1!='P' || (ch2!='5' && ch2!='2')) goto error1;
+	
+	width=read_int(fp);
+	height=read_int(fp);
+	if ((width==0) || (height==0) ) goto error1;
+	max=read_int(fp);
+
+	img=new_intimage(width,height);
+
+	img->bpp=8;
+			
+	data=img->data;
+	for (i=0; i<img->size; i++)
+	{ if (ch2=='5')
+	    *data=getc(fp);
+	  else
+	    *data=read_int(fp);
+	  data++;
+	}	
+	fclose(fp);
+	return img;
+
+        error1:
+          err_SimpleMessage(err_GetErrorMessage(Error_WrongFileFormat));
+          return NULL;
+        error:
+          err_SimpleMessage(err_GetErrorMessage(Error_CantOpenFile));
+          return NULL;
+}
+
+/************************************************************************
+ *	Functionname:		load_image
+ * --------------------------------------------------------------------
+ *	PARAMETER:
+ *	file:		filename of image
+ *	max_val:	scaling of grey values to [0..max_val]
+ *
+ *	RETURN:
+ *	Image that shoud be loaded, if not possible return NULL
+ * --------------------------------------------------------------------
+ * 	DESCRIPTION:
+ *	This function loads an IntImage with load_intimage
+ *	and then converts to Image.
+ ************************************************************************/
+extern Image load_image(char *file, int max_val)
+{
+	Image img;
+	IntImage intimg;
+
+	intimg = load_intimage(file, max_val);
+	if (!intimg) return NULL;
+	img = intimage_to_image(intimg);
+	if (!intimg) return NULL;
+
+	return img;
+}
+
+/************************************************************************/
+/*	Functionname:		save_image_P5                           */
+/* -------------------------------------------------------------------- */
+/*	Parameter:							*/
+/*            img: Image that shoud be saved                            */
+/*            file: filename of image                                   */
+/* -------------------------------------------------------------------- */
+/* 	Description: save an image as PGM (P5 binary decoded) file      */
+/*	                                              			*/
+/************************************************************************/
+
+extern int save_image_P5(char *file, Image img)
+{       FILE *fp;
+        Pixel *data;
+        long i;
+	int p;
+	
+        fp=fopen(file,"wb");
+        if (fp==NULL)
+          goto error;
+        fprintf(fp,"P5\n");
+        fprintf(fp,"%d %d\n%d ",img->width,img->height,255);
+        data=img->data;
+        for (i=0;i<img->size;i++) {
+	  p=floor(*data+0.5);
+	  if (p<0) p=0;
+	  if (p>255) p=255;
+/*          putc(*data,fp);	*/
+	  putc(p,fp);
+          data++;
+        }
+        fclose(fp);
+        return 1;
+
+        error:
+          err_SimpleMessage(err_GetErrorMessage(Error_CantOpenFile));
+          return 0;
+}
+
+void clear_image(Image img)
+{
+	int i;
+
+	PreCondition(img!=NULL,"image==NULL");
+
+	for (i=0;i<img->size;i++)
+		(img->data)[i]=(Pixel) 0;
+}
+
+extern void copy_into_image(Image img1,Image img2,int x,int y)
+/* copy img2 into img1 at position (x,y)*/
+{
+        int start,i,j,aim;
+        Pixel *temp;
+
+        temp=img2->data;
+        start=img1->width*y+x;
+        for (i=0;i<img2->height;i++) {
+          for (j=0;j<img2->width;j++) {
+	    aim=start+j+img1->width*i;
+            img1->data[aim]=*temp;
+            temp++;
+          }
+        }
+}
+
+extern void copy_into_intimage(IntImage img1,IntImage img2,int x,int y)
+{/* copy img2 into img1 at position (x,y)*/
+
+        int start,i,j,aim;
+        IntPixel *temp;
+
+        temp=img2->data;
+        start=img1->width*y+x;
+        for (i=0;i<img2->height;i++)
+        {
+          for (j=0;j<img2->width;j++)
+          {
+	    aim=start+j+img1->width*i;
+            img1->data[aim]=*temp;
+            temp++;
+          }
+        }
+}
+
+void copy_part_of_image_into_image(Image dest_img, int dest_x, int dest_y,
+				   Image src_img, int src_x, int src_y,
+				   int width, int height)
+{
+	Pixel *sp,*dp;
+	int y,siz;
+
+	sp=get_pixel_adr(src_img,src_x,src_y);
+	dp=get_pixel_adr(dest_img,dest_x,dest_y);
+
+	siz=width*sizeof(Pixel);
+
+	for (y=0;y<height;y++)
+	{
+		memcpy(dp,sp,siz);
+		sp+=src_img->width;
+		dp+=dest_img->width;
+	}
+}
+
+extern void copy_part_of_image(Image img1,Image img2,int x,int y)
+/* copy part of img2 begining at position (x,y) into img1 */
+{	int i,j,width,height,start,step;
+	Pixel *data;
+
+	width=img1->width;
+	height=img1->height;
+	start=img2->width*y+x;
+	data=img1->data;
+	for (i=0;i<height;i++) {
+	  step=i*img2->width;
+	  for (j=0;j<width;j++){
+	    *data=img2->data[start+j+step];
+	    data++;
+	  }
+	}
+}
+
+
+extern void scale_image(Image img,int maximum)
+/* scale image to [0..maximum]*/
+{ 	int i;
+	Pixel max,min,multi;
+
+	for (i=0;i<img->size;i++) {
+  	  if (img->data[i]<min) min=img->data[i];
+  	  else if (img->data[i]>max) max=img->data[i];
+	}
+
+	multi=(Pixel)maximum/(max-min);
+	for (i=0;i<img->size;i++) img->data[i]=multi*(img->data[i]-min);
+	img->min_val=0;
+	img->max_val=maximum;
+}
+
+int string_to_pixel(char *str, Pixel *p)
+{
+	float ppp;
+	if (sscanf(str,"%f",&ppp)==1)
+	{
+		*p=(Pixel) ppp;
+		return 1;
+	}
+	else
+	{
+		*p=0.0;
+		return 0;
+	}
+}
+
+Image intimage_to_image(IntImage i)
+{	Image img;
+	int j; 	
+
+	img=new_image(i->width,i->height);
+	if (img==NULL) goto error;
+	for (j=0;j<i->size;j++)
+	  img->data[j]=(Pixel)i->data[j];
+	img->bpp=i->bpp;
+        return img;
+
+       	error:
+          err_SimpleMessage(err_GetErrorMessage(Error_NotEnoughMemory));	
+	  return NULL;
+}
+IntImage image_to_intimage(Image i)
+{       IntImage img;
+        int j,multi=1,max,min;
+
+        img=(IntImage)calloc(1,sizeof(struct IntImage_struct));
+        if (img==NULL) goto error;
+        img->data=(IntPixel *)calloc(i->size,sizeof(IntPixel));
+        if (img->data==NULL) goto error;
+        img->width=i->width;
+        img->height=i->height;
+        img->size=i->size;
+        img->bpp=i->bpp;
+
+        max=i->max_val;
+        min=i->min_val;
+        if ((max-min)!=0)
+	  multi=255.0/(max-min);
+	
+        for (j=0;j<img->size;j++)
+          img->data[j]=(int)((i->data[j]-min)*multi+0.5);
+        return img;
+
+        error:
+          err_SimpleMessage(err_GetErrorMessage(Error_NotEnoughMemory));	
+	  return NULL;
+	  
+}
+
+static int read_char(FILE *fp)
+/*read a character from file, but skip any comments*/
+{       int ch;
+
+	ch=getc(fp);
+	if (ch=='#'){
+	   do {
+	     ch=getc(fp);
+	   } while (ch!='\n' && ch!=EOF);
+	}
+	return ch;
+}
+
+
+static int read_int(FILE *fp)
+/*read an ascii integer from file, and skip leading tabstops,new lines ...*/
+{  	int r,ch;
+
+	do {
+	  ch=read_char(fp);
+	} while (ch==' ' || ch=='\n' || ch=='\t');
+	
+	if (ch<'0' || ch>'9')
+	 goto error;
+	
+	r=ch-'0';
+	while ( (ch=read_char(fp)) >='0' && (ch <= '9') ) {
+	  r*=10;
+	  r+=ch-'0';
+	}
+	return r;
+	error:
+	  return 0;
+}
+
+Image_tree new_image_tree()
+{
+	Image_tree t;
+	t=(Image_tree) calloc(1,sizeof(struct Image_tree_struct));
+	t->entropy=0.0;
+	t->image=NULL;
+	t->coarse=t->horizontal=t->vertical=t->diagonal=t->doubletree=NULL;
+	t->level=0;
+	t->codec_data=NULL;
+	t->significance_map=NULL;
+	return t;
+}
+
+void free_image_tree(Image_tree t)
+{
+	if (t->coarse) free_image_tree(t->coarse);
+	if (t->horizontal) free_image_tree(t->horizontal);
+	if (t->vertical) free_image_tree(t->vertical);
+	if (t->diagonal) free_image_tree(t->diagonal);
+	if (t->doubletree) free_image_tree(t->doubletree);	
+	if (t->image) free_image(t->image);
+	if (t->significance_map) free_intimage(t->significance_map);
+	if (t->codec_data) free(t->codec_data);
+	t->image=NULL;
+	free(t);
+}
+
+/***********************************************************************
+ *      Functionname: get_image_infos                                   
+ * -------------------------------------------------------------------- 
+ *      Parameter:                                                      
+ *          Image image: input image                                    
+ *          Pixel *min,*max,*avg,*var: return minimum, maximum,         
+ *                average and variance of current image                 
+ * -------------------------------------------------------------------- 
+ *      Description:                                                    
+ *          get statistical information of Image                        
+ ************************************************************************/
+
+void get_image_infos(Image image, Image_info info)
+{
+	int x,y;
+	Pixel p,sp,sp2;
+
+	sp=sp2=(Pixel)0.0;
+
+	p=get_pixel(image,0,0);
+
+	info->min=info->max=p;
+
+	for (y=0;y<image->height;y++)
+		for (x=0;x<image->width;x++)
+		{
+			p=get_pixel(image,x,y);
+			info->max=MAX(info->max,p);
+			info->min=MIN(info->min,p);
+			sp+=p;
+			sp2+=p*p;
+		}
+	sp=sp/image->width/image->height;
+	sp2=sp2/image->width/image->height;
+
+	info->mean=sp;
+	info->var=sp2-sp*sp;
+	info->rms=sqrt(sp2);
+}
+
+/***********************************************************************
+ *      Functionname: get_difference_image
+ * -------------------------------------------------------------------- 
+ *      Parameter:
+ *          Image image1, image 2: input images
+ *
+ *      Return:
+ *          Image : difference of image1 and image 2,
+ *                  NULL if error occurs
+ ************************************************************************/
+
+Image get_difference_image(Image image1, Image image2)
+{
+	Image diff;
+	int i,max,w,h;
+	Pixel *d,*i1,*i2;
+
+	if ((!image1) || (!image2)) return NULL;
+
+	w=image1->width;
+	h=image1->height;
+
+	if (image2->width != w || image2->height != h) return NULL;
+
+	diff=new_image(w,h);
+	max=w*h;
+
+	d=diff->data;
+	i1=image1->data;
+	i2=image2->data;
+
+	for (i=0;i<max;i++)
+		d[i]=i2[i]-i1[i];
+
+	return diff;
+}
+
+
+/************************************************************************/
+/*      Functionname: get_intimage_infos                                */
+/* -------------------------------------------------------------------- */
+/*      Parameter:                                                      */
+/*          IntImage image: input image                                 */
+/*          IntPixel *min,*max, return minimum, maximum			*/
+/*	       Pixel *avg,*var: average and variance of current image   */
+/*                average and variance of current image                 */
+/* -------------------------------------------------------------------- */
+/*      Description:                                                    */
+/*          get statistical information of Image                        */
+/************************************************************************/
+
+void get_intimage_infos(IntImage image, IntPixel *min, IntPixel *max, Pixel *avg, Pixel *var)
+{
+	int x,y;
+	Pixel p,sp,sp2;
+
+	sp=sp2=(Pixel)0.0;
+
+	p= (Pixel) get_intpixel(image,0,0);
+	*min=*max=p;
+
+	for (y=0;y<image->height;y++)
+		for (x=0;x<image->width;x++)
+		{
+			p= (Pixel) get_intpixel(image,x,y);
+			*max=MAX(*max, (IntPixel) p);
+			*min=MIN(*min, (IntPixel) p);
+			sp+=p;
+			sp2+=p*p;
+		}
+	sp=sp/image->width/image->height;
+	sp2=sp2/image->width/image->height;
+
+	*avg=sp;
+	*var=sp2-sp*sp;
+}
+
+/************************************************************************/
+/*      Functionname: init_zigzag                                       */
+/* -------------------------------------------------------------------- */
+/*      Parameter:                                                      */
+/*          Zigzag_data_struct:                                         */
+/*              output: will be initialized, x/y hold coordinates of    */
+/*                      the first pixel                                 */
+/*          int width,height:                                           */
+/*              input: width/height of image:                           */
+/* -------------------------------------------------------------------- */
+/*      Description:                                                    */
+/*          initializes Zigzag_data structure for use with next_zigzag  */
+/************************************************************************/
+
+void init_zigzag(Zigzag_data zz, int width, int height)
+{
+	zz->x=0;
+	zz->y=0;
+	zz->dir=zigzag_up;
+	zz->w=width;
+	zz->h=height;
+}
+
+/************************************************************************/
+/*      Functionname: next_zigzag                                       */
+/* -------------------------------------------------------------------- */
+/*      Parameter:                                                      */
+/*          Zigzag_data_struct:                                         */
+/*              int x,y:                                                */
+/*                  input: current position of zigzag-scan              */
+/*                  output: next position of zigzag-scan                */
+/*              int w,h: width and height of image                      */
+/*              enum zigzag_direction *dir: i/o:                        */
+/*                  direction moving thru the image                     */
+/* -------------------------------------------------------------------- */
+/*      Description:                                                    */
+/*          calculates the next point (x',y') of the zigzag-scan        */
+/*          through the image with size (w,h)                           */
+/************************************************************************/
+
+
+void next_zigzag(Zigzag_data zz)
+{
+	switch(zz->dir)
+	{
+	case zigzag_up:
+		if (zz->y==0)
+		{
+			if (zz->x==zz->w-1)
+			{
+				(zz->y)++; zz->dir=zigzag_down;
+			}
+			else
+			{
+				(zz->x)++; zz->dir=zigzag_down;
+			}
+		}
+		else
+		{
+			if (zz->x==zz->w-1)
+			{
+				(zz->y)++; zz->dir=zigzag_down;
+			}
+			else
+			{
+				(zz->x)++; (zz->y)--;
+			}
+		}
+		break;
+
+	case zigzag_down:
+
+		if (zz->x==0)
+		{
+			if (zz->y==zz->h-1)
+			{
+				(zz->x)++; zz->dir=zigzag_up;
+			}
+			else
+			{
+				(zz->y)++; zz->dir=zigzag_up;
+			}
+		}
+		else
+		{
+			if (zz->y==zz->h-1)
+			{
+				(zz->x)++; zz->dir=zigzag_up;
+			}
+			else
+			{
+				(zz->x)--;(zz->y)++;
+			}
+		}
+		break;
+	}
+}
+
+Image get_absolute_image_scaled(Image img)
+{
+	Image out;
+
+	int x,y;
+
+	struct Image_info_struct info;
+	Pixel scale,p;
+
+	out=new_image(img->width,img->height);
+
+	get_image_infos(img, &info);
+
+	scale=255/MAX(fabs(info.min),fabs(info.max));
+
+	for(y=0;y<img->height;y++)
+	for(x=0;x<img->width;x++)
+	{
+		p=get_pixel(img,x,y)*scale;
+		set_pixel(out,x,y,p);
+	}
+	return out;
+}
+	
+#define FLOOR_HALF(x) ((x)&1 ? ((x)-1)/2 : (x)/2)
+#define CEILING_HALF(x) ((x)&1 ? ((x)+1)/2 : (x)/2)
+
+#define MOD(a,b) ( (a)<0 ? ((b)-((-(a))%(b))) : (a)%(b) )
+
+Filter new_filter(int size)
+{
+	Filter f;
+
+	Entering;
+	f=(Filter) calloc(1,sizeof(struct FilterStruct));
+	f->data=(Pixel *)calloc(size,sizeof(Pixel));
+	f->len=size;
+	f->hipass=0;
+
+	Leaving;
+	return f;
+}
+
+Pixel get_filter_center(Filter f)
+{
+	int i;
+	Pixel p, sum, norm;
+
+	if (f==NULL) return 0;
+
+	sum=norm=0;
+
+	for (i=0;i<f->len;i++)
+	{
+		p=f->data[i];
+		p=p*p;
+		norm += p;
+		sum += (i+f->start)*p;
+	}
+	p=sum/norm;
+
+	return p;
+}
+int filter_cutoff(Image in, int in_start, int in_len, int in_step,
+		Image out, int out_start, int out_len, int out_step,
+		Filter f)
+{
+	int i,i2,j;
+	Pixel *out_pix, *in_pix, *f_data;
+	int fstart,fend; /* Source interval */
+
+	Entering;
+
+	PreCondition(out_len == in_len/2,"out_len != in_len/2 !!!");
+
+/* convolution: out[i]=sum_{j=start}^{end} (in[2*i-j]*f[j])
+
+   boundaries:	image in [in_start ... in_start + in_len-1]
+		image out [out_start ... out_start + out_len-1]
+		filter f [0..f->len-1] = [f->start .. f->end]
+		cutoff at: 
+*/
+
+	for (i=0;i<out_len;i++)
+	{
+		i2=2*i;
+
+		fstart=i2-(in_len-1);
+		fstart=MAX(fstart,f->start);
+		fend=MIN(i2,f->end);
+
+#ifdef TRACE
+		sprintf(dbgstr,"i=%d fstart=%d fend=%d\n",i,fstart,fend);
+		Trace(dbgstr);
+#endif
+
+		out_pix=out->data+out_start+i*out_step;
+
+		in_pix=in->data+in_start+(i2-fstart)*in_step;
+
+		f_data=f->data-f->start+fstart;
+
+		for (j=fstart;j<=fend;j++,in_pix-=in_step,f_data++)
+		{
+			*out_pix += (*f_data) * (*in_pix);
+#ifdef TRACE
+
+			sprintf(dbgstr,"     j=%2d in: %4.2f filter: %4.2f [%4d] [%4d]  opt : %4.2f %4.2f\n",
+				j,
+				in->data[in_start+in_step*(i2-j)],
+				f->data[j-f->start],
+				in_start+in_step*(i2-j),
+				j-f->start,
+				*in_pix, *f_data);
+			Trace(dbgstr);
+#endif
+		}
+	}
+
+	Leaving;
+	return 1;
+}
+
+
+int filter_inv_cutoff(Image in, int in_start, int in_len, int in_step,
+		Image out, int out_start, int out_len, int out_step,
+		Filter f)
+{
+	int i,j;
+	Pixel *out_pix, *in_pix, *f_data;
+	int fstart,fend; /* Source interval */
+	Entering;
+	PreCondition(out_len == in_len*2,"out_len != in_len*2 !!!");
+
+/* convolution: out[i]=sum_{j=start}^{end} (f[2*j-i]*in[j])
+
+   boundaries:	image in [in_start ... in_start + in_len-1]
+		image out [out_start ... out_start + out_len-1]
+		filter f [0..f->len-1] = [f->start .. f->end]
+		cutoff at: 
+*/
+
+	for (i=0;i<out_len;i++)
+	{
+		fstart=CEILING_HALF(f->start+i);
+		fend=FLOOR_HALF(f->end+i);
+		fstart=MAX(fstart,0);
+		fend=MIN(fend,in_len-1);
+
+#ifdef TRACE
+		sprintf(dbgstr,"i=%d fstart=%d fend=%d\n",i,fstart,fend);
+		Trace(dbgstr);
+#endif
+		out_pix=out->data+out_start+i*out_step;
+
+		in_pix=in->data+in_start+fstart*in_step;
+
+		f_data=f->data-f->start+2*fstart-i;
+
+		for (j=fstart;j<=fend;j++,in_pix+=in_step,f_data+=2)
+		{
+			*out_pix += (*f_data) * (*in_pix);
+#ifdef TRACE
+			sprintf(dbgstr,"     j=%2d in: %4.2f filter: %4.2f [%4d] [%4d]  opt : %4.2f %4.2f\n",
+				j,
+				in->data[in_start+j*in_step],
+				f->data[2*j-i-f->start],
+				in_start+j*in_step,
+				2*j-i-f->start,
+				*in_pix, *f_data);
+			Trace(dbgstr);
+#endif
+		}
+	}
+
+	Leaving;
+	return 1;
+}
+
+int filter_periodical(Image in, int in_start, int in_len, int in_step,
+		Image out, int out_start, int out_len, int out_step,
+		Filter f)
+{
+	int i,i2,j;
+	Pixel *out_pix, *in_pix, *f_data;
+	int fstart,fend;
+	int istart;
+	int ipix_len;
+
+	Entering;
+	PreCondition(out_len == in_len/2,"out_len != in_len/2 !!!");
+
+/* convolution: out[i]=sum_{j=start}^{end} (in[2*i-j]*f[j])
+
+   boundaries:	image in [in_start ... in_start + in_len-1]
+		image out [out_start ... out_start + out_len-1]
+		filter f [0..f->len-1] = [f->start .. f->end]
+*/
+
+	ipix_len=in_len*in_step;
+
+	for (i=0;i<out_len;i++)
+	{
+		i2=2*i;
+
+		fstart=f->start;
+		fend=f->end;
+
+		istart=(i2-fstart);
+		istart=MOD(istart,in_len);
+
+#ifdef TRACE
+		sprintf(dbgstr,"i=%d istart=%d\n",i,istart);
+		Trace(dbgstr);
+#endif
+
+		out_pix=out->data+out_start+i*out_step;
+
+		in_pix=in->data+in_start+istart*in_step;
+
+		f_data=f->data;
+
+		for (j=fstart;j<=fend;j++,f_data++)
+		{
+			*out_pix += (*f_data) * (*in_pix);
+#ifdef TRACE
+
+			sprintf(dbgstr,"     j=%2d in: %4.2f filter: %4.2f [%4d] [%4d]  opt : %4.2f %4.2f\n",
+				j,
+				in->data[in_start+in_step*((i2-j+in_len)%in_len)],
+				f->data[j-f->start],
+				in_start+in_step*((i2-j+in_len)%in_len),
+				j-f->start,
+				*in_pix, *f_data);
+			Trace(dbgstr);
+#endif
+			in_pix-=in_step;
+			istart--;
+			if (istart<0)
+			{
+				istart+=in_len;
+				in_pix+=ipix_len;
+			}
+		}
+	}
+
+	Leaving;
+	return 1;
+}
+
+int filter_inv_periodical(Image in, int in_start, int in_len, int in_step,
+		Image out, int out_start, int out_len, int out_step,
+		Filter f)
+{
+	int i,j;
+	Pixel *out_pix, *in_pix, *f_data;
+	int fstart,fend; /* Source interval */
+	int istart;
+	int ipix_len;
+	Entering;
+	PreCondition(out_len == in_len*2,"out_len != in_len*2 !!!");
+
+/* convolution: out[i]=sum_{j=start}^{end} (f[2*j-i]*in[j])
+
+   boundaries:	image in [in_start ... in_start + in_len-1]
+		image out [out_start ... out_start + out_len-1]
+		filter f [0..f->len-1] = [f->start .. f->end]
+*/
+
+	ipix_len=in_len*in_step;
+
+	for (i=0;i<out_len;i++)
+	{
+		fstart=CEILING_HALF(f->start+i);
+		fend=FLOOR_HALF(f->end+i);
+
+		istart=MOD(fstart,in_len);
+#ifdef TRACE
+		sprintf(dbgstr,"i=%d fstart=%d fend=%d istart=%d\n",i,fstart,fend,istart);
+		Trace(dbgstr);
+#endif
+		out_pix=out->data+out_start+i*out_step;
+
+		in_pix=in->data+in_start+istart*in_step;
+
+		f_data=f->data-f->start+2*fstart-i;
+
+		for (j=fstart;j<=fend;j++,f_data+=2)
+		{
+			*out_pix += (*f_data) * (*in_pix); 
+#ifdef TRACE
+			sprintf(dbgstr,"     j=%2d in: %4.2f filter: %4.2f [%4d] [%4d]  opt : %4.2f %4.2f\n",
+				j,
+				in->data[in_start+(j % in_len)*in_step],
+				f->data[2*j-i-f->start],
+				in_start+(j%in_len)*in_step,
+				2*j-i-f->start,
+				*in_pix, *f_data);
+			Trace(dbgstr);
+#endif
+			in_pix+=in_step;
+			istart++;
+			if (istart>=in_len)
+			{
+				istart-=in_len;
+				in_pix-=ipix_len;
+			}
+		}
+	}
+
+	Leaving;
+	return 1;
+}
+
+int filter_mirror(Image in, int in_start, int in_len, int in_step,
+		Image out, int out_start, int out_len, int out_step,
+		Filter f)
+{
+	int i,i2,j;
+	Pixel *out_pix, *in_pix, *f_data;
+	int fstart,fend;
+	int in_pos;
+
+	int in_dir,in_div,in_mod;
+
+	Entering;
+	PreCondition(out_len == in_len/2,"out_len != in_len/2 !!!");
+
+/* convolution: out[i]=sum_{j=start}^{end} (in[2*i-j]*f[j])
+
+   boundaries:	image in [in_start ... in_start + in_len-1]
+		image out [out_start ... out_start + out_len-1]
+		filter f [0..f->len-1] = [f->start .. f->end]
+*/
+
+	in_pix=in->data+in_start;
+
+	for (i=0;i<out_len;i++)
+	{
+		i2=2*i;
+
+		fstart=f->start;
+		fend=f->end;
+
+		out_pix=out->data+out_start+i*out_step;
+
+		f_data=f->data;
+
+		for (j=fstart;j<=fend;j++)
+		{
+			in_pos=(i2-j);
+			if (in_pos<0)
+			{
+				in_pos=-in_pos;
+				if (in_pos>=in_len) continue;
+			}
+			if (in_pos>=in_len)
+			{
+				in_pos=2*in_len-2-in_pos;
+				if (in_pos<0) continue;
+			}
+			*out_pix += (f_data[j-fstart]) * (in_pix[in_pos*in_step]);
+		}
+	}
+
+	Leaving;
+	return 1;
+}
+
+int filter_inv_mirror(Image in, int in_start, int in_len, int in_step,
+		Image out, int out_start, int out_len, int out_step,
+		Filter f)
+{
+	int i,j;
+	Pixel *out_pix, *in_pix, *f_data;
+	int fstart,fend; /* Source interval */
+	int in_pos,in_dir,in_div,in_mod;
+
+	Entering;
+	PreCondition(out_len == in_len*2,"out_len != in_len*2 !!!");
+
+/* convolution: out[i]=sum_{j=start}^{end} (f[2*j-i]*in[j])
+
+   boundaries:	image in [in_start ... in_start + in_len-1]
+		image out [out_start ... out_start + out_len-1]
+		filter f [0..f->len-1] = [f->start .. f->end]
+*/
+
+	/*fprintf(stderr,"inv started\n");*/
+	for (i=0;i<out_len;i++)
+	{
+		fstart=CEILING_HALF(f->start+i);
+		fend=FLOOR_HALF(f->end+i);
+
+		out_pix=out->data+out_start+i*out_step;
+
+		in_pix=in->data+in_start;
+		
+/*
+		printf("in: %4d - %4d  flt: %4d - %4d   [%s]\n",fstart,fend,2*fstart-i,2*fend-i,
+		(2*fstart-i<f->start || 2*fend-i>f->end) ? "error":"ok");
+*/
+		/*fprintf(stderr,"inv[%d]\n",i);*/
+		for (j=fstart;j<=fend;j++)
+		{
+			in_pos=j;
+			if (in_pos<0)
+			{
+				if (f->hipass)
+					in_pos=-in_pos-1;
+				else
+					in_pos=-in_pos;
+				if (in_pos>=in_len) continue;
+			}
+			if (in_pos>=in_len)
+			{
+				if (f->hipass)
+					in_pos=2*in_len-2-in_pos;
+				else
+					in_pos=2*in_len-1-in_pos;
+				if (in_pos<0) continue;
+			}
+			/*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]);*/
+			*out_pix += f->data[2*j-i-f->start] * (in_pix[in_pos*in_step]);
+		}
+	}
+
+	Leaving;
+	return 1;
+}
+
+#define MAX_LINE 256
+
+#define skip_blank(str) { while(isspace(*(str))) (str)++; }
+
+static int get_next_line(FILE *f, char *c)
+{
+        char *str,string[200];
+        int len;
+        do
+        {
+                str=string;
+                if (!fgets(str,200,f))
+		{
+			Trace("get_next_line: eof\n");
+			goto error;
+		}
+                len=strlen(str);
+                while (len>=1 && isspace(str[len-1])) str[--len]=0;
+                while (isspace(*str)) str++;
+        }
+        while (strlen(str)==0 || *str=='#');
+        strcpy(c,str);
+	return 1;
+error:
+	return 0;
+}
+
+static int next_line_str(FILE *f, char *tag, char *out)
+{
+	char str[MAX_LINE],*t_str;
+
+	if (!get_next_line(f,str)) goto error;
+	t_str=strtok(str," ");
+	if (!t_str || strcmp(t_str,tag)) goto error;
+	t_str=strtok(NULL,"\n");
+	if (!t_str) goto error;
+	skip_blank(t_str);
+
+	strcpy(out,t_str);
+	return 1;
+error:
+	return 0;
+}
+
+static int next_line_str_alloc(FILE *f, char *tag, char **out)
+{
+	char str[MAX_LINE];
+	if (!next_line_str(f,tag,str)) goto error;
+
+	*out=malloc(strlen(str)+1);
+	strcpy(*out,str);
+
+	return 1;
+error:
+	return 0;
+}
+
+static int next_line_int(FILE *f, char *tag, int *out)
+{
+	char str[MAX_LINE];
+	if (next_line_str(f,tag,str) && sscanf(str,"%d",out)==1)
+		return 1;
+	else
+		return 0;
+}
+
+
+static Filter read_filter(FILE *f)
+{
+	char str[MAX_LINE];
+	Filter filter;
+	int i;
+
+	Entering;
+
+	filter=calloc(1,sizeof(struct FilterStruct));
+
+	if (!next_line_str(f,"Type",str)) goto error1;
+
+	if (!strcmp(str,"nosymm"))
+	{
+		filter->type=FTNoSymm;
+	}
+	else if (!strcmp(str,"symm"))
+	{
+		filter->type=FTSymm;
+	}
+	else if (!strcmp(str,"antisymm"))
+	{
+		filter->type=FTAntiSymm;
+	}
+	else 
+ 		goto error1;
+
+	if (!next_line_int(f,"Length",&(filter->len))) goto error1;
+	if (!next_line_int(f,"Start",&(filter->start))) goto error1;
+	if (!next_line_int(f,"End",&(filter->end))) goto error1;	
+
+	if ((filter->end-filter->start+1!=filter->len))
+	{
+		Trace("error: len != end-start+1\n");
+		goto error1;
+	}
+
+	filter->data=calloc(filter->len,sizeof(Pixel));
+
+	for (i=0;i<filter->len;i++)
+	{
+		if (!get_next_line(f,str)) goto error2;
+		if (!string_to_pixel(str,filter->data+i))
+		{
+			Trace("error: invalid filter-value\n");
+			goto error2;
+		}
+	}
+	if (!get_next_line(f,str)) goto error2;
+	if (*str!='}')
+	{
+		Trace("error: '}' not found\n");
+		goto error2;
+	}
+
+	Leaving;
+	return filter;
+
+error2:
+	free(filter->data);
+
+error1:
+	free(filter);
+
+	LeavingErr;
+	return NULL;
+
+}
+
+static FilterGH read_filter_gh(FILE *f)
+{
+	char str[MAX_LINE];
+	FilterGH fgh;
+	Filter filter;
+	int i,max;
+
+	Entering;
+
+	fgh=calloc(1,sizeof(struct FilterGHStruct));
+
+	if (!next_line_str_alloc(f,"Name",&(fgh->name)))
+	{
+		Trace("error: 'Name' tag not found\n");
+		goto error1;
+	}
+
+	if (!next_line_str(f,"Type",str))
+	{
+		Trace("error: 'Type' tag not found\n");
+		goto error1;
+	}
+
+	if (!strcmp(str,"orthogonal"))
+	{
+		fgh->type=FTOrtho;
+		max=2;
+	}
+	else if (!strcmp(str,"biorthogonal"))
+	{
+		fgh->type=FTBiOrtho;
+		max=4;
+	}
+	else if (!strcmp(str,"other"))
+	{
+		fgh->type=FTOther;
+		max=4;
+	}
+	else
+	{
+		Trace("error: expecting 'orthogonal', 'biorthogonal' or 'other' type-tag\n");
+		goto error1;
+	}
+
+	for (i=0;i<max;i++)
+	{
+		if (!get_next_line(f,str)) goto error2;
+		if (*str!='{')
+		{
+			Trace("error: '{' not found\n");
+			goto error2;
+		}
+		if (!(filter=read_filter(f)))
+		{
+			Trace("error: read_filter failed\n");
+			goto error2;
+		}
+		filter->hipass = !(i&1);
+		switch(i)
+		{
+		case 0: fgh->g=filter; break;
+		case 1: fgh->h=filter; break;
+		case 2: fgh->gi=filter; break;
+		case 3: fgh->hi=filter; break;
+		}
+	}
+	if (!get_next_line(f,str)) goto error2;
+	if (*str!='}')
+	{
+		Trace("error: '}' not found\n");
+		goto error2;
+	}
+
+	Leaving;
+	return fgh;
+
+error2:
+	if (fgh->g) free(fgh->g);
+	if (fgh->h) free(fgh->h);
+	if (fgh->gi) free(fgh->gi);
+	if (fgh->hi) free(fgh->hi);
+
+error1:
+	free(fgh);
+
+	LeavingErr;
+	return NULL;
+}
+
+
+AllFilters load_filters(char *name)
+{
+	FILE *f;
+	char str[MAX_LINE];
+	AllFilters a;
+	FilterGH fgh;
+
+	Entering;
+
+	PreCondition(name!=NULL,"name=NULL!");
+
+	f=fopen(name,"rt");
+	if (!f)
+	{
+		Trace("error: fopen failed\n");
+		goto error1;
+	}
+
+	a=calloc(1,sizeof(struct AllFilterStruct));
+	a->count=0;
+
+	while (get_next_line(f,str))
+	{
+		if (*str=='{')
+		{
+			fgh=read_filter_gh(f);
+			if (!fgh)
+			{
+				Trace("error: read_filter returned NULL\n");
+				goto error2;
+			}
+			if (a->count)
+				a->filter=realloc(a->filter,(a->count+1)*sizeof(FilterGH));
+			else
+				a->filter=malloc(sizeof(FilterGH));
+			(a->filter)[a->count]=fgh;
+			a->count++;
+		}
+		else
+		{
+			Trace("error: '{' not found\n");
+			goto error2;
+		}
+	}
+
+	fclose(f);
+
+	Leaving;
+	return a;
+
+error2:
+	fclose(f);
+error1:
+
+	LeavingErr;
+	return 0;
+}
+
+#define doubletree_min 32
+#define best_basis_min 8
+
+static int convolute_lines(Image output,Image input,Filter flt,enum FilterMethod method);
+static int convolute_rows(Image output,Image input,Filter flt,enum FilterMethod method);
+static int decomposition(Image t_img,Image coarse,Image horizontal,Image vertical,
+                               Image diagonal,Filter g,Filter h,enum FilterMethod method);
+static int compute_best(Image_tree tree,int level,int max_level,FilterGH *flt,
+                        enum FilterMethod method,enum Information_Cost cost,double epsilon);                           
+static double compute_entropy(Image img,enum Information_Cost cost,double epsilon);
+static compute_levels(Image_tree tree,double *entropies,enum Information_Cost cost,double epsilon);
+static free_levels(Image_tree tree,int best);
+
+static Pixel sumationq(Image img);
+static Pixel normq(Image_tree tree);
+static Pixel sumation_down(Image_tree tree, Pixel normq);
+static Pixel compute_non_additive(Image_tree tree,int size,enum Information_Cost cost,double
+epsilon,int down);
+
+/************************************************************************/
+/*	Functionname: wavelettransform					*/
+/* -------------------------------------------------------------------- */
+/*	Parameter: 							*/
+/*		original: Image that should be transformed  		*/
+/*	        level: transform down to level                 		*/
+/*		flt: transform with filters flt[0..level]		*/
+/*		method: method of filtering				*/
+/* -------------------------------------------------------------------- */
+/* 	Description: Carries out the wavelettransform 			*/
+/*	                           		           		*/
+/************************************************************************/
+extern Image_tree wavelettransform(Image original,int level,FilterGH *flt,enum FilterMethod method)
+{	int i,width,height,min,max_level,e;
+        Image coarsei,horizontali,verticali,diagonali,tempi;
+	Image_tree ret_tree,temp_tree;
+			
+	width=original->width;
+	height=original->height;
+	
+	tempi=new_image(width,height);
+	if(!tempi) goto error;
+	
+        copy_into_image(tempi,original,0,0);
+        	
+	ret_tree=new_image_tree();
+	if(!ret_tree) goto error;
+	
+	temp_tree=ret_tree;
+	ret_tree->level=0;
+
+	min=original->width;
+	if (original->height<min) min=original->height;
+	max_level=log(min)/log(2)-2;
+	if (max_level<level) level=max_level;
+
+	if (level<1)  /* do not transform */
+	{
+		ret_tree->image=tempi;
+		return ret_tree;
+	}
+
+	/* decomposition */
+	
+	for (i=0;i<level;i++)
+	{
+
+	        width=(width+1)/2;
+		height=(height+1)/2;
+	
+		coarsei=new_image(width,height);
+		horizontali=new_image(width,height);
+		verticali=new_image(width,height);
+		diagonali=new_image(width,height);
+		if(!coarsei||!horizontali||!verticali||!diagonali) goto error;		
+
+		e=decomposition(tempi,coarsei,horizontali,verticali,diagonali,
+	                       flt[i]->g,flt[i]->h,method);
+		if (!e) return NULL;	                       
+	                       
+		temp_tree->coarse=new_image_tree();
+		temp_tree->horizontal=new_image_tree();
+		temp_tree->vertical=new_image_tree();
+		temp_tree->diagonal=new_image_tree();
+		
+		temp_tree->coarse->level=i+1;
+		temp_tree->horizontal->level=i+1;		
+		temp_tree->vertical->level=i+1;		
+		temp_tree->diagonal->level=i+1;		
+		
+		temp_tree->horizontal->image=horizontali;
+		temp_tree->vertical->image=verticali;
+		temp_tree->diagonal->image=diagonali;
+	  	free_image(tempi);
+	    	  
+		if (i!=(level-1))
+		{
+	    		tempi=new_image(width,height);
+	    		copy_into_image(tempi,coarsei,0,0);
+	    		free_image(coarsei);
+	    		/*if i=level coarsei is inserted into the image tree
+	    		  so we should not free coarsei on level-1*/
+	 	}
+	 	
+		temp_tree=temp_tree->coarse;
+		
+  	}
+
+ 	temp_tree->image=coarsei;
+	return ret_tree;
+
+	error:
+        	err_SimpleMessage(err_GetErrorMessage(Error_NotEnoughMemory));	
+	  	return NULL;		
+}
+
+static Image_tree wavelettransform__wp(Image original, int current_level, int level, FilterGH *flt, enum FilterMethod method)
+{	
+  int i, width, height, min, max_level, e;
+  Image coarse_image,horizontal_image,vertical_image,diagonal_image,temp_image;
+  Image_tree return_tree, temp_tree;
+			
+  width = original->width;
+  height = original->height;
+	
+  temp_image = new_image(width, height);
+  if (!temp_image) goto error;
+	
+  copy_into_image(temp_image, original, 0, 0);
+        	
+  temp_tree = return_tree = new_image_tree();
+  if (!return_tree) goto error;
+
+  temp_tree->level = current_level;
+	
+  min = original->width;
+  if (original->height < min) min = original->height;
+  max_level = log(min) / log(2) - 2;
+  if (max_level < level) level = max_level;
+
+  if (current_level >= level) {
+    return_tree->image = temp_image;
+    return return_tree;
+  }
+
+  for (i = current_level; i < level; i++) {
+    width = (width + 1) / 2;
+    height = (height + 1) / 2;
+	
+    coarse_image = new_image(width, height);
+    horizontal_image = new_image(width, height);
+    vertical_image = new_image(width, height);
+    diagonal_image = new_image(width, height);
+
+    if (!coarse_image || !horizontal_image || 
+        !vertical_image || !diagonal_image) goto error;
+
+    e = decomposition(temp_image, coarse_image, horizontal_image, 
+                                  vertical_image, diagonal_image,
+	                          flt[i]->g, flt[i]->h, method);
+    if (!e) return NULL;	                       
+		                       
+    temp_tree->coarse = new_image_tree();
+    temp_tree->coarse->level = i+1;
+    temp_tree->horizontal = wavelettransform__wp(horizontal_image, i+1, level, flt, method);
+    temp_tree->vertical = wavelettransform__wp(vertical_image, i+1, level, flt, method);
+    temp_tree->diagonal = wavelettransform__wp(diagonal_image, i+1, level, flt, method);
+		
+    free_image(horizontal_image);
+    free_image(vertical_image);
+    free_image(diagonal_image);
+    free_image(temp_image);
+	    	  
+    if (i != (level - 1)) {
+      temp_image = new_image(width, height);
+      copy_into_image(temp_image, coarse_image, 0, 0);
+      free_image(coarse_image);
+    }
+	 	
+    temp_tree = temp_tree->coarse;
+  }
+
+ temp_tree->image = coarse_image;
+ return return_tree;
+
+  error:
+    err_SimpleMessage(err_GetErrorMessage(Error_NotEnoughMemory));	
+    return NULL;		
+}
+
+extern Image_tree wavelettransform_wp(Image original, int level, FilterGH *flt, enum FilterMethod method) {
+  wavelettransform__wp(original, 0, level, flt, method);
+}
+
+
+/************************************************************************/
+/*	Functionname: best_basis					*/
+/* -------------------------------------------------------------------- */
+/*	Parameter:							*/
+/*	    	original: Image to be transformed			*/
+/*		level: best basis selection down to this level		*/
+/*		flt: transform with filters flt[0..level]		*/
+/*		method: transform with filter method			*/
+/*		cost: carry best basis selection out with this costfunc */
+/*		epsilon: limit for threshold method			*/
+/* -------------------------------------------------------------------- */
+/* 	Description: carries best basis and near best basis selection	*/
+/*			out						*/
+/************************************************************************/
+extern Image_tree best_basis(Image original,int level,FilterGH *flt,
+				enum FilterMethod method,enum Information_Cost cost,double epsilon)
+
+{       Image_tree tree;
+	Image img;
+	int min,max_level,e;
+
+	tree=new_image_tree();
+	if(!tree) goto error;
+	
+	img=new_image(original->width,original->height);
+	if(!img) goto error;
+	
+        copy_into_image(img,original,0,0);
+        
+        tree->image=img;	
+
+	min=original->width;
+	if (original->height<min) min=original->height;
+	max_level=log10((float) min/best_basis_min)/log10(2);
+	if (max_level>level) max_level=level;
+	
+	e=compute_best(tree,0,max_level,flt,method,cost,epsilon);
+
+	if (!tree->image) free(img);
+
+        return tree;
+
+	error:
+        	err_SimpleMessage(err_GetErrorMessage(Error_NotEnoughMemory));	
+	  	return NULL;	        
+
+}
+/************************************************************************/
+/*	Functionname: best_level_selection				*/
+/* -------------------------------------------------------------------- */
+/*	Parameter: 							*/
+/*		original: Image that should be transformed  		*/
+/*	        maxlevel: transform down to level                 	*/
+/*		flt: transform with filters flt[0..level]		*/
+/*		method: transform with filter method			*/
+/*		cost: carry best basis selection out with this costfunc */
+/*		epsilon: limit for threshold method			*/
+/* -------------------------------------------------------------------- */
+/* 	Description: Carries out the best level selection		*/
+/*	                           		           		*/
+/************************************************************************/
+extern Image_tree best_level(Image original,int maxlevel,int *bestlevel,FilterGH *flt,enum FilterMethod method,
+				enum Information_Cost cost,double epsilon)
+{	Image_tree tree;
+	Image img;
+	double *entropies,min;
+	int best=0,i,e;
+
+	img=new_image(original->width,original->height);
+       	copy_into_image(img,original,0,0);
+	
+	tree=new_image_tree();
+	tree->image=img;
+	
+	entropies=(double *)calloc(maxlevel+1,sizeof(double));
+	if(!entropies) goto error;
+
+	/* decompose down to maxlevel */
+	e=decompose_all(tree,maxlevel,flt,method,cost,epsilon);
+	if (!e) return NULL;
+
+	/* compute costs of each level and store it in entropies array*/
+	compute_levels(tree,entropies,cost,epsilon);
+
+	min=entropies[0];
+	for (i=1;i<=maxlevel;i++)
+	{
+		if (entropies[i]<min)
+		{
+			min=entropies[i];
+			best=i;
+		}
+	}
+
+	/* free all other levels */
+	free_levels(tree,best);
+
+	*bestlevel=best;
+	
+	return tree;
+
+	error:
+        	err_SimpleMessage(err_GetErrorMessage(Error_NotEnoughMemory));	
+	  	return NULL;	
+}
+
+/************************************************************************/
+/*	Functionname: compute_best					*/
+/* -------------------------------------------------------------------- */
+/*	Parameter: 							*/
+/*		img: Image that should be transformed	 		*/
+/*	        level: transform level	                		*/
+/*		max_level: transform to maximum level			*/
+/*		flt: transform with filters flt[0..level]		*/
+/*		method: transform with filter method			*/
+/*		cost: carry best basis selection out with this costfunc */
+/*		epsilon: limit for threshold method			*/
+/* -------------------------------------------------------------------- */
+/* 	Description: Carries out the best basis selection (recursivly)  */
+/*	             (is needed by the waveletpacket procedure)		*/
+/************************************************************************/
+static int compute_best(Image_tree tree,int level,int max_level,FilterGH *flt,
+                        enum FilterMethod method,enum Information_Cost cost,double epsilon)
+
+{ 	Image coarse,horizontal,vertical,diagonal;
+        int e,width,height;
+	double sum;
+	
+	tree->level=level;
+		
+	/* non additive cost function*/
+	if (cost>=shanon) 
+	{
+		tree->entropy=compute_non_additive(tree,tree->image->size,cost,epsilon,0);
+	}
+	/*additive cost function*/
+	else 	tree->entropy=compute_entropy(tree->image,cost,epsilon);
+	
+	if (level<max_level) {
+        	width=(tree->image->width+1)/2;
+        	height=(tree->image->height+1)/2;
+          
+	  	tree->coarse=new_image_tree();
+	  	tree->horizontal=new_image_tree();
+		tree->vertical=new_image_tree();
+	  	tree->diagonal=new_image_tree();
+
+          	coarse=new_image(width,height);	
+          	horizontal=new_image(width,height);	
+          	vertical=new_image(width,height);
+          	diagonal=new_image(width,height);
+		if(!coarse||!vertical||!horizontal||!diagonal) goto error;          	
+
+	        e=decomposition(tree->image,coarse,horizontal,vertical,diagonal,flt[0]->g,flt[0]->h,method);
+	        if (!e) return 0;
+
+	        tree->coarse->image=coarse;
+	        tree->horizontal->image=horizontal;
+	        tree->vertical->image=vertical;
+	        tree->diagonal->image=diagonal;
+	        
+          	e=compute_best(tree->coarse,level+1,max_level,flt+1,method,cost,epsilon);
+          	e=compute_best(tree->horizontal,level+1,max_level,flt+1,method,cost,epsilon);
+          	e=compute_best(tree->vertical,level+1,max_level,flt+1,method,cost,epsilon);
+          	e=compute_best(tree->diagonal,level+1,max_level,flt+1,method,cost,epsilon);
+          	if (!e) return 0;
+	  
+		/*going back in recursion*/
+
+		if (cost>=shanon) {
+			 sum=compute_non_additive(tree,tree->image->size,cost,epsilon,1);
+		}
+		else sum=(tree->coarse->entropy)+(tree->horizontal->entropy)
+			+(tree->vertical->entropy)+(tree->diagonal->entropy);
+			
+	  	if (tree->entropy>sum)
+	  	{
+	  		tree->entropy=sum;	     		
+	      		free_image(tree->image);	/* take down tree */
+	      		tree->image=NULL;
+	      		
+	  	}
+	  	else
+	  	{   				/* delete the tree downwards */
+         		free_image_tree(tree->coarse);
+              		free_image_tree(tree->horizontal);
+              		free_image_tree(tree->vertical);
+              		free_image_tree(tree->diagonal);                			
+              			
+              		tree->coarse=tree->vertical=tree->horizontal=tree->diagonal=NULL;	    		
+	  	}
+	}
+
+	return 1;
+
+	error:
+        	err_SimpleMessage(err_GetErrorMessage(Error_NotEnoughMemory));
+        	return 0;
+	  		
+}
+
+/************************************************************************/
+/*	Functionname:		decompose_all                         */
+/* -------------------------------------------------------------------- */
+/*	Parameter:							*/
+/*            	tree: Image tree to be decomposed			*/
+/*           	maxlevel: decompose down to level	                */
+/*		flt: transform with filters flt[0..maxlevel]		*/
+/*		method: transform with filter method			*/
+/*		cost: cost function for entropy computing		*/
+/*		epsilon: limit for threshold method			*/
+/* -------------------------------------------------------------------- */
+/* 	Description: whole decompositing down to maxlevel          	*/
+/*		The original image must be in tree->image		*/
+/************************************************************************/
+extern int decompose_all(Image_tree tree,int maxlevel,FilterGH *flt,enum FilterMethod method,
+				enum Information_Cost cost,double epsilon)
+{	
+	Image original,coarse,horizontal,vertical,diagonal;
+	int e,width,height,level;
+	
+	if (tree->level<maxlevel)
+	{
+		tree->coarse=new_image_tree();
+		tree->horizontal=new_image_tree();
+		tree->vertical=new_image_tree();
+		tree->diagonal=new_image_tree();
+
+		original=tree->image;
+		width=(original->width+1)/2;
+		height=(original->height+1)/2;
+		level=tree->level;
+		
+		coarse=new_image(width,height);
+		horizontal=new_image(width,height);
+		vertical=new_image(width,height);
+		diagonal=new_image(width,height);
+		if(!coarse||!vertical||!horizontal||!diagonal) goto error;          	
+		
+		
+		e=decomposition(tree->image,coarse,horizontal,vertical,diagonal,flt[0]->g,flt[0]->h,method);
+		if (!e) return 0;
+
+		tree->coarse->image=coarse;
+		tree->horizontal->image=horizontal;
+		tree->vertical->image=vertical;
+		tree->diagonal->image=diagonal;
+
+		tree->coarse->entropy=compute_entropy(coarse,cost,epsilon);
+		tree->horizontal->entropy=compute_entropy(horizontal,cost,epsilon);
+		tree->vertical->entropy=compute_entropy(vertical,cost,epsilon);
+		tree->diagonal->entropy=compute_entropy(diagonal,cost,epsilon);
+		
+		tree->coarse->level=tree->horizontal->level=
+			tree->vertical->level=tree->diagonal->level=level+1;
+
+		e=decompose_all(tree->coarse,maxlevel,flt+1,method,cost,epsilon);
+		e=decompose_all(tree->horizontal,maxlevel,flt+1,method,cost,epsilon);
+		e=decompose_all(tree->vertical,maxlevel,flt+1,method,cost,epsilon);
+		e=decompose_all(tree->diagonal,maxlevel,flt+1,method,cost,epsilon);
+		if (!e) return 0;
+		
+	}
+
+	return 1;
+	
+	error:
+        	err_SimpleMessage(err_GetErrorMessage(Error_NotEnoughMemory));	
+		return 0;	  		
+}
+
+/************************************************************************/
+/*	Functionname:		compute_levels                          */
+/* -------------------------------------------------------------------- */
+/*	Parameter:							*/
+/*            	tree: Image tree where the entropy should be computed	*/
+/*           	entropies : array for entropy          	                */
+/*		cost: carry best basis selection out with this costfunc */
+/*		epsilon: limit for threshold method			*/
+/* -------------------------------------------------------------------- */
+/* 	Description: Compute the entropies of all decomposition	levels	*/
+/************************************************************************/
+static compute_levels(Image_tree tree,double *entropies,enum Information_Cost cost,double epsilon)
+{	
+	if (tree->image){
+		entropies[tree->level]+=compute_entropy(tree->image,cost,epsilon);
+	}
+	if (tree->coarse) compute_levels(tree->coarse,entropies,cost,epsilon);
+	if (tree->horizontal) compute_levels(tree->horizontal,entropies,cost,epsilon);
+	if (tree->vertical) compute_levels(tree->vertical,entropies,cost,epsilon);
+	if (tree->diagonal) compute_levels(tree->diagonal,entropies,cost,epsilon);
+
+}
+
+/************************************************************************/
+/*	Functionname:		free_levels	                        */
+/* -------------------------------------------------------------------- */
+/*	Parameter:							*/
+/*            	tree: Image tree which should be cleaned		*/
+/*           	best: best level	         	                */
+/* -------------------------------------------------------------------- */
+/* 	Description: clean the image tree except the best level      	*/
+/************************************************************************/
+static free_levels(Image_tree tree,int best)
+{
+	if (tree->level<best)
+	{
+		free_image(tree->image);
+		tree->image=NULL;
+		free_levels(tree->coarse,best);
+		free_levels(tree->horizontal,best);
+		free_levels(tree->vertical,best);
+		free_levels(tree->diagonal,best);
+	}
+	else
+	{
+		if (tree->coarse)
+		{
+			free_image_tree(tree->coarse);
+			free_image_tree(tree->horizontal);
+			free_image_tree(tree->vertical);
+			free_image_tree(tree->diagonal);
+			tree->coarse=tree->horizontal=tree->vertical=tree->diagonal=NULL;
+		}
+	}
+}
+		
+/************************************************************************/
+/*	Functionname:		decompose_to_level                       */
+/* -------------------------------------------------------------------- */
+/*	Parameter:							*/
+/*            	original: original image		 		*/
+/*           	level: decompose to level	 	                */
+/*		flt: decompos with filters[0..level]                   	*/
+/*		method: transform with filter method			*/
+/* -------------------------------------------------------------------- */
+/* 	Description: Decomposes an image to an certain level and stores	*/
+/*	     only this level in the returned quadtree      		*/
+/************************************************************************/
+extern Image_tree decompose_to_level(Image original,int level,FilterGH *flt,enum FilterMethod method)
+{	Image_tree tree;
+	int e;
+	
+	tree=new_image_tree();
+	tree->image=original;
+	
+	e=decompose_all(tree,level,flt,method,entropy,1);
+	if (!e) return NULL;
+	
+	free_levels(tree,level);
+	
+	return tree;
+
+}
+	
+/************************************************************************/
+/*	Functionname:		decomposition                           */
+/* -------------------------------------------------------------------- */
+/*	Parameter:							*/
+/*            	t_img: Image which should be decomposed  		*/
+/*           	coarse,horizontal,vertical,diagonal: 	                */
+/*			decomposed images                             	*/
+/*		method: transform with filter method			*/
+/*            	g,h: the transformation is carried out with these filters*/
+/* -------------------------------------------------------------------- */
+/* 	Description: This carries out one wavelettransformation		*/
+/*	     using waveletfilters.            				*/
+/************************************************************************/
+
+static int decomposition(Image t_img,Image coarse,Image horizontal,Image vertical,
+                               Image diagonal,Filter g,Filter h,enum FilterMethod method)
+{ 	Image temp1;
+	
+ 	/*coarse*/	
+	temp1=new_image(coarse->width,t_img->height);
+	if(!temp1) goto error;          	
+        convolute_lines(temp1,t_img,h,method);
+	convolute_rows(coarse,temp1,h,method);
+
+	/*horizontal*/
+	convolute_rows(horizontal,temp1,g,method);	
+	free_image(temp1);
+	
+        /*vertical*/
+	temp1=new_image(vertical->width,t_img->height);
+	if(!temp1) goto error;          	
+        convolute_lines(temp1,t_img,g,method);
+	convolute_rows(vertical,temp1,h,method);
+
+        /*diagonal*/
+	convolute_rows(diagonal,temp1,g,method);
+	free_image(temp1);
+
+	return 1;
+
+	error:
+        	err_SimpleMessage(err_GetErrorMessage(Error_NotEnoughMemory));	
+	  	return 0;		
+
+}
+
+/************************************************************************/
+/*	Functionname: inv_decomposition					*/
+/* -------------------------------------------------------------------- */
+/*	Parameter: 							*/
+/*		sum: reconstructed image		  		*/
+/*		coarse,horizontal,vertical,diagonal: images to carry out*/
+/*			the inverse transformation			*/
+/*		flt_gh: transform with filters g and h			*/
+/* 		method: transform with filter method			*/
+/* -------------------------------------------------------------------- */
+/* 	Description: Carries out the wavelettransform 			*/
+/*	                           		           		*/
+/************************************************************************/
+static int inv_decomposition(Image sum,Image coarse,Image horizontal,Image vertical,
+                               Image diagonal,FilterGH flt_gh,enum FilterMethod method)
+{       Image temp1;
+	Filter g,h;
+
+	if (flt_gh->type==FTOrtho) {
+	  g=flt_gh->g;
+	  h=flt_gh->h;
+	}
+	else {
+	  g=flt_gh->gi;
+	  h=flt_gh->hi;
+	}
+
+	/*coarse*/
+	temp1=new_image(coarse->width,sum->height);
+	if(!temp1) goto error;          	
+	convolute_rows(temp1,coarse,h,method);
+
+        /*horizontal*/
+	convolute_rows(temp1,horizontal,g,method);
+        convolute_lines(sum,temp1,h,method);
+        free_image(temp1);
+        
+        /*vertical*/
+        temp1=new_image(vertical->width,sum->height);
+	if(!temp1) goto error;          	
+        convolute_rows(temp1,vertical,h,method);
+
+        /*diagonal*/
+        convolute_rows(temp1,diagonal,g,method);
+        convolute_lines(sum,temp1,g,method);
+	
+        free_image(temp1);
+        
+	return 1;
+
+	error:
+        	err_SimpleMessage(err_GetErrorMessage(Error_NotEnoughMemory));	
+	  	return 0;	
+}
+
+/************************************************************************/
+/*	Functionname: build_image					*/
+/* -------------------------------------------------------------------- */
+/*	Parameter: 							*/
+/*		quadtree: quadtree with decomposition information	*/
+/*	        width,height: image width and height           		*/
+/*		RETURN: returns the build up image			*/
+/* -------------------------------------------------------------------- */
+/* 	Description: builds up an image out of an Image_tree		*/
+/*	                           		           		*/
+/************************************************************************/
+extern Image build_image(Image_tree quadtree,int width,int height)
+{ 	Image ret_img,coarse,horizontal,vertical,diagonal;
+
+	
+	ret_img=new_image(width,height);
+	if(!ret_img) goto error;          	
+	
+	width=(width+1)/2;
+	height=(height+1)/2;
+
+	if (!(quadtree->image)) {
+        	coarse=build_image(quadtree->coarse,width,height);
+          	horizontal=build_image(quadtree->horizontal,width,height);
+          	vertical=build_image(quadtree->vertical,width,height);
+          	diagonal=build_image(quadtree->diagonal,width,height);
+          	if (!coarse||!horizontal||!vertical||!diagonal) return NULL;
+     
+          	copy_into_image(ret_img,coarse,0,0);
+	  	copy_into_image(ret_img,horizontal,width,0);
+	  	copy_into_image(ret_img,vertical,0,height);
+	  	copy_into_image(ret_img,diagonal,width,height);
+	  
+	  	if (!quadtree->coarse->image) free_image(coarse);
+	  	if (!quadtree->horizontal->image) free_image(horizontal);
+	  	if (!quadtree->vertical->image) free_image(vertical);
+	  	if (!quadtree->diagonal->image) free_image(diagonal);
+	  
+          	return ret_img;
+	}
+	else return quadtree->image;
+
+	error:
+        	err_SimpleMessage(err_GetErrorMessage(Error_NotEnoughMemory));	
+	  	return NULL;	
+}
+
+/************************************************************************/
+/*	Functionname: inv_transform					*/
+/* -------------------------------------------------------------------- */
+/*	Parameter: 							*/
+/*		tree: tree with decomposition information		*/
+/*		flt_gh: transform with filters g and h			*/
+/* 		method: transform with filter method			*/
+/* -------------------------------------------------------------------- */
+/* 	Description: Inverts the wavelettransform,best_basis,best_level */
+/*	                           		           		*/
+/************************************************************************/
+extern Image inv_transform(Image_tree tree,FilterGH *flt,
+                                enum FilterMethod method)
+
+{	int er,width,height;
+	Image ret_img,coarse,vertical,horizontal,diagonal;
+
+	if (!tree->image) {
+		
+		coarse=inv_transform(tree->coarse,flt,method);
+        	horizontal=inv_transform(tree->horizontal,flt,method);
+	        vertical=inv_transform(tree->vertical,flt,method);
+	        diagonal=inv_transform(tree->diagonal,flt,method);
+         	if (!coarse||!horizontal||!vertical||!diagonal) return NULL;
+ 
+		width=coarse->width+horizontal->width;
+		height=coarse->height+vertical->height;
+		
+		ret_img=new_image(width,height);
+		if(!ret_img) goto error;          	
+
+
+	        if (tree->flag==0)		/*if flag is set it is a doubletree tiling*/
+	        {
+//			er=inv_decomposition(ret_img,coarse,horizontal,vertical,diagonal,flt[1],method);
+			er=inv_decomposition(ret_img,coarse,horizontal,vertical,diagonal,flt[tree->level],method);
+			if (!er) return NULL;
+	        }
+	  	else
+	  	{
+	  		copy_into_image(ret_img,coarse,0,0);
+	  		copy_into_image(ret_img,horizontal,coarse->width,0);
+	  		copy_into_image(ret_img,vertical,0,coarse->height);
+	  		copy_into_image(ret_img,diagonal,coarse->width,coarse->height);  		
+	  	}
+
+		if (!tree->coarse->image) free_image(coarse);
+		if (!tree->horizontal->image) free_image(horizontal);
+		if (!tree->vertical->image) free_image(vertical);
+		if (!tree->diagonal->image) free_image(diagonal);
+	  	
+		return ret_img;
+	}
+
+	else return tree->image;
+
+	error:
+        	err_SimpleMessage(err_GetErrorMessage(Error_NotEnoughMemory));	
+	  	return NULL;		
+}
+
+/************************************************************************/
+/*	Functionname: find_deepest_level				*/
+/* -------------------------------------------------------------------- */
+/*	Parameter: 							*/
+/* -------------------------------------------------------------------- */
+/* 	Description: Finds the deepest possible level where width and 	*/
+/*			height can divided by two exactly.		*/
+/************************************************************************/
+extern int find_deepest_level(int width,int height)
+{
+	int level=0,w=width,h=height;
+	
+	while ( !((w%2)||(h%2)))
+	{
+		w=w/2;
+		h=h/2;
+		level++;
+	}
+	
+	return level-1;
+
+}
+
+/************************************************************************/
+/*	Functionname: convolute_lines					*/
+/* -------------------------------------------------------------------- */
+/*	Parameter: 							*/
+/*		output: output image of wavelettransformation		*/
+/*	        input: input image for decomposition            	*/
+/*		flt: transform with filter flt				*/
+/*		method: transform with filter method			*/
+/* -------------------------------------------------------------------- */
+/* 	Description: Carries out the wavelettransform for all lines of  */
+/*	             the input image					*/
+/************************************************************************/
+static int convolute_lines(Image output,Image input,Filter flt,enum FilterMethod method)
+/*Convolute the lines with filter*/
+{       int i;
+
+        for (i=0;i<input->height;i++) {
+	  switch(method) {
+	  case cutoff:
+            filter_cutoff(input,input->width*i,input->width,1,
+			output,output->width*i,output->width,1,flt);
+	    break;
+	  case inv_cutoff:
+            filter_inv_cutoff(input,input->width*i,input->width,1,
+			output,output->width*i,output->width,1,flt);
+	    break;
+	  case periodical:
+            filter_periodical(input,input->width*i,input->width,1,
+			output,output->width*i,output->width,1,flt);
+	    break;
+	  case inv_periodical:
+            filter_inv_periodical(input,input->width*i,input->width,1,
+			output,output->width*i,output->width,1,flt);
+	    break;
+	  case mirror:
+            filter_mirror(input,input->width*i,input->width,1,
+			output,output->width*i,output->width,1,flt);
+	    break;
+	  case inv_mirror:
+            filter_inv_mirror(input,input->width*i,input->width,1,
+			output,output->width*i,output->width,1,flt);
+	    break;
+
+	    
+	  }
+        }
+        
+        return 1;
+}
+
+/************************************************************************/
+/*	Functionname: convolute_rows					*/
+/* -------------------------------------------------------------------- */
+/*	Parameter: 							*/
+/*		output: output image of wavelettransformation		*/
+/*	        input: input image for decomposition            	*/
+/*		flt: transform with filter flt				*/
+/*		method: transform with filter method			*/
+/* -------------------------------------------------------------------- */
+/* 	Description: Carries out the wavelettransform for all rows of   */
+/*	             the input image					*/
+/************************************************************************/
+static int convolute_rows(Image output,Image input,Filter flt,enum FilterMethod method)
+/*Convolute the rows with filter*/
+{       int i;
+
+        for (i=0;i<input->width;i++)
+        {
+         	switch (method)
+         	{
+		case cutoff:
+	    		filter_cutoff(input,i,input->height,input->width,
+	           		output,i,output->height,output->width,flt);
+	    		break;
+	  	case inv_cutoff:
+	    		filter_inv_cutoff(input,i,input->height,input->width,
+	           		output,i,output->height,output->width,flt);
+	    		break;
+	  	case periodical:
+	    		filter_periodical(input,i,input->height,input->width,
+	           		output,i,output->height,output->width,flt);
+	    		break;
+		case inv_periodical:
+			filter_inv_periodical(input,i,input->height,input->width,
+	           		output,i,output->height,output->width,flt);
+	    		break;
+	  	case mirror:
+	    		filter_mirror(input,i,input->height,input->width,
+	           		output,i,output->height,output->width,flt);
+	    		break;
+		case inv_mirror:
+			filter_inv_mirror(input,i,input->height,input->width,
+	           		output,i,output->height,output->width,flt);
+	    		break;
+	    		
+	  	}
+        }
+        return 1;
+}
+
+/************************************************************************/
+/*	Functionname: sumationq						*/
+/* -------------------------------------------------------------------- */
+/*	Parameter: 							*/
+/*		img: image to compute					*/
+/* -------------------------------------------------------------------- */
+/* 	Description: compute the sum of quadrats of all elements of  	*/
+/*	             the input image					*/
+/************************************************************************/
+static Pixel sumationq(Image img)
+{	Pixel sum=0;
+	int i;
+	
+	for (i=0;i<img->size;i++) {
+		sum+=(*img->data+i)*(*img->data+i);
+	}
+	return sum;
+}
+
+/************************************************************************/
+/*	Functionname: normq						*/
+/* -------------------------------------------------------------------- */
+/*	Parameter: 							*/
+/*		tree: tree to compute					*/
+/* -------------------------------------------------------------------- */
+/* 	Description: computes the quadratic norm over all images in 	*/
+/*	             the input tree					*/
+/************************************************************************/
+static Pixel normq(Image_tree tree)
+{	Pixel sum=0;
+
+	if (tree->image)
+	{
+		sum=sumationq(tree->image);
+	}
+	else 
+	{
+		if (tree->coarse) sum+=normq(tree->coarse);
+		if (tree->horizontal) sum+=normq(tree->horizontal);
+		if (tree->vertical) sum+=normq(tree->vertical);
+		if (tree->diagonal) sum+=normq(tree->diagonal);
+	}
+	
+	return sum;
+}
+
+/************************************************************************/
+/*	Functionname: sumation_down					*/
+/* -------------------------------------------------------------------- */
+/*	Parameter: 							*/
+/*		tree: tree to compute					*/
+/* 		normq: norm of the images in the tree			*/
+/* -------------------------------------------------------------------- */
+/* 	Description: computes the Entropy over all (string aded) images */
+/*	             in the input tree					*/
+/************************************************************************/
+static Pixel sumation_down(Image_tree tree, Pixel normq)
+{	Pixel sum=0,p;
+	int i;
+	Image img;
+	Pixel *data;
+
+	if (tree->image)
+	{
+		img=tree->image;
+		data=img->data;
+		for (i=0;i<img->size;i++,data++)
+		{
+			if (*data!=0)
+			{
+				p=(*data)*(*data)/normq;
+				sum+=p*log(1/p);
+			}
+		}
+	}
+	else
+	{
+		if (tree->coarse) sum+=sumation_down(tree->coarse,normq);
+		if (tree->horizontal) sum+=sumation_down(tree->horizontal,normq);
+		if (tree->vertical) sum+=sumation_down(tree->vertical,normq);
+		if (tree->diagonal) sum+=sumation_down(tree->diagonal,normq);
+	}
+	
+	return sum;
+}
+
+/************************************************************************/
+/*	Functionname: comp						*/
+/* -------------------------------------------------------------------- */
+/* 	Description: used for quicksort for decreasing order		*/
+/************************************************************************/
+int comp(const Pixel *x,const Pixel *y)
+{
+	if (*x<*y) return 1;
+	else if (*x==*y) return 0;
+	else return -1;
+}
+
+/************************************************************************/
+/*	Functionname: recarea						*/
+/*		tree: Image tree to compute				*/
+/*		list: target list					*/
+/*		list_size: actual size of the list			*/
+/* -------------------------------------------------------------------- */
+/* 	Description: copies all elements within the tree into an list	*/
+/************************************************************************/
+static void recarea(Image_tree tree,Pixel *list,int *list_size)
+{	Image img;
+	
+	if (tree->image)
+	{
+		img=tree->image;
+		memcpy(list+(*list_size),img->data,img->size*sizeof(Pixel));
+		*list_size+=img->size;
+	}
+	else 
+	{
+		if (tree->coarse) recarea(tree->coarse,list,list_size);
+		if (tree->horizontal) recarea(tree->horizontal,list,list_size);
+		if (tree->vertical) recarea(tree->vertical,list,list_size);
+		if (tree->diagonal) recarea(tree->diagonal,list,list_size);
+	}
+		
+}
+
+static void abs_list(Pixel *list,int list_size)
+{
+	int i;
+
+	for (i=0;i<list_size;i++) list[i]=fabs(list[i]);
+}
+
+/************************************************************************/
+/*	Functionname: sum_list						*/
+/* -------------------------------------------------------------------- */
+/* 	Description: computes the sum of all poweres list elements	*/
+/************************************************************************/
+static Pixel sum_list(Pixel *list,int p,int size)
+{	Pixel sum=0;
+	int i;
+	
+	for (i=0;i<size;i++)
+	{
+		if (p!=1) sum+=pow(list[i],p);
+		else sum+=list[i];
+	}
+	return sum;
+}
+
+static Pixel weak_lp(Image_tree tree,int size,int p,double epsilon)
+{	Pixel wlp,*list,max=0;
+	int *list_size,k;
+
+	list_size=(int *)malloc(sizeof(int));
+	if (!list_size) goto error;
+	
+	*list_size=0;
+	
+	list=(Pixel *)calloc(size,sizeof(Pixel));
+	if (!list) goto error;
+	
+	recarea(tree,list,list_size);
+	abs_list(list,*list_size);
+
+	qsort(list,*list_size, sizeof(Pixel), &comp);
+
+	for (k=0;k<size;k++)
+	{
+		if (k!=0) wlp=pow(k,1/p)*list[k];
+		else wlp=0;
+		if (wlp>max) max=wlp;
+	}
+
+	free(list);
+	
+	return max;
+	
+	error:
+        	err_SimpleMessage(err_GetErrorMessage(Error_NotEnoughMemory));	
+	  	return 0;		
+}
+
+static Pixel comp_number(Image_tree tree,int size,int p,double f)
+{	Pixel sum=0,*list,min,norm,npf,normf;
+	int *list_size=0,k;
+
+	list_size=(int *)malloc(sizeof(int));
+	if (!list_size) goto error;
+	*list_size=0;
+
+	list=(Pixel *)calloc(size,sizeof(Pixel));
+	if (!list) goto error;
+	recarea(tree,list,list_size);
+	abs_list(list,*list_size);
+
+	qsort(list,*list_size, sizeof(Pixel), &comp);
+
+	norm=sum_list(list,p,size);
+	normf=norm*f;
+
+	for (k=0;k<size;k++)
+	{
+		if (list[k]!=0)
+		{
+			sum+=pow(list[k],p);
+			npf=fabs(sum-normf);
+			if (npf<min) min=npf;
+		}
+	}
+	min=min/norm;
+
+	free(list);
+	
+	return min;
+
+	error:
+        	err_SimpleMessage(err_GetErrorMessage(Error_NotEnoughMemory));	
+	  	return 0;	
+}
+
+static Pixel comp_area(Image_tree tree,int size,int p,double f)
+{	Pixel sum=0,*list,norm,vk=0;
+	int *list_size=0,k;
+
+	list_size=(int *)malloc(sizeof(int));
+	if (!list_size) goto error;
+	*list_size=0;
+
+	list=(Pixel *)calloc(size,sizeof(Pixel));
+	if (!list) goto error;
+	
+	recarea(tree,list,list_size);
+	abs_list(list,*list_size);
+	
+	qsort(list,*list_size, sizeof(Pixel), &comp);
+
+	norm=sum_list(list,p,size);
+
+	for (k=0;k<size;k++)
+	{
+		if (list[k]!=0)
+		{
+			vk+=pow(list[k],p);
+			sum+=vk;
+			
+		}
+	}
+
+	free(list);
+	
+	return (size-sum/norm);
+
+	error:
+        	err_SimpleMessage(err_GetErrorMessage(Error_NotEnoughMemory));	
+	  	return 0;	
+}
+
+static Pixel compute_sdiscrepancy(Image_tree tree,int size)
+{	Pixel *list,min,max,factor,maximum=0,x;
+	int *list_size=0,k;
+
+	list_size=(int *)malloc(sizeof(int));
+	if (!list_size) goto error;
+	*list_size=0;
+
+	list=(Pixel *)calloc(size,sizeof(Pixel));
+	if (!list) goto error;
+
+	recarea(tree,list,list_size);
+	
+	qsort(list,*list_size, sizeof(Pixel), &comp);
+
+	min=list[0];
+	max=list[size-1];
+	factor=1/(max-min);
+
+				/*scaling to [0,1]*/
+	for (k=0;k<size;k++)
+	{
+		list[k]=factor*(list[k]-min);
+	}
+
+	for (k=0;k<size;k++)
+	{
+		x=fabs(list[k]-(2*k-1)/(2*size));
+		if (x>maximum) maximum=x;
+	}
+	
+	free(list);
+	
+	return (1/(2*size)+maximum);
+
+	error:
+        	err_SimpleMessage(err_GetErrorMessage(Error_NotEnoughMemory));	
+	  	return 0;	
+}
+
+static Pixel compute_discrepancy(Image_tree tree,int size)
+{	Pixel *list,min,max,factor,maximum=0,minimum=0,x;
+	int *list_size=0,k;
+
+	list_size=(int *)malloc(sizeof(int));
+	if (!list_size) goto error;
+	*list_size=0;
+
+	list=(Pixel *)calloc(size,sizeof(Pixel));
+	if (!list) goto error;
+
+	recarea(tree,list,list_size);
+	
+	qsort(list,*list_size, sizeof(Pixel), &comp);
+
+	min=list[0];
+	max=list[size-1];
+	factor=1/(max-min);
+
+				/*scaling to [0,1]*/
+	for (k=0;k<size;k++)
+	{
+		list[k]=factor*(list[k]-min);
+	}
+
+	for (k=0;k<size;k++)
+	{
+		x=((Pixel)k/size-list[k]);
+		if (x>maximum) maximum=x;
+		else if (x<minimum) minimum=x;
+		
+	}
+	
+	free(list);
+	
+	return (1/size+maximum-minimum);
+
+	error:
+        	err_SimpleMessage(err_GetErrorMessage(Error_NotEnoughMemory));	
+	  	return 0;	
+}
+
+static Pixel compute_concentration(Image_tree tree,int size)
+{	Pixel *list,min,max,factor,lkm=0,length,sum=0,value,norm;
+	int *list_size=0,k,next=0,last=0,i=0;
+
+	list_size=(int *)malloc(sizeof(int));
+	if (!list_size) goto error;
+	*list_size=0;
+
+	list=(Pixel *)calloc(size+1,sizeof(Pixel));
+	if (!list) goto error;
+
+	recarea(tree,list,list_size);
+	
+	qsort(list,*list_size, sizeof(Pixel), &comp);
+
+	min=list[0];
+	max=list[size-1];
+	length=(max-min)/100;
+	
+	factor=1/(max-min);
+	for (k=0;k<size;k++)
+	{
+		list[k]=factor*(list[k]-min);
+	}
+	
+	norm=size*sum_list(list,1,size);
+	length=0.01;
+	value=length;
+	
+	list[size]=max+value;
+	
+	for (k=0;k<100;k++)
+	{
+		while ((list[i]<value)&(i<size))
+		{
+			sum+=list[i];
+			next++;
+			i++;
+		}
+		lkm+=(next-last)*sum/norm;
+		value+=length;
+		last=next;
+		sum=0;
+	}
+	
+	return -lkm;
+	
+	error:
+        	err_SimpleMessage(err_GetErrorMessage(Error_NotEnoughMemory));	
+	  	return 0;	
+}
+/************************************************************************/
+/*	Functionname: compute_entropy					*/
+/* -------------------------------------------------------------------- */
+/*	Parameter: 							*/
+/*		img: Image from which the entropy should be computed	*/
+/*		cost: choosen costfunction				*/
+/*		epsilon: limit for threshold method			*/
+/* -------------------------------------------------------------------- */
+/* 	Description: computes entropy of an image			*/
+/************************************************************************/
+static double compute_entropy(Image img,enum Information_Cost cost,double epsilon)
+{       double sum=0,x=0;
+	int i;
+	Pixel *data;
+	
+	data=img->data;
+	
+	switch(cost) {
+
+	case threshold:
+  		for(i=0;i<img->size;i++) 
+	    		if (fabs(img->data[i])>epsilon) sum++;  
+  	break;
+
+	case log_energy:  
+        	for(i=0;i<img->size;i++,data++) {
+        		x=(*data) * (*data);
+	  		if (x!=0) sum+=(x*log(1/x));
+	  	}
+	break;
+
+	case norml:
+        	for(i=0;i<img->size;i++,data++) {
+        		x=fabs(*data);
+	  		sum+=x;
+	  	}
+	break;	
+
+	case norml2:
+        	for(i=0;i<img->size;i++,data++) {
+        		x=(*data) * (*data);
+	  		sum+=x;
+	  	}
+	  	sum=pow(sum,0.5);
+	break;	
+
+	case entropy:
+		for(i=0;i<img->size;i++,data++) {
+	    		x=(*data)*(*data);
+	    		if (x!=0) sum-=(x*log(x));
+	  	}
+	break;
+	 
+	case gauss_markov:
+		for(i=0;i<img->size;i++) {
+	    		x=(img->data[i])*(img->data[i]);
+		if (x!=0) sum+=log(x*x);
+		}
+	break;
+
+        }
+
+        return sum;
+}
+
+/************************************************************************/
+/*	Functionname: compute_non_additive				*/
+/* -------------------------------------------------------------------- */
+/*	Parameter: 							*/
+/*		tree: Image tree from which the entropy should be 	*/
+/*			computed					*/
+/*		size :	size of the image				*/
+/*		cost: choosen costfunction				*/
+/*		epsilon: limit for threshold method			*/
+/*		down: decides if only the first image should be computed*/ 
+/* -------------------------------------------------------------------- */
+/* 	Description: computes entropy of an image			*/
+/************************************************************************/
+static Pixel compute_non_additive(Image_tree tree,int size,enum Information_Cost cost,double epsilon,int down)
+{	Pixel sum=0,normx;
+	Image img;
+
+	if (down)
+	{
+		img=tree->image;
+		tree->image=NULL;
+	}
+	switch (cost)
+	{
+		case shanon:
+			normx=normq(tree);
+			sum=-sumation_down(tree,normx);
+			
+			break;
+		case weak_l:
+			sum=weak_lp(tree,size,1,epsilon);
+			break;
+		case weak_lq:
+			sum=weak_lp(tree,size,2,epsilon);
+			break;
+		case compression_number:
+			sum=comp_number(tree,size,1,epsilon);
+			break;
+		case compression_numberq:
+			sum=comp_number(tree,size,2,epsilon);
+			break;
+		case compression_area:
+			sum=comp_area(tree,size,1,epsilon);
+			break;
+		case compression_areaq:
+			sum=comp_area(tree,size,2,epsilon);
+			break;
+		case discrepancy:
+			sum=compute_discrepancy(tree,size);
+			break;	
+		case sdiscrepancy:
+			sum=compute_sdiscrepancy(tree,size);
+			break;
+		case concentration:
+			sum=compute_concentration(tree,size);
+			break;
+			
+					
+	}
+
+	if (down) tree->image=img;
+	
+	return sum;
+}
+
+extern int rec_double(Image_tree dtree,int level,FilterGH *flt,enum FilterMethod method,enum Information_Cost cost,double epsilon)
+
+{	int min,width,height;
+	double sum=0;
+	Image c,h,v,d;
+
+	dtree->level=0;
+	
+	if (cost>=shanon)
+	{
+		dtree->entropy=compute_non_additive(dtree,dtree->image->size,cost,epsilon,0);
+	}
+	else 	dtree->entropy=compute_entropy(dtree->image,cost,epsilon);
+	
+	dtree->doubletree=best_basis(dtree->image,level,flt,method,cost,epsilon);
+	
+	min=dtree->image->width;
+	if (dtree->image->height<min) min=dtree->image->height;
+
+	if (doubletree_min<min)
+	{
+		width=(dtree->image->width+1)/2;
+		height=(dtree->image->height+1)/2;
+		
+		dtree->coarse=new_image_tree();
+		dtree->horizontal=new_image_tree();
+		dtree->vertical=new_image_tree();	
+		dtree->diagonal=new_image_tree();
+		
+		c=new_image(width,height);
+		h=new_image(width,height);
+		v=new_image(width,height);
+		d=new_image(width,height);
+		if(!c||!h||!v||!d) goto error;          	
+		
+
+		copy_part_of_image(c,dtree->image,0,0);
+		copy_part_of_image(h,dtree->image,width,0);
+		copy_part_of_image(v,dtree->image,0,height);
+		copy_part_of_image(d,dtree->image,width,height);
+
+		dtree->coarse->image=c;
+		dtree->horizontal->image=h;
+		dtree->vertical->image=v;	
+		dtree->diagonal->image=d;
+
+		rec_double(dtree->coarse,level,flt,method,cost,epsilon);
+ 		rec_double(dtree->horizontal,level,flt,method,cost,epsilon);
+ 		rec_double(dtree->vertical,level,flt,method,cost,epsilon);
+ 		rec_double(dtree->diagonal,level,flt,method,cost,epsilon);
+
+ 		/* going back in recursion*/
+
+ 		sum=dtree->coarse->entropy+dtree->horizontal->entropy+
+ 			dtree->vertical->entropy+dtree->diagonal->entropy;
+
+ 		if (sum>dtree->entropy)
+ 		{
+ 			/*take image*/
+ 			
+ 			free_image_tree(dtree->coarse);
+  			free_image_tree(dtree->horizontal);
+  			free_image_tree(dtree->vertical);
+  			free_image_tree(dtree->diagonal);
+  			dtree->coarse=dtree->horizontal=dtree->vertical=dtree->diagonal=NULL;
+ 		}
+ 		else
+ 		{	/*take tiling*/
+ 			dtree->entropy=sum;
+ 			free_image(dtree->image);
+ 			dtree->image=NULL;
+ 		}
+  			
+ 		if (dtree->entropy>dtree->doubletree->entropy)
+ 		{	
+ 			/*take best basis tree*/
+
+ 			dtree->entropy=dtree->doubletree->entropy;
+ 			
+ 			if(dtree->coarse) free_image_tree(dtree->coarse);
+  			if(dtree->horizontal) free_image_tree(dtree->horizontal);
+  			if(dtree->vertical) free_image_tree(dtree->vertical);
+  			if(dtree->diagonal) free_image_tree(dtree->diagonal);
+ 					
+  			dtree->coarse=dtree->doubletree->coarse;
+  			dtree->horizontal=dtree->doubletree->horizontal;
+  			dtree->vertical=dtree->doubletree->vertical;
+  			dtree->diagonal=dtree->doubletree->diagonal;
+  			
+ 			free_image(dtree->image);
+ 			dtree->image=NULL;
+ 			free(dtree->doubletree);
+ 			dtree->doubletree=NULL;
+   			
+  		}
+ 		else
+ 		{
+ 			dtree->flag=1;
+ 			if(dtree->doubletree) free_image_tree(dtree->doubletree);
+ 			dtree->doubletree=NULL;
+ 		}
+	}
+		
+	return 1;
+
+	error:
+        	err_SimpleMessage(err_GetErrorMessage(Error_NotEnoughMemory));	
+	  	return 0;		
+}		
+
+static save_structur(Image_tree tree,FILE *fp,int pos)
+{
+	int shift,next_pos,max;
+
+	if (tree->flag)
+	{
+		fprintf(fp,"%d ",pos);
+	
+		shift=pos-(pow(4,tree->level-1)-1)*4/3-1;
+		max=(int) ((pow(4,tree->level)-1)*4/3);
+		next_pos=max+4*shift+1;
+		if (tree->coarse) save_structur(tree->coarse,fp,next_pos);
+		if (tree->horizontal) save_structur(tree->horizontal,fp,next_pos+1);
+		if (tree->vertical) save_structur(tree->vertical,fp,next_pos+2);
+		if (tree->diagonal) save_structur(tree->diagonal,fp,next_pos+3);	
+	}
+	
+}
+
+static int is_in_list(int *list,int len, int x)
+{
+	int i,found=0;
+
+	for (i=0;i<len;i++)
+	{
+		if (list[i]==x)
+		{
+			found=1;
+			i=len;
+		}
+	}
+
+	return found;
+}
+
+static write_flags(Image_tree tree,int *list,int len,int pos)
+{
+	int shift,next_pos,max;
+
+	if (is_in_list(list,len,pos))
+	{
+		tree->flag=1;
+	
+		shift=pos-(pow(4,tree->level-1)-1)*4/3-1;
+		max=(int) ((pow(4,tree->level)-1)*4/3);
+		next_pos=max+4*shift+1;
+		
+		write_flags(tree->coarse,list,len,next_pos);
+		write_flags(tree->horizontal,list,len,next_pos+1);
+		write_flags(tree->vertical,list,len,next_pos+2);
+		write_flags(tree->diagonal,list,len,next_pos+3);		
+	}
+}
+
+static read_structur(Image_tree tree,FILE *fp)
+{
+	int e, flags[1000],len=0,i=0;
+
+	do
+	{
+		e=fscanf(fp,"%d ",&flags[i++]);
+		if (e!=-1) len++;
+	}
+	while (e!=-1);
+
+	write_flags(tree,flags,len,0);
+
+}
+
+/************************************************************************/
+/*	Functionname:		err_simple_message			*/
+/* -------------------------------------------------------------------- */
+/*	Parameter:							*/
+/*	    char *: string that contains information about an		*/
+/*		    error the user should know.				*/
+/* -------------------------------------------------------------------- */
+/* 	Description:							*/
+/*	    Prints error messages for the user.				*/
+/************************************************************************/
+
+void err_SimpleMessage(char *message)
+{
+	fprintf(stderr,"%s\n",message);
+}
+
+/************************************************************************/
+/*	Functionname: 		err_get_message				*/
+/* -------------------------------------------------------------------- */
+/* 	Return value:   Errormessage for this specific error.		*/
+/*	Parameter:							*/
+/*	    Error err:	Error whose errormessage should be returned	*/
+/* -------------------------------------------------------------------- */
+/*	Description:							*/
+/************************************************************************/
+char * err_GetErrorMessage(Error err)
+{
+
+        switch (err)
+        {
+            case Error_NotImplemented:
+                return "Sorry, this is not implemented yet. ";
+                break;
+
+            case Error_AssertionFailed:
+                return "Sorry, an internal assertion was violated.\n"
+                       "This action can not be completed. :-(";
+                break;
+
+            case Error_NotEnoughMemory:
+                return "Sorry, there is not enough memory";
+                break;
+
+            case Error_Limitation:
+                return "Some limitation of the program exceeded";
+                break;
+
+	/* - FILES - */
+
+	    case Error_CantOpenFile:
+		return "Could not open file";
+		break;
+
+	    case Error_CantCreateFile:
+		return "Could not create file";
+		break;
+
+	    case Error_CantCloseFile:
+		return "Could not close file";
+		break;
+            
+	    case Error_InternalError:
+                return "Sorry, an internal error occured.\n"
+                       "This action can not be completed. :-(";
+                break;
+
+            default:
+                return "Sorry, but an unknown error ocurred.\n"
+                       "This action can not be completed. :-(";
+                break;
+
+
+	}
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Meerwald/wavelet.h	Sun Aug 12 13:14:34 2007 +0200
@@ -0,0 +1,334 @@
+#ifndef WAVELET_H
+
+#include <stdio.h>
+
+extern char dbgstr[1000];
+
+/* this are internal functions - don't use 'em! */
+extern void out_dbg_str(const char *str);
+extern void start_trace(void);
+extern void stop_trace(void);
+extern void flush_trace_file(void);
+
+/* public functions / macros */
+#define StartTrace
+#define StopTrace
+
+#define Trace(str)
+#define TraceVar(str,var)
+
+#define Entering
+#define Leaving
+#define LeavingErr
+#define FlushTrace
+
+#define Warning(str)
+
+#define PreCondition(exp,str)
+#define PostCondition(exp,str)
+
+/* Note that if an error is added, an errormessage for this specific
+   error must also be added. Otherwise no appropriate message can
+   be displayed in an error window. ( Then "Unknown error ocurred"
+   will be displayed.)
+   The errormessage must be added to the case-construct in the 
+   procedure err_GetErrorMessage
+*/   
+
+typedef enum
+{
+        Error_NoError,          /* No Error has happened. */
+        Error_NotImplemented,   /* A needed part has not (yet) been 
+                                   implemented */
+        Error_AssertionFailed,  /* An assertion, pre- or postcondition failed. 
+                                   Occurs only in buggy programs. */
+        Error_NotEnoughMemory,   /* We can't allocate the memory we need. */
+
+        Error_Limitation,       /* Some limitation exceeded, e.g. a string
+                                   variable is too short */
+
+
+	Error_CantOpenFile,	/* The file cannot be opened */
+	Error_CantCreateFile,
+        Error_CantWriteIntoFile,
+	Error_CantCloseFile,
+	Error_WrongFileFormat,
+
+	Error_WidthOrHeightZero,
+	Error_CompressedZeroContent,
+	Error_OriginalZeroContent,
+
+	Error_InternalError
+
+}Error;	
+	
+
+/************************************************************************/
+/*      Functionname:           err_simple_message                      */
+/* -------------------------------------------------------------------- */
+/*      Parameter:                                                      */
+/*          char *: string that contains information about an           */
+/*                  error the user should know.                         */
+/* -------------------------------------------------------------------- */
+/*      Description:                                                    */
+/*          Prints error messages for the user.                         */
+/************************************************************************/
+void err_SimpleMessage(char *message);
+
+/************************************************************************/
+/*      Functionname:           err_get_message                         */
+/* -------------------------------------------------------------------- */
+/*      Return value:   Errormessage for this specific error.           */
+/*      Parameter:                                                      */
+/*          Error err:  Error whose errormessage should be returned     */
+/* -------------------------------------------------------------------- */
+/*      Description:                                                    */
+/************************************************************************/
+char * err_GetErrorMessage(Error err);
+
+#include <stddef.h>
+
+typedef double Pixel;
+
+typedef struct Image_struct {
+	Pixel *data;
+	int width,height;
+
+	/* redundant, for our fun only :-) */
+	Pixel min_val,max_val;   /* range of pixel-values in data */
+                                 /* [min_val..max_val] */
+	int size;   /* = width * height */
+	int bpp;    /* bits per pixel of original image */
+	} *Image;
+
+typedef unsigned int IntPixel;
+
+typedef struct IntImage_struct {
+	IntPixel *data;
+	int width, height;
+
+	/* redundant, for our fun only :-) */
+	IntPixel min_val,max_val;   /* range of values in data */
+                                    /* [min_val..max_val] */
+	int size;   /* = width * height */
+	int bpp;    /* bits per pixel of original image */
+	} *IntImage;
+
+typedef struct Image_tree_struct {
+	double entropy;
+	struct Image_tree_struct *coarse,*horizontal,*vertical,*diagonal,*doubletree;
+	Image image;
+	int level;
+	int flag;
+
+	void *codec_data;
+	IntImage significance_map;
+	} *Image_tree;
+
+typedef struct Image_info_struct {
+	Pixel min,max,mean,var,rms;
+	} *Image_info;
+
+enum zigzag_direction {zigzag_up,zigzag_down,zigzag_right,zigzag_left};
+
+typedef struct Zigzag_data_struct {
+	int x,y,w,h;
+	enum zigzag_direction dir;
+	} *Zigzag_data;
+
+#define get_intpixel(image,x,y) ( ((image)==NULL || \
+	(x)<0 || (x)>=(image)->width || (y)<0 || (y)>=(image)->height) \
+	? (IntPixel) 0 : (image)->data[(x)+(y)*(image)->width])
+
+#define set_intpixel(image,x,y,val) if (!((image)==NULL || \
+	(x)<0 || (x)>=(image)->width || (y)<0 || (y)>=(image)->height)) \
+	(image)->data[(x)+(y)*(image)->width]=(IntPixel) (val)
+
+#define get_pixel(image,x,y) ( ((image)==NULL || \
+	(x)<0 || (x)>=(image)->width || (y)<0 || (y)>=(image)->height) \
+	? (Pixel) 0 : (image)->data[(x)+(y)*(image)->width])
+
+#define set_pixel(image,x,y,val) if (!((image)==NULL || \
+	(x)<0 || (x)>=(image)->width || (y)<0 || (y)>=(image)->height)) \
+	(image)->data[(x)+(y)*(image)->width]=(Pixel) (val)
+
+#define get_pixel_adr(image,x,y) ( ((image)==NULL || \
+	(x)<0 || (x)>=(image)->width || (y)<0 || (y)>=(image)->height) \
+	? (Pixel*) NULL : (image)->data+((x)+(y)*(image)->width))
+
+/* functions: */
+
+extern IntImage new_intimage(int width, int height);
+extern IntImage load_intimage(char *file, int max_val);
+extern void free_intimage(IntImage img);
+
+extern void clear_intimage(IntImage img);
+extern void copy_into_intimage(IntImage img1,IntImage img2,int x,int y);
+extern void copy_part_of_intimage(IntImage img1,IntImage img2,int x,int y);
+
+extern Image new_image(int width, int height);
+extern void free_image(Image img);
+extern void clear_image(Image img);
+extern void copy_into_image(Image img1,Image img2,int x,int y);
+extern void scale_image(Image img,int maximum);
+extern void copy_part_of_image(Image img1,Image img2,int x,int y);
+
+extern void copy_part_of_image_into_image(
+				Image dest_img, int dest_x, int dest_y,
+				Image src_img, int src_x, int src_y,
+				int width, int height);
+
+
+extern int string_to_pixel(char *str, Pixel *p);
+
+extern Image load_image(char *file, int max_val);
+extern int save_image_P5(char *file, Image img);
+
+extern Image intimage_to_image(IntImage i);
+extern IntImage image_to_intimage(Image i);
+
+extern Image_tree new_image_tree();
+extern void free_image_tree(Image_tree t);
+
+extern Image get_difference_image(Image image1, Image image2);
+
+extern void get_image_infos(Image image, Image_info info);
+
+extern void get_intimage_infos(IntImage image, IntPixel *min, IntPixel *max, Pixel *avg, Pixel *var);
+
+extern void init_zigzag(Zigzag_data zz, int width, int height);
+extern void next_zigzag(Zigzag_data zz);
+extern Image get_absolute_image_scaled(Image img);
+
+/* common macros */
+
+#ifndef MIN
+#define MIN(a,b) ((a)<(b)?(a):(b))
+#endif
+
+#ifndef MAX
+#define MAX(a,b) ((a)>(b)?(a):(b))
+#endif
+
+enum FilterType { FTNoSymm, FTSymm, FTAntiSymm};
+
+typedef struct FilterStruct {
+	enum FilterType type;
+	int hipass;
+	Pixel * data;
+	int start,end;
+
+	int len;
+	} *Filter;
+
+extern Filter new_filter(int size);
+
+extern int filter_cutoff(Image in, int in_start, int in_len, int in_step,
+		Image out, int out_start, int out_len, int out_step,
+		Filter f);
+
+extern int filter_inv_cutoff(Image in, int in_start, int in_len, int in_step,
+		Image out, int out_start, int out_len, int out_step,
+		Filter f);
+
+extern int filter_periodical(Image in, int in_start, int in_len, int in_step,
+		Image out, int out_start, int out_len, int out_step,
+		Filter f);
+
+extern int filter_inv_periodical(Image in, int in_start, int in_len, int in_step,
+		Image out, int out_start, int out_len, int out_step,
+		Filter f);
+
+extern int filter_mirror(Image in, int in_start, int in_len, int in_step,
+		Image out, int out_start, int out_len, int out_step,
+		Filter f);
+
+extern int filter_inv_mirror(Image in, int in_start, int in_len, int in_step,
+		Image out, int out_start, int out_len, int out_step,
+		Filter f);
+
+extern Pixel get_filter_center(Filter f);
+
+enum FilterGHType { FTOrtho, FTBiOrtho, FTOther};
+
+typedef struct FilterGHStruct {
+	enum FilterGHType type;
+	Filter g, h, gi, hi;
+	char *name;
+	} *FilterGH;
+
+typedef struct AllFilterStruct {
+	FilterGH *filter;
+	int count;
+	} *AllFilters;
+
+
+extern AllFilters load_filters(char *name);
+
+typedef struct SegmentsStruct	{
+		int width,height; /* segment width & height*/
+		int *data;
+	} *Segments;
+	
+enum FilterMethod{cutoff,inv_cutoff,periodical,inv_periodical,mirror,inv_mirror};
+
+enum Information_Cost{threshold,log_energy,entropy,norml,norml2,gauss_markov,
+		shanon,weak_l,weak_lq,compression_number,compression_numberq,
+		compression_area,compression_areaq,sdiscrepancy,discrepancy,concentration};
+
+extern Image_tree wavelettransform(Image original,int level,FilterGH *flt,enum FilterMethod method);
+extern Image_tree wavelettransform_wp(Image original,int level,FilterGH *flt,enum FilterMethod method);
+                            
+extern Image_tree best_basis(Image original,int level,FilterGH *flt,
+				enum FilterMethod method,enum Information_Cost cost,double epsilon);
+				                             
+extern Image_tree best_level(Image original,int maxlevel,int *bestlevel,FilterGH *flt,enum FilterMethod method,
+				enum Information_Cost cost,double epsilon);
+
+extern Image build_image(Image_tree quadtree,int width,int height);
+
+extern Image inv_transform(Image_tree quadtree,FilterGH *flt,
+                                 enum FilterMethod method);
+
+extern Image inv_transform_wp(Image_tree quadtree,FilterGH *flt,
+                                 enum FilterMethod method);
+
+extern int rec_double(Image_tree dtree,int level,FilterGH *flt,enum FilterMethod method,enum Information_Cost cost,double epsilon);
+
+extern Image_tree decompose_to_level(Image original,int level,FilterGH *flt,enum FilterMethod method);
+
+extern decompose_all(Image_tree tree,int maxlevel,FilterGH *flt,enum FilterMethod method,
+				enum Information_Cost cost,double epsilon);
+
+extern int find_deepest_level(int width,int height);
+
+			/*Selective methods*/
+extern int selectiv_tiling1(Image img,Segments seg,int filternumber,char *file,
+                                enum Information_Cost cost,double epsilon);
+extern Image inv_selectiv_tiling1(char *file);
+
+extern int selectiv_tiling2(Image img,Segments seg,int filternumber,char *file,
+                                enum Information_Cost cost,double epsilon);
+extern Image inv_selectiv_tiling2(char *file);                    
+
+extern int selectiv_quant1(Image img,IntImage area,int filternumber,char *file,
+                                enum Information_Cost cost,double epsilon);
+extern Image inv_selectiv_quant1(char *file);
+
+extern int selectiv_quant2(Image img,IntImage area,int filternumber,char *file,
+                                enum Information_Cost cost,double epsilon);
+extern Image inv_selectiv_quant2(char *file);
+
+extern int selectiv_quant3(Image img,IntImage area,int filternumber,char *file,
+                                enum Information_Cost cost,double epsilon);
+extern Image inv_selectiv_quant3(char *file);
+
+extern smooth_block(Image img,int x,int y, int width,int height);
+
+extern compute_map(Image_tree tree,IntImage map);
+
+extern int *pixelarray_to_intarray(Pixel *pdata,int size);
+extern Pixel *intarray_to_pixelarray(int *idata,int size);
+
+#define WAVELET_H
+#endif
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Meerwald/wm.c	Sun Aug 12 13:14:34 2007 +0200
@@ -0,0 +1,38 @@
+#include "wm.h"
+
+#ifdef __MINGW32_VERSION
+void bzero(char *b, size_t length) {
+  int i;
+  for (i=0; i<length; i++) { *b=0; b++; }
+}
+#endif
+
+void set_in_binary() {
+#if defined(EMX)
+  _fsetmode(in, "b");
+#elif defined(MINGW)
+  setmode(STDIN_FILENO, O_BINARY);
+#endif
+}
+
+void set_out_binary() {
+#if defined(EMX)
+  _fsetmode(out, "b");
+#elif defined(MINGW)
+  setmode(STDOUT_FILENO, O_BINARY);
+#endif
+}
+
+void wm_init2() {
+  set_in_binary();
+}
+
+void wm_init1() {
+  set_out_binary();
+}
+
+void wm_init() {
+  set_in_binary();
+  set_out_binary();
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Meerwald/wm.h	Sun Aug 12 13:14:34 2007 +0200
@@ -0,0 +1,62 @@
+#ifndef WM_H
+#define WM_H
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <getopt.h>
+#include <math.h>
+#include <float.h>
+#include <fcntl.h>
+
+#if defined(MINGW)
+#define M_PI 3.1415926536
+#define rint floor
+#define MAXPATHLEN 255
+void bzero(char *b, size_t length);
+#elif defined(LINUX)
+#include <values.h>
+#include <sys/param.h>
+#else
+#error platform not supported
+#endif
+
+/*
+ * This macro is used to ensure correct rounding of integer values.
+ */
+#define ROUND(a) (((a) < 0) ? (int) ((a) - 0.5) : (int) ((a) + 0.5))
+
+/*
+ * Macros to converts number of bytes to number of bits and vice verse
+ */
+#define NBITSTOBYTES(N) ((N & 7) ? (N >> 3) + 1 : N >> 3)
+#define NBYTESTOBITS(N) (N << 3)
+
+#define GRAYRANGE(P) ((P > 255) ? 255 : (P < 0) ? 0 : P)
+#define PIXELRANGE(P) ((P > 255) ? 255 : (P < 0) ? 0 : P)
+
+#ifndef sqr
+#define sqr(X) ((X) * (X))
+#endif
+
+#ifndef MAX
+#define MAX(X, Y) (((X) > (Y)) ? (X) : (Y))
+#endif
+
+#ifndef MIN
+#define MIN(X, Y) (((X) < (Y)) ? (X) : (Y))
+#endif
+
+#ifdef NEED_STRCASECMP
+#define strcasecmp stricmp
+#endif
+
+#ifndef SIGN
+#define SIGN(X) (((X) > 0) ? ((X) == 0 ? 0 : 1) : -1)
+#endif
+
+void wm_init();
+void wm_init1();
+void wm_init2();
+
+#endif
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Meerwald/wm_bruyn_d.c	Sun Aug 12 13:14:34 2007 +0200
@@ -0,0 +1,503 @@
+#include "wm.h"
+#include "signature.h"
+#include "coord.h"
+#include "gray.h"
+#include "sort.h"
+#include "bruyn_common.h"
+#include "pgm.h"
+
+char *progname;
+
+// prints out program's parameters
+void usage(void) {
+  fprintf(stderr, "usage: %s [-b n] [-h] [-k] [-n n] [-o file] [-pP n] [-q n] [-tT n] [-v n] -s file file\n", progname);
+  fprintf(stderr, "\t-b n\t\tblock size\n");
+  fprintf(stderr, "\t-h\t\tprint usage\n");
+  fprintf(stderr, "\t-k\t\tdisable block skipping\n");
+  fprintf(stderr, "\t-n n\t\tnumber of signature bits to detect\n");
+  fprintf(stderr, "\t-o file\t\textracted signature file\n");
+  fprintf(stderr, "\t-p n\t\tpattern type for zone 1\n");
+  fprintf(stderr, "\t-P n\t\tpattern type for zone 2\n");
+  fprintf(stderr, "\t-q n\t\tsignature strength\n");
+  fprintf(stderr, "\t-s file\t\tembedded signature\n");
+  fprintf(stderr, "\t-t n\t\tthreshold for noise\n");
+  fprintf(stderr, "\t-T n\t\tthreshold for slope\n");
+  fprintf(stderr, "\t-v n\t\tverbosity level\n");
+  exit(0);
+}
+
+int main(int argc, char *argv[]) {
+  FILE *in = stdin;
+  FILE *out = stdout;
+  FILE *sig = NULL;
+
+  gray** image;
+  gray **block;
+  gray **zone;
+  gray **category1, **category2;
+  gray maxval;
+  double *slope;
+  int rows, cols, colors, format;
+  int c;
+  int i, j;
+  int r;
+  int n;
+  int col, row;
+  int bwidth, bheight;
+  int n_block;
+
+  char signature_name[MAXPATHLEN];
+  char input_name[MAXPATHLEN] = "(stdin)";
+  char output_name[MAXPATHLEN] = "(stdout)";
+
+  double quality = 0.0;
+  double threshold_noise = 0.0;
+  double threshold_slope = 0.0;
+  int pattern1 = 0;
+  int pattern2 = 0;
+  int blocksize = 0;
+  int seed;
+
+  int verbose = 0;
+  int skipping = 0;
+
+  struct coords *coords;
+
+  progname = argv[0];
+
+  pgm_init(&argc, argv); wm_init2();
+
+  // parse command line and set options
+  while ((c = getopt(argc, argv, "b:h?n:o:p:P:q:s:t:T:v:k")) != EOF) {
+    switch (c) {
+      case 'h':
+      case '?':
+        usage();
+        break;
+      case 'k':  
+        skipping = 1;
+        break;
+      case 'n':
+        nbit_signature = atoi(optarg);
+        if (nbit_signature <= 0 || nbit_signature > NBITSIGNATURE) {
+          fprintf(stderr, "%s: invalid signature length %d\n", progname, nbit_signature);
+          exit(1);
+        }
+        break;
+      case 'o':
+        if ((out = fopen(optarg, "wb")) == NULL) {
+          fprintf(stderr, "%s: unable to open output file %s\n", progname, optarg);
+          exit(1);
+        }
+        strcpy(output_name, optarg);
+        break;
+      case 'p':
+        pattern1 = atoi(optarg);
+        if (pattern1 <= 0 || pattern1 > NPATTERN) {
+          fprintf(stderr, "%s: pattern type out of range\n", progname);
+          exit(1);
+        }
+        break;
+      case 'P':
+        pattern2 = atoi(optarg);
+        if (pattern2 <= 0 || pattern2 > 3) {
+          fprintf(stderr, "%s: pattern type out of range\n", progname);
+          exit(1);
+        }
+        break;
+      case 'q':
+        quality = atof(optarg);
+        if (quality <= 0) {
+          fprintf(stderr, "%s: quality factor %f out of range\n", progname, quality);
+        }
+        break;
+      case 's':
+        if ((sig = fopen(optarg, "r")) == NULL) {
+          fprintf(stderr, "%s: unable to open signature file %s\n", progname, optarg);
+          exit(1);
+        }
+        strcpy(signature_name, optarg);
+        break;
+      case 't':
+        threshold_noise = atof(optarg);
+        if (threshold_noise <= 0) {
+          fprintf(stderr, "%s: noise threshold %f out of range\n", progname, threshold_noise);
+        }
+        break;
+      case 'T':
+        threshold_slope = atof(optarg);
+        if (threshold_slope <= 0) {
+          fprintf(stderr, "%s: slope threshold %f out of range\n", progname, threshold_slope);
+        }
+        break;
+      case 'v':
+        verbose = atoi(optarg);
+        if (verbose < 0) {
+          fprintf(stderr, "%s: verbosity level %d out of range\n",progname, verbose);
+          exit(1);
+        }
+        break;
+    }
+  }
+
+  argc -= optind;
+  argv += optind;
+
+  if (argc > 1) {
+    usage();
+    exit(1);
+  }
+
+  // open input image file or read from stdin
+  if (argc == 1 && *argv[0] != '-')
+    if ((in = fopen(argv[0], "rb")) == NULL) {
+      fprintf(stderr, "%s: unable to open input file %s\n", progname, argv[0]);
+      exit(1);
+    }
+    else
+      strcpy(input_name, argv[0]);
+
+  // read signature file and set options
+  // command line options override signature file options
+  if (sig) {
+    char line[128];
+    fgets(line, sizeof(line), sig);
+    if (strspn(line, "BRSG") >= 4) {
+      if (nbit_signature == 0)
+        fscanf(sig, "%d\n", &nbit_signature);
+      else
+         fscanf(sig, "%*d\n");
+      if (skipping == 0)
+        fscanf(sig, "%d\n", &skipping);
+      else
+        fscanf(sig, "%*d\n");
+      if (pattern1 == 0)
+        fscanf(sig, "%d\n", &pattern1);
+      else
+        fscanf(sig, "%*d\n");
+      if (pattern2 == 0)
+        fscanf(sig, "%d\n", &pattern2);
+      else
+        fscanf(sig, "%*d\n");
+      if (quality == 0.0)
+        fscanf(sig, "%lf\n", &quality);
+      else
+        fscanf(sig, "%*lf\n");
+      if (threshold_noise == 0.0)
+        fscanf(sig, "%lf\n", &threshold_noise);
+      else
+        fscanf(sig, "%*lf\n");
+      if (threshold_slope == 0.0)
+        fscanf(sig, "%lf\n", &threshold_slope);
+      else
+        fscanf(sig, "%*lf\n");
+      if (blocksize == 0)
+        fscanf(sig, "%d\n", &blocksize);
+      else
+        fscanf(sig, "%*d\n");
+      fscanf(sig, "%d\n", &seed);
+      srandom(seed);
+      n_signature = NBITSTOBYTES(nbit_signature);
+      fread(signature, sizeof(char), n_signature, sig);
+      init_signature_bits();
+      fscanf(sig, "\n");
+    }
+    else {
+      fprintf(stderr, "%s: invalid signature file %s\n", progname, signature_name);
+      exit(1);
+    }
+    fclose(sig);
+  }
+  else {
+    fprintf(stderr, "%s: signature file not specified, use -s file option\n", progname);
+    exit(1);
+  }
+
+  if (pattern1 <= 0 || pattern2 <= 0 || pattern1 > NPATTERN || pattern2 > NPATTERN) {
+    fprintf(stderr, "%s: invalid pattern type specified\n");
+    exit(1);
+  }
+
+  // read dimensions of input image file
+  pgm_readpgminit(in, &cols, &rows, &maxval, &format);
+
+  // see if we can extract all signature bits
+  // we want at least half of the blocks untouched
+  if (((rows / blocksize) * (cols / blocksize)) < nbit_signature / 2) {
+    fprintf(stderr, "%s: image not large enough to contain %d bits of signature\n", progname, nbit_signature);
+    exit(1);
+  }
+  n_block = blocksize * blocksize;
+
+  // allocate structure to remember which blocks we already touched, 
+  // allow plenty of room to skip over blocks
+  if ((coords = alloc_coords(nbit_signature * 2)) == NULL) {
+    fprintf(stderr, "%s: unable to allocate memory\n", progname);
+    exit(1);
+  }
+
+  // read in input image file
+  image = pgm_allocarray(cols, rows);
+  for (row = 0; row < rows; row++)
+    pgm_readpgmrow(in, image[row], cols, maxval, format);
+
+  fclose(in);
+
+  row = 0;
+  col = 0;
+
+  // allocate memory for one block
+  block = alloc_grays(blocksize, blocksize);
+
+  // allocate memory for zone classification
+  zone = alloc_grays(blocksize, blocksize);
+
+  // allocate memory for category classification
+  category1 = alloc_grays(blocksize, blocksize);
+  category2 = alloc_grays(blocksize, blocksize);
+
+  // set up category classification array according to 
+  // pattern type parameter
+  for (i = 0; i < blocksize; i++)
+    for (j = 0; j < blocksize; j++) {
+      category1[j][i] = lookup_pattern(pattern1, i, j);
+      category2[j][i] = lookup_pattern(pattern2, i, j);
+    }
+
+  // allocate memory for slope calculation
+  slope = malloc(sizeof(double) * n_block);
+
+  fprintf(out, "BRWM\n");
+  fprintf(out, "%d\n", nbit_signature);
+
+  // extract all the signature bits, one by one
+  n = 0;
+  while (n < nbit_signature) {
+    int xb;
+    int yb;
+    int blocktype;
+    double smax;
+    int alpha, beta_minus, beta_plus;
+    double mean_1A, mean_1B, mean_2A, mean_2B, mean_1, mean_2;
+    double mean__1A, mean__1B, mean__2A, mean__2B;
+    int n_1A, n_1B, n_2A, n_2B, n_1, n_2;
+    double sigma, sigma_1, sigma_2;
+    int zone1_ok, zone2_ok;
+
+    // find an unused block randomly, depending on seed
+    do {
+      xb = random() % (cols / blocksize);
+      yb = random() % (rows / blocksize);
+    } while (add_coord(coords, xb, yb) < 0);
+
+    // copy image block
+    copy_grays_to_block(block, image, xb * blocksize, yb * blocksize, blocksize, blocksize);    
+
+    if (verbose > 0)
+      fprintf(stderr, "detecting bit #%d in block at (%d/%d)\n", n, xb * blocksize, yb * blocksize);
+
+    // sort luminance values in block to represent increasing function F
+    sort_grays(block[0], n_block);
+
+    // calculate slopes of F and determine smax, the max. slope of F
+    // the index where smax occures is called alpha
+    alpha = 0;
+    smax = 0.0;
+    for (i = 0; i < n_block - 1; i++) {
+      slope[i] = block[0][i + 1] - block[0][i];
+      if (slope[i] > smax) {
+        smax = slope[i];
+        alpha = i;
+      }
+    }
+    slope[n_block - 1] = 0;
+
+    // block type classification
+    blocktype = BLOCKTYPE_UNKNOWN;
+
+    if (smax < threshold_noise) {
+      // block has noise contrast
+      beta_minus = beta_plus = alpha;
+      blocktype = BLOCKTYPE_NOISE;
+    }
+    else {
+      // block has progressive or hard contrast, let's find out...
+
+      beta_minus = alpha - 1;
+      while (beta_minus >= 0 && smax - slope[beta_minus] <= threshold_slope)
+        beta_minus--;
+
+      beta_plus = alpha + 1;
+      while (beta_plus < n_block && smax - slope[beta_plus] <= threshold_slope)
+        beta_plus++;
+
+      if (beta_minus + 1 == alpha && beta_plus - 1 == alpha)
+        blocktype = BLOCKTYPE_HARD;
+      else 
+        blocktype = BLOCKTYPE_PROGRESSIVE;
+    }
+
+    if (verbose > 1) {
+      fprintf(stderr, "blocktype: %d\n", blocktype);
+      fprintf(stderr, "Smax = %lf, alpha = %d, beta- = %d, beta+ = %d\n", smax, alpha, beta_minus, beta_plus);
+    }
+
+    // block pixel classification
+    for (i = 0; i < blocksize; i++)
+      for (j = 0; j < blocksize; j++) {
+        gray pixel = image[yb * blocksize + j][xb * blocksize + i];
+        zone[j][i] = ZONE_VOID;
+        switch (blocktype) {
+          case BLOCKTYPE_PROGRESSIVE:
+          case BLOCKTYPE_HARD:
+            if (pixel < block[0][beta_minus])
+              zone[j][i] = ZONE_1;  
+            else if (pixel > block[0][beta_plus])
+              zone[j][i] = ZONE_2;  
+            break;
+          case BLOCKTYPE_NOISE:
+            if (pixel < block[0][n_block / 2])
+              zone[j][i] = ZONE_1;
+            else if (pixel > block[0][n_block / 2])
+              zone[j][i] = ZONE_2;
+            break;
+          default:
+            fprintf(stderr, "%s: invalid block type\n", progname);
+            break;
+        }
+      }
+
+    // calculate mean values for zone/categories
+    mean_1A = mean_1B = mean_2A = mean_2B = mean_1 = mean_2 = 0.0;
+    n_1A = n_1B = n_2A = n_2B = n_1 = n_2 = 0;
+    for (i = 0; i < blocksize; i++)
+      for (j = 0; j < blocksize; j++) {
+        gray pixel = image[yb * blocksize + j][xb * blocksize + i];
+        int pixel_zone = zone[j][i];
+        int pixel_category = CATEGORY_VOID;
+        if (pixel_zone == ZONE_1)
+          pixel_category = category1[j][i];
+        else if (pixel_zone == ZONE_2)
+          pixel_category = category2[j][i];
+
+        switch (pixel_zone | pixel_category) {
+          case CLASSIFICATION_1A:
+            n_1++;
+            n_1A++;
+            mean_1A += pixel;
+            mean_1 += pixel;
+            break;
+          case CLASSIFICATION_1B:
+            n_1++;
+            n_1B++;
+            mean_1B += pixel;
+            mean_1 += pixel;
+            break;
+          case CLASSIFICATION_2A:
+            n_2++;
+            n_2A++;
+            mean_2A += pixel;
+            mean_2 += pixel;
+            break;
+          case CLASSIFICATION_2B:
+            n_2++;
+            n_2B++;
+            mean_2B += pixel;
+            mean_2 += pixel;
+            break;
+        }
+      }
+
+    if (n_1 && n_1A && n_1B) {   
+      mean_1 /= (double) n_1;
+      mean_1A /= (double) n_1A;
+      mean_1B /= (double) n_1B;
+      zone1_ok = 1;
+    }
+    else {
+      mean_1 = mean_1A = mean_1B = 0.0;
+      zone1_ok = 0;
+      if (verbose > 0)
+        fprintf(stderr, "zone 1 unusable\n");
+    }
+   
+    if (n_2 && n_2A && n_2B) {
+      mean_2 /= (double) n_2;
+      mean_2A /= (double) n_2A;
+      mean_2B /= (double) n_2B;
+      zone2_ok = 1;
+    }
+    else {
+      mean_2 = mean_2A = mean_2B = 0.0;
+      zone2_ok = 0;
+      if (verbose > 0)
+        fprintf(stderr, "zone 2 unusable\n");
+    }  
+
+    // bit extraction
+    if (zone1_ok && zone2_ok) {
+      sigma_1 = mean_1A - mean_1B;
+      sigma_2 = mean_2A - mean_2B;
+
+      if (verbose > 2) {
+        fprintf(stderr, "m_1A = %lf, m_1B = %lf\n", mean_1A, mean_1B);
+        fprintf(stderr, "m_2A = %lf, m_2B = %lf\n", mean_2A, mean_2B);
+        fprintf(stderr, "sigma1 = %lf, sigma2 = %lf\n", sigma_1, sigma_2);
+      }
+
+#define EPSILON 0.001
+      if (fabs(sigma_1 * sigma_2) < EPSILON) {
+        // case 3
+        sigma = MAX(fabs(sigma_1), fabs(sigma_2));
+        set_signature_bit(n, sigma > 0.0);
+        if (verbose > 0)
+          fprintf(stderr, "case 3, bit #%d = %d\n", n, sigma > 0.0);
+      }
+      else if (sigma_1 * sigma_2 > 0.0) {
+        // case 1
+        set_signature_bit(n, sigma_1 > 0.0); 
+        if (verbose > 0)
+          fprintf(stderr, "case 1, bit #%d = %d\n", n, sigma_1 > 0.0);
+      }
+      else if (sigma_1 * sigma_2 < 0.0) {
+        // case 2
+        sigma = (double) (n_1A + n_1B) * sigma_1 + (double) (n_2A + n_2B) * sigma_2;
+        set_signature_bit(n, sigma > 0.0);
+        if (verbose > 0)
+          fprintf(stderr, "case 2, bit #%d = %d\n", n, sigma > 0.0);
+      }
+    }
+    else if (zone1_ok) {
+      set_signature_bit(n, mean_1A > mean_1B);
+      if (verbose > 0)
+        fprintf(stderr, "case 4, bit #%d = %d\n", n, mean_1A > mean_1B);
+    }
+    else if (zone2_ok) {
+      set_signature_bit(n, mean_2A > mean_2B);
+      if (verbose > 0)
+        fprintf(stderr, "case 5, bit #%d = %d\n", n, mean_2A > mean_2B);
+    }
+    else {
+      // pathological case - can it ever happen?
+      if (verbose > 0)
+        fprintf(stderr, "block skipped\n");
+      if (!skipping) continue;
+    }
+
+    n++;      
+  }
+
+  free_grays(category2);
+  free_grays(category1);
+  free_grays(zone);
+  free_grays(block);
+
+  // write extracted signature
+
+  fwrite(signature, sizeof(char), n_signature, out);
+  fclose(out);
+
+  pgm_freearray(image, rows);
+
+  exit(0);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Meerwald/wm_bruyn_e.c	Sun Aug 12 13:14:34 2007 +0200
@@ -0,0 +1,551 @@
+#include "wm.h"
+#include "signature.h"
+#include "coord.h"
+#include "gray.h"
+#include "sort.h"
+#include "bruyn_common.h"
+#include "pgm.h"
+
+char *progname;
+
+// prints out program's parameters
+void usage(void) {
+  fprintf(stderr, "usage: %s [-b n] [-h] [-k] [-n n] [-o file] [-pP n] [-q n] [-tT n] [-v n] -s file file\n", progname);
+  fprintf(stderr, "\t-b n\t\tblock size\n");
+  fprintf(stderr, "\t-h\t\tprint usage\n");
+  fprintf(stderr, "\t-k\t\tdisable block skipping\n");
+  fprintf(stderr, "\t-n n\t\tnumber of signature bits to embed\n");
+  fprintf(stderr, "\t-o file\t\toutput (watermarked) file\n");
+  fprintf(stderr, "\t-p n\t\tpattern type for zone 1\n");
+  fprintf(stderr, "\t-P n\t\tpattern type for zone 2\n");
+  fprintf(stderr, "\t-q n\t\tsignature strength\n");
+  fprintf(stderr, "\t-s file\t\tsignature to embed in input image\n");
+  fprintf(stderr, "\t-t n\t\tthreshold for noise\n");
+  fprintf(stderr, "\t-T n\t\tthreshold for slope\n");
+  fprintf(stderr, "\t-v n\t\tverbosity level\n");
+  exit(0);
+}
+
+int main(int argc, char *argv[]) {
+  FILE *in = stdin;
+  FILE *out = stdout;
+  FILE *sig = NULL;
+
+  gray** image;
+  gray **block;
+  gray **zone;
+  gray **category1, **category2;
+  gray maxval;
+  double *slope;
+  int rows, cols, colors, format;
+  int c;
+  int i, j;
+  int r;
+  int n;
+  int col, row;
+  int bwidth, bheight;
+  int n_block;
+  int skipping = 0;
+
+  char signature_name[MAXPATHLEN];
+  char input_name[MAXPATHLEN] = "(stdin)";
+  char output_name[MAXPATHLEN] = "(stdout)";
+
+  double quality = 0.0;
+  double threshold_noise = 0.0;
+  double threshold_slope = 0.0;
+  int pattern1 = 0;
+  int pattern2 = 0;
+  int blocksize = 0;
+  int seed;
+
+  int verbose = 0;
+
+  struct coords *coords;
+
+  progname = argv[0];
+
+  pgm_init(&argc, argv); wm_init();
+
+  // parse command line and set options
+  while ((c = getopt(argc, argv, "b:h?n:o:p:P:q:s:t:T:v:k")) != EOF) {
+    switch (c) {
+      case 'k':  
+        skipping = 1;
+        break;
+      case 'h':
+      case '?':
+        usage();
+        break;
+      case 'n':
+        nbit_signature = atoi(optarg);
+        if (nbit_signature <= 0 || nbit_signature > NBITSIGNATURE) {
+          fprintf(stderr, "%s: invalid signature length %d\n", progname, nbit_signature);
+          exit(1);
+        }
+        break;
+      case 'o':
+        if ((out = fopen(optarg, "wb")) == NULL) {
+          fprintf(stderr, "%s: unable to open output file %s\n", progname, optarg);
+          exit(1);
+        }
+        strcpy(output_name, optarg);
+        break;
+      case 'p':
+        pattern1 = atoi(optarg);
+        if (pattern1 <= 0 || pattern1 > NPATTERN) {
+          fprintf(stderr, "%s: pattern type out of range\n", progname);
+          exit(1);
+        }
+        break;
+      case 'P':
+        pattern2 = atoi(optarg);
+        if (pattern2 <= 0 || pattern2 > 3) {
+          fprintf(stderr, "%s: pattern type out of range\n", progname);
+          exit(1);
+        }
+        break;
+      case 'q':
+        quality = atof(optarg);
+        if (quality <= 0) {
+          fprintf(stderr, "%s: quality factor %f out of range\n", progname, quality);
+        }
+        break;
+      case 's':
+        if ((sig = fopen(optarg, "r")) == NULL) {
+          fprintf(stderr, "%s: unable to open signature file %s\n", progname, optarg);
+          exit(1);
+        }
+        strcpy(signature_name, optarg);
+        break;
+      case 't':
+        threshold_noise = atof(optarg);
+        if (threshold_noise <= 0) {
+          fprintf(stderr, "%s: noise threshold %f out of range\n", progname, threshold_noise);
+        }
+        break;
+      case 'T':
+        threshold_slope = atof(optarg);
+        if (threshold_slope <= 0) {
+          fprintf(stderr, "%s: slope threshold %f out of range\n", progname, threshold_slope);
+        }
+        break;
+      case 'v':
+        verbose = atoi(optarg);
+        if (verbose < 0) {
+          fprintf(stderr, "%s: verbosity level %d out of range\n",progname, verbose);
+          exit(1);
+        }
+        break;
+    }
+  }
+
+  argc -= optind;
+  argv += optind;
+
+  if (argc > 1) {
+    usage();
+    exit(1);
+  }
+
+  // open input image file or read from stdin
+  if (argc == 1 && *argv[0] != '-')
+    if ((in = fopen(argv[0], "rb")) == NULL) {
+      fprintf(stderr, "%s: unable to open input file %s\n", progname, argv[0]);
+      exit(1);
+    }
+    else
+      strcpy(input_name, argv[0]);
+
+  // read signature file and set options
+  // command line options override signature file options
+  if (sig) {
+    char line[128];
+    fgets(line, sizeof(line), sig);
+    if (strspn(line, "BRSG") >= 4) {
+      if (nbit_signature == 0)
+        fscanf(sig, "%d\n", &nbit_signature);
+      else
+        fscanf(sig, "%*d\n");
+      if (skipping == 0)
+        fscanf(sig, "%d\n", &skipping);
+      else
+        fscanf(sig, "%*d\n");
+      if (pattern1 == 0)
+        fscanf(sig, "%d\n", &pattern1);
+      else
+        fscanf(sig, "%*d\n");
+      if (pattern2 == 0)
+        fscanf(sig, "%d\n", &pattern2);
+      else
+        fscanf(sig, "%*d\n");
+      if (quality == 0.0)
+        fscanf(sig, "%lf\n", &quality);
+      else
+        fscanf(sig, "%*lf\n");
+      if (threshold_noise == 0.0)
+        fscanf(sig, "%lf\n", &threshold_noise);
+      else
+        fscanf(sig, "%*lf\n");
+      if (threshold_slope == 0.0)
+        fscanf(sig, "%lf\n", &threshold_slope);
+      else
+        fscanf(sig, "%*lf\n");
+      if (blocksize == 0)
+        fscanf(sig, "%d\n", &blocksize);
+      else
+        fscanf(sig, "%*d\n");
+      fscanf(sig, "%d\n", &seed);
+      srandom(seed);
+      n_signature = NBITSTOBYTES(nbit_signature);
+      fread(signature, sizeof(char), n_signature, sig);
+      fscanf(sig, "\n");
+    }
+    else {
+      fprintf(stderr, "%s: invalid signature file %s\n", progname, signature_name);
+      exit(1);
+    }
+    fclose(sig);
+  }
+  else {
+    fprintf(stderr, "%s: signature file not specified, use -s file option\n", progname);
+    exit(1);
+  }
+
+  if (pattern1 <= 0 || pattern2 <= 0 || pattern1 > NPATTERN || pattern2 > NPATTERN) {
+    fprintf(stderr, "%s: invalid pattern type specified\n");
+    exit(1);
+  }
+
+  // read dimensions of input image file
+  pgm_readpgminit(in, &cols, &rows, &maxval, &format);
+
+  // see if we can embed all signature bits
+  // we want at least half of the blocks untouched
+  if (((rows / blocksize) * (cols / blocksize)) < nbit_signature / 2) {
+    fprintf(stderr, "%s: image not large enough to embed %d bits of signature\n", progname, nbit_signature);
+    exit(1);
+  }
+  n_block = blocksize * blocksize;
+
+  // allocate structure to remember which blocks we already touched,
+  // allow plenty of room to skip over blocks
+  if ((coords = alloc_coords(nbit_signature * 2)) == NULL) {
+    fprintf(stderr, "%s: unable to allocate memory\n", progname);
+    exit(1);
+  }
+
+  // read in input image file
+  image = pgm_allocarray(cols, rows);
+  for (row = 0; row < rows; row++)
+    pgm_readpgmrow(in, image[row], cols, maxval, format);
+
+  fclose(in);
+
+  row = 0;
+  col = 0;
+
+  // allocate memory for one block
+  block = alloc_grays(blocksize, blocksize);
+
+  // allocate memory for zone classification
+  zone = alloc_grays(blocksize, blocksize);
+
+  // allocate memory for category classification
+  category1 = alloc_grays(blocksize, blocksize);
+  category2 = alloc_grays(blocksize, blocksize);
+
+  // set up category classification array according to 
+  // pattern type parameter
+  for (i = 0; i < blocksize; i++)
+    for (j = 0; j < blocksize; j++) {
+      category1[j][i] = lookup_pattern(pattern1, i, j);
+      category2[j][i] = lookup_pattern(pattern2, i, j);
+    }
+
+  // allocate memory for slope calculation
+  slope = malloc(sizeof(double) * n_block);
+
+  // embed all the signature bits, one by one
+  n = 0;
+  while (n < nbit_signature) {
+    int xb;
+    int yb;
+    int blocktype;
+    double smax;
+    int alpha, beta_minus, beta_plus;
+    double mean_1A, mean_1B, mean_2A, mean_2B, mean_1, mean_2;
+    double mean__1A, mean__1B, mean__2A, mean__2B;
+    int n_1A, n_1B, n_2A, n_2B, n_1, n_2;
+    int var_1A, var_1B, var_2A, var_2B;
+    int zone1_ok, zone2_ok;
+
+    // find an unused block randomly, depending on seed
+    do {
+      xb = random() % (cols / blocksize);
+      yb = random() % (rows / blocksize);
+    } while (add_coord(coords, xb, yb) < 0);
+
+    // copy image block
+    copy_grays_to_block(block, image, xb * blocksize, yb * blocksize, blocksize, blocksize);    
+
+    if (verbose > 0)
+      fprintf(stderr, "embedding bit #%d (= %d) in block at (%d/%d)\n", n, get_signature_bit(n), xb * blocksize, yb * blocksize);
+    if (verbose > 8) {
+      print_grays(image, xb * blocksize, yb * blocksize, blocksize, blocksize);
+      fprintf(stderr, "\n");
+    }
+
+    // sort luminance values in block to represent increasing function F
+    sort_grays(block[0], n_block);
+
+    if (verbose > 8) {
+      print_grays(block, 0, 0, blocksize, blocksize);
+      fprintf(stderr, "\n");
+    }
+
+    // calculate slopes of F and determine smax, the max. slope of F
+    // the index where smax occures is called alpha
+    alpha = 0;
+    smax = 0.0;
+    for (i = 0; i < n_block - 1; i++) {
+      slope[i] = block[0][i + 1] - block[0][i];
+      if (slope[i] > smax) {
+        smax = slope[i];
+        alpha = i;
+      }
+    }
+    slope[n_block - 1] = 0;
+
+    // block type classification
+    blocktype = BLOCKTYPE_UNKNOWN;
+
+    if (smax < threshold_noise) {
+      // block has noise contrast
+     
+       blocktype = BLOCKTYPE_NOISE;
+      beta_minus = beta_plus = alpha;
+    }
+    else {
+      // block has progressive or hard contrast, let's find out...
+
+      beta_minus = alpha - 1;
+      while (beta_minus >= 0 && smax - slope[beta_minus] <= threshold_slope)
+        beta_minus--;
+
+      beta_plus = alpha + 1;
+      while (beta_plus < n_block && smax - slope[beta_plus] <= threshold_slope)
+        beta_plus++;
+
+      if (beta_minus + 1 == alpha && beta_plus - 1 == alpha)
+        blocktype = BLOCKTYPE_HARD;
+      else 
+        blocktype = BLOCKTYPE_PROGRESSIVE;
+    }
+
+    if (verbose > 1) {
+      fprintf(stderr, "blocktype: %d\n", blocktype); 
+      fprintf(stderr, "Smax = %lf, alpha = %d, beta- = %d, beta+ = %d\n", smax, alpha, beta_minus, beta_plus);
+    }
+
+    // block pixel classification
+    for (i = 0; i < blocksize; i++)
+      for (j = 0; j < blocksize; j++) {
+        gray pixel = image[yb * blocksize + j][xb * blocksize + i];
+        zone[j][i] = ZONE_VOID;
+        switch (blocktype) {
+          case BLOCKTYPE_PROGRESSIVE:
+          case BLOCKTYPE_HARD:
+            if (pixel < block[0][beta_minus])
+              zone[j][i] = ZONE_1;  
+            else if (pixel > block[0][beta_plus])
+              zone[j][i] = ZONE_2;  
+            break;
+          case BLOCKTYPE_NOISE:
+            if (pixel < block[0][n_block / 2])
+              zone[j][i] = ZONE_1;
+            else if (pixel > block[0][n_block / 2])
+              zone[j][i] = ZONE_2;
+            break;
+          default:
+            fprintf(stderr, "%s: invalid block type\n", progname);
+            break;
+        }
+      }
+ 
+    if (verbose > 8) {
+      print_grays(zone, 0, 0, blocksize, blocksize);
+      fprintf(stderr, "\n");
+    }
+
+    // calculate mean values for zone/categories
+    mean_1A = mean_1B = mean_2A = mean_2B = mean_1 = mean_2 = 0.0;
+    n_1A = n_1B = n_2A = n_2B = n_1 = n_2 = 0;
+    for (i = 0; i < blocksize; i++)
+      for (j = 0; j < blocksize; j++) {
+        gray pixel = image[yb * blocksize + j][xb * blocksize + i];
+        int pixel_zone = zone[j][i];
+        int pixel_category = CATEGORY_VOID;
+        if (pixel_zone == ZONE_1)
+          pixel_category = category1[j][i];
+        else if (pixel_zone == ZONE_2)
+          pixel_category = category2[j][i];
+
+        switch (pixel_zone | pixel_category) {
+          case CLASSIFICATION_1A:
+            n_1++;
+            n_1A++;
+            mean_1A += pixel;
+            mean_1 += pixel;
+            break;
+          case CLASSIFICATION_1B:
+            n_1++;
+            n_1B++;
+            mean_1B += pixel;
+            mean_1 += pixel;
+            break;
+          case CLASSIFICATION_2A:
+            n_2++;
+            n_2A++;
+            mean_2A += pixel;
+            mean_2 += pixel;
+            break;
+          case CLASSIFICATION_2B:
+            n_2++;
+            n_2B++;
+            mean_2B += pixel;
+            mean_2 += pixel;
+            break;
+        }
+      }
+
+    if (n_1 && n_1A && n_1B) {
+      mean_1 /= (double) n_1;
+      mean_1A /= (double) n_1A;
+      mean_1B /= (double) n_1B;
+      zone1_ok = 1;
+    }
+    else {
+      mean_1 = mean_1A = mean_1B = 0.0;
+      zone1_ok = 0;
+      if (verbose > 0)
+        fprintf(stderr, "zone 1 unusable\n");
+    }
+    
+    if (n_2 && n_2A && n_2B) {
+      mean_2 /= (double) n_2;
+      mean_2A /= (double) n_2A;
+      mean_2B /= (double) n_2B;
+      zone2_ok = 1;
+    }
+    else {
+      mean_2 = mean_2A = mean_2B = 0.0;
+      zone2_ok = 0;
+      if (verbose > 0)
+        fprintf(stderr, "zone 2 unusable\n");
+    }
+
+    if (!skipping && !zone1_ok && !zone2_ok) {
+      // pathological case - can it ever happen?
+      if (verbose > 0)
+        fprintf(stderr, "block skipped\n");
+      continue;
+    }
+
+    if (verbose > 2) {
+      fprintf(stderr, "m_1 = %lf, m_1A = %lf, m_1B = %lf\n", mean_1, mean_1A, mean_1B);
+      fprintf(stderr, "m_2 = %lf, m_2A = %lf, m_2B = %lf\n", mean_2, mean_2A, mean_2B);
+    }
+
+    // calculate new mean values required by embedding rule
+    if (get_signature_bit(n)) {
+      if (zone1_ok) {
+        mean__1A = (mean_1 * (double) (n_1A + n_1B) + (double) n_1B * quality) / (double) (n_1A + n_1B);
+        mean__1B = mean__1A - quality;
+      }
+      if (zone2_ok) {
+        mean__2A = (mean_2 * (double) (n_2A + n_2B) + (double) n_2B * quality) /  (double) (n_2A + n_2B);
+        mean__2B = mean__2A - quality;
+      }
+    }
+    else {
+      if (zone1_ok) {
+        mean__1A = (mean_1 * (double) (n_1A + n_1B) - (double) n_1B * quality) / (double) (n_1A + n_1B);
+        mean__1B = mean__1A + quality;
+      }
+      if (zone2_ok) {
+        mean__2A = (mean_2 * (double) (n_2A + n_2B) - (double) n_2B * quality) / (double) (n_2A + n_2B);
+        mean__2B = mean__2A + quality; 
+      }
+    }
+
+    // calculate luminance variations
+    if (zone1_ok) {
+      var_1A = rint(mean__1A - mean_1A);
+      var_1B = rint(mean__1B - mean_1B);
+    }
+    else var_1A = var_1B = 0;
+    
+    if (zone2_ok) {
+      var_2A = rint(mean__2A - mean_2A);
+      var_2B = rint(mean__2B - mean_2B);
+    }
+    else var_2A = var_2B = 0;
+
+    if (verbose > 2) {
+      if (zone1_ok)
+        fprintf(stderr, "m*_1A = %lf, m*_1B = %lf\n", mean__1A, mean__1B);
+      if (zone2_ok)
+        fprintf(stderr, "m*_2A = %lf, m*_2B = %lf\n", mean__2A, mean__2B);
+      fprintf(stderr, "var %d %d %d %d\n", var_1A, var_1B, var_2A, var_2B);
+    }
+
+    // apply luminance variations to image pixels
+    for (i = 0; i < blocksize; i++)
+      for (j = 0; j < blocksize; j++) {
+        int pixel = image[yb * blocksize + j][xb * blocksize + i];
+        int pixel_zone = zone[j][i];
+        int pixel_category = CATEGORY_VOID;
+        if (pixel_zone == ZONE_1)
+          pixel_category = category1[j][i];
+        else if (pixel_zone == ZONE_2)
+          pixel_category = category2[j][i];
+
+        switch (pixel_zone | pixel_category) {
+          case CLASSIFICATION_1A:
+            pixel = GRAYRANGE(pixel + var_1A);
+            break;
+          case CLASSIFICATION_1B:
+            pixel = GRAYRANGE(pixel + var_1B);
+            break;
+          case CLASSIFICATION_2A:
+            pixel = GRAYRANGE(pixel + var_2A);
+            break;
+          case CLASSIFICATION_2B:
+            pixel = GRAYRANGE(pixel + var_2B);
+            break;
+        }
+        image[yb * blocksize + j][xb * blocksize + i] = pixel;
+      }
+
+    n++;      
+  }
+
+  free_grays(category2);
+  free_grays(category1);
+  free_grays(zone);
+  free_grays(block);
+
+  // write output image dimensions to output file
+  pgm_writepgminit(out, cols, rows, maxval, 0);
+
+  // write output image
+  for (row = 0; row < rows; row++)
+    pgm_writepgmrow(out, image[row], cols, maxval, 0);
+
+  fclose(out);
+
+  pgm_freearray(image, rows);
+
+  exit(0);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Meerwald/wm_corvi_d.1	Sun Aug 12 13:14:34 2007 +0200
@@ -0,0 +1,173 @@
+.\"
+.\" wm_corvi_d.1 - the *roff document processor man page source
+.\"
+.TH wm_corvi_d 1 "98/07/29" "Watermarking, Version 1.0"
+.SH NAME
+.B wm_corvi_d
+\- a program to extract a signature from the DWT residue of a watermarked
+image
+.SH SYNOPSIS
+.B wm_corvi_d
+[
+.BI \-a \ number
+]
+[
+.BI \-e \ number
+]
+[
+.BI \-f \ number
+]
+[
+.BI \-F \ ffile
+]
+[
+.BI \-g \ number
+]
+[
+.B \-h
+]
+[
+.BI \-i \ ifile
+]
+.br
+[
+.BI \-n \ number
+]
+[
+.BI \-o \ ofile
+]
+[
+.BI \-q \ number
+]
+[
+.BI \-v \ number
+]
+.BI \-s \ sfile
+.I file
+.SH DESCRIPTION
+.B wm_corvi_d
+is a program to extract a signature from the DWT residue of
+a watermarked image
+.I file.
+The
+.B cmp_corvi_sig
+program is used to test the extracted signature against the original signature.
+The input image is in PGM (portable graymap) format.
+.PP
+If
+.I file
+or
+.I ofile
+is not specified, then standard input or standard output is
+used.
+.PP
+.B gen_corvi_sig
+is used to generate a signature file,
+.B wm_corvi_e
+embeds the signature into an image.
+.PP
+Please refer to Marco Corvi's paper "Wavelet-based image watermarking
+for copyright protection", to get an idea about the algorithm.
+.PP
+.SH OPTIONS
+.TP
+.BI \-a \ number
+Alpha factor that determines embedding strength of the signature.
+Allows to override the setting in the signature file.
+.TP
+.BI \-e \ number
+Wavelet filtering method for forward transformation.
+Allows to override the setting in the signature file.
+.TP
+.BI \-f \ number
+Wavelet filter number.
+Allows to override the setting in the signature file.
+.TP
+.BI \-F \ ffile
+Wavelet filter definition file.
+Allows to override the setting in the signature file.
+.TP
+.BI \-g \ number
+Wavelet filtering method for inverse transformation.
+Allows to override the setting in the signature file.
+.TP
+.B \-h
+Print a help message.
+.TP
+.BI \-i \ ifile
+The original image.
+.TP
+.BI \-o \ ofile
+Output watermarked image to the specified
+.I file
+instead of standard output.
+.TP
+.BI \-q \ number
+Set quantization/quality factor. Overrides the setting in the signature
+file.
+.TP
+.BI \-v \ number
+Verbosity level. Default value: 0.
+.TP
+.BI \-s \ sfile
+The signature file to embed into the input image. See
+.B gen_corvi_sig
+(1) for a description of the file format. Mandatory parameter.
+.IR file
+Input image in PGM format to sign (watermark). Default: standard input.
+.TP
+.I file
+The watermarked image in PGM format.
+.PP
+.SH OUTPUT
+The signed (watermarked) image in PGM format is written to standard output
+or, optionally, to
+.I ofile.
+.PP
+The output file has the following format:
+.TP
+.B CVSG
+Magic to identify file type.
+.TP
+.I number
+The length of the signature in bits.
+.TP
+.I number
+The alpha factor (embedding strength).
+.TP
+.I number
+The quantization/quality factor.
+.TP
+.I number
+The wavelet forward transform filtering method.
+.TP
+.I number
+The wavelet filter number.
+.TP
+.I file
+The wavelet filter definition file name.
+.TP
+.I number
+The wavelet inverse transform filtering method.
+.TP
+.I numbers
+The actual normal distributed signature values, one per line.
+.PP
+.SH AUTHOR
+Peter Meerwald <pmeerw@cosy.sbg.ac.at>
+Email bug reports to pmeerw@cosy.sbg.ac.at.
+.SH AVAILABILITY
+The most recent released version of
+.B wm_corvi_d
+is always available
+at http://www.cosy.sbg.ac.at/~pmeerw/Watermarking or via anonymous ftp from ftp.cosy.sbg.ac.at in the
+directory /pub/people/pmeerw/Watermarking.
+.SH "SEE ALSO"
+.BR gen_corvi_sig
+(1),
+.BR wm_corvi_e
+(1),
+.BR wm_corvi_s
+(1), 
+.BR cmp_corvi_sig
+(1)
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Meerwald/wm_corvi_d.c	Sun Aug 12 13:14:34 2007 +0200
@@ -0,0 +1,310 @@
+#include "dwt.h"
+#include "pgm.h"
+
+char *progname;
+
+void usage(void) {
+  fprintf(stderr, "usage: %s [-a n] [-h] [-n n] [-o file] [-s file] [-v n] -i file file\n\n", progname);
+  fprintf(stderr, "\t-a n\t\talpha factor\n");
+  fprintf(stderr, "\t-e n\t\twavelet filtering method\n");
+  fprintf(stderr, "\t-f n\t\tfilter number\n");
+  fprintf(stderr, "\t-F file\t\tfilter definition file\n");
+  fprintf(stderr, "\t-h\t\tprint usage\n");
+  fprintf(stderr, "\t-i file\t\toriginal image file\n");
+  fprintf(stderr, "\t-n n\t\twatermark length\n");
+  fprintf(stderr, "\t-o file\t\textracted signature file\n");
+  fprintf(stderr, "\t-s file\t\toriginal signature file\n");
+  fprintf(stderr, "\t-v n\t\tverbosity level\n");
+  exit(0);
+}
+
+int main(int argc, char *argv[]) {
+
+  FILE *in = stdin;
+  FILE *out = stdout;
+  FILE *orig = NULL;
+  FILE *sig = NULL;
+
+  gray **input_image;
+  gray **orig_image;
+
+  char signature_name[MAXPATHLEN];
+  char output_name[MAXPATHLEN] = "(stdout)";
+  char input_name[MAXPATHLEN] = "(stdin)";
+  char orig_name[MAXPATHLEN];
+
+  int c;
+  int i;
+  int n = 0;
+  int method = -1;
+  int filter = 0;
+  char filter_name[MAXPATHLEN] = "";
+
+  int level;
+  double alpha = 0.0;
+
+  int in_rows, in_cols, in_format;
+  gray in_maxval;
+  int orig_rows, orig_cols, orig_format;
+  gray orig_maxval;
+  int rows, cols;
+  int row, col;
+
+  Image_tree input_dwts;
+  Image_tree orig_dwts;
+
+  int verbose = 0;
+
+  progname = argv[0];
+
+  pgm_init(&argc, argv); wm_init2();
+
+  while ((c = getopt(argc, argv, "a:e:f:F:h?i:n:o:s:v:")) != EOF) {
+    switch (c) {
+      case 'a':
+        alpha = atof(optarg);
+        if (alpha <= 0.0) {
+          fprintf(stderr, "%s: alpha factor %f out of range\n", progname, alpha);
+          exit(1);
+        }
+        break;
+      case 'e':
+        method = atoi(optarg);
+        if (method < 0) {
+          fprintf(stderr, "%s: wavelet filtering method %d out of range\n", progname, method);
+          exit(1);
+        }
+        break;
+      case 'f':
+        filter = atoi(optarg);
+        if (filter <= 0) {
+          fprintf(stderr, "%s: filter number %d out of range\n", progname, filter);
+          exit(1);
+        }
+        break;
+      case 'F':
+        strcpy(filter_name, optarg);
+        break;
+      case 'h':
+      case '?':
+        usage();
+        break;
+      case 'i':
+        if ((orig = fopen(optarg, "rb")) == NULL) {
+          fprintf(stderr, "%s: unable to open original image file %s\n", progname, optarg);
+          exit(1);
+        }
+        strcpy(orig_name, optarg);
+        break;
+      case 'n':
+        n = atoi(optarg);
+        if (n < 1 || n > 1000) {
+          fprintf(stderr, "%s: watermark length %d out of range\n", progname, n);
+          exit(1);
+        }
+        break;
+      case 'o':
+        if ((out = fopen(optarg, "w")) == NULL) {
+          fprintf(stderr, "%s: unable to open output file %s\n", progname, optarg);
+          exit(1);
+        }
+        strcpy(output_name, optarg);
+        break;
+      case 's':
+        if ((sig = fopen(optarg, "r")) == NULL) {
+          fprintf(stderr, "%s: unable to open signature file %s\n", progname, optarg);
+          exit(1);
+        }
+        strcpy(signature_name, optarg);
+        break;
+      case 'v':
+        verbose = atoi(optarg);
+        if (verbose < 0) {
+          fprintf(stderr, "%s: verbosity level %d out of range\n", progname, verbose);
+          exit(1);
+        }
+        break;
+    }
+  }
+
+  argc -= optind;
+  argv += optind;
+
+  if (argc > 1) {
+    usage();
+    exit(1);
+  }
+
+  if (argc == 1 && *argv[0] != '-')
+    if ((in = fopen(argv[0], "rb")) == NULL) {
+      fprintf(stderr, "%s: unable to open input file %s\n", progname, argv[0]);
+      exit(1);
+    }
+    else
+      strcpy(input_name, argv[0]);
+
+  if (!orig) {
+    fprintf(stderr, "%s: original image file not specified, use -i file option\n", progname);
+    exit(1);
+  }
+
+  if (sig) {
+    char line[32];
+    fgets(line, sizeof(line), sig);
+    if (strspn(line, "CVSG") >= 4) {
+      fscanf(sig, "%d\n", &n);
+      if (alpha == 0.0)
+        fscanf(sig, "%lf\n", &alpha);
+      else
+        fscanf(sig, "%*lf\n");
+      if (method < 0)
+        fscanf(sig, "%d\n", &method);
+      else
+        fscanf(sig, "%*d\n");
+      if (filter == 0)
+        fscanf(sig, "%d\n", &filter);
+      else
+        fscanf(sig, "%*d\n");
+      if (!strcmp(filter_name, ""))
+        fscanf(sig, "%[^\n\r]\n", &filter_name);
+      else
+        fscanf(sig, "%*[^\n\r]\n");
+    }
+    else {
+      fprintf(stderr, "%s: invalid signature file %s\n", progname, signature_name);
+      exit(1);
+    }
+    fclose(sig);
+  }
+  else {
+    fprintf(stderr, "%s: signature file not specified, use -s file option\n", progname);
+    exit(1);
+  }
+
+  pgm_readpgminit(in, &in_cols, &in_rows, &in_maxval, &in_format);
+  pgm_readpgminit(orig, &orig_cols, &orig_rows, &orig_maxval, &orig_format);
+
+  if (in_cols != orig_cols || in_rows != orig_rows) {
+    fprintf(stderr, "%s: input image %s does not match dimensions of original image %s\n", progname, input_name, orig_name);
+    exit(1);
+  }
+
+  cols = in_cols;
+  rows = in_rows;
+
+  input_image = pgm_allocarray(in_cols, in_rows);
+
+  orig_image = pgm_allocarray(orig_cols, orig_rows);
+
+  for (row = 0; row < in_rows; row++)
+    pgm_readpgmrow(in, input_image[row], in_cols, in_maxval, in_format);
+
+  fclose(in);
+
+  for (row = 0; row < orig_rows; row++)
+    pgm_readpgmrow(orig, orig_image[row], orig_cols, orig_maxval, orig_format);
+
+  fclose(orig);
+
+  level = 0;
+  row = rows;
+  col = cols;
+  while (n < row * col / 4.0 && row >= 2 && col >= 2) {
+    row /= 2;
+    col /= 2;
+    level++;
+  }
+
+  if (verbose >= 2) {
+    fprintf(stderr, "%s: extracting from coarse image (x %d/y %d) at level %d\n", progname, col, row, level);
+  }
+
+  init_dwt(cols, rows, filter_name, filter, level, method);
+#ifdef POLLEN_STUFF
+#include "pollen_stuff.xxx"
+#endif
+#ifdef PARAM_STUFF
+#include "param_stuff.xxx"
+#endif
+
+  input_dwts = fdwt(input_image);
+  orig_dwts = fdwt(orig_image);
+
+  fprintf(out, "CVWM\n");
+  fprintf(out, "%d\n", n);
+
+  {
+    Image_tree p = input_dwts;
+    Image_tree q = orig_dwts;
+    Image input_img;
+    Image orig_img;
+    double input_med;
+    double orig_med;
+    double input_var;
+    double orig_var;
+
+    while (!p->image)
+      p = p->coarse;
+
+    while (!q->image)
+      q = q->coarse;
+
+    input_img = p->image;
+    orig_img = q->image;
+
+    input_med = 0.0;
+    for (row = 0; row < input_img->height; row++)
+      for (col = 0; col < input_img->width; col++)
+        input_med += get_pixel(input_img, col, row);
+    input_med /= (double) (input_img->height * input_img->width);
+
+    orig_med = 0.0;
+    for (row = 0; row < orig_img->height; row++)
+      for (col = 0; col < orig_img->width; col++)
+        orig_med += get_pixel(orig_img, col, row);
+    orig_med /= (double) (orig_img->height * orig_img->width);
+
+    orig_var = 0.0;
+    for (row = 0; row < orig_img->height; row++)
+      for (col = 0; col < orig_img->width; col++)
+        orig_var += sqr(get_pixel(orig_img, col, row) - orig_med);
+    orig_var /= (double) (orig_img->height * orig_img->width);
+
+    input_var = 0.0;
+    for (row = 0; row < input_img->height; row++)
+      for (col = 0; col < input_img->width; col++)
+        input_var += sqr(get_pixel(input_img, col, row) - input_med);
+    input_var /= (double) (input_img->height * input_img->width);
+
+    orig_var = sqrt(orig_var);
+    input_var = sqrt(input_var);
+
+    if (verbose > 3)
+      fprintf(stderr, "%s: mean (input, orig): %f, %f,\n  variance (input, orig): %f, %f\n", progname, input_med, orig_med, input_var, orig_var);
+
+    row = 0;
+    col = 0;
+    while (n > 0) {
+      double input_pix;
+      double orig_pix;
+      double x;
+
+      input_pix = get_pixel(input_img, col, row);
+      orig_pix = get_pixel(orig_img, col, row);
+
+      x = (((input_pix - input_med) * (orig_var / input_var) - (orig_pix / orig_med)) / (orig_pix - orig_med) - 1.0) / alpha;
+
+      fprintf(out, "%f\n", x);
+
+      if (++col == orig_img->width) { col = 0; row++; }
+      n--;
+    }
+  }
+
+  fclose(out);
+
+  pgm_freearray(input_image, rows);
+  pgm_freearray(orig_image, rows);
+
+  exit(0);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Meerwald/wm_corvi_e.1	Sun Aug 12 13:14:34 2007 +0200
@@ -0,0 +1,142 @@
+.\"
+.\" wm_corvi_e.1 - the *roff document processor man page source
+.\"
+.TH wm_corvi_e 1 "98/07/29" "Watermarking, Version 1.0"
+.SH NAME
+.B wm_corvi_e
+\- a program to embed a signature in the DWT residue of an image
+.SH SYNOPSIS
+.B wm_corvi_e
+[
+.BI \-a \ number
+]
+[
+.BI \-e \ number
+]
+[
+.BI \-f \ number
+]
+[
+.BI \-F \ ffile
+]
+[
+.BI \-g \ number
+]
+[
+.B \-h
+]
+[
+.BI \-o \ ofile
+]
+.br
+[
+.BI \-q \ number
+]
+[
+.BI \-v \ number
+]
+.BI \-s \ sfile
+.I file
+.SH DESCRIPTION
+.B wm_corvi_e
+is a program to embed a signature (watermark) from
+.I sfile
+into the DWT residue of an image
+.I file
+and output a signed (watermarked) image
+.I ofile.
+Both, input and output image,
+are in PGM (portable graymap) format.
+.PP
+If
+.I file
+or
+.I ofile
+is not specified, then standard input or standard output is
+used. The signature
+.I sfile
+is a mandatory parameter however.
+.PP
+.B gen_corvi_sig
+is used to generate a signature file,
+.B wm_corvi_d
+extracts a signature from a watermarked image and
+.B cmp_corvi_sig
+allows to compare and test an extracted watermark against the original
+signature.
+.PP
+Please refer to Marco Corvi's paper "Wavelet-based image watermarking
+for copyright protection", to get an idea about the algorithm.
+.PP
+.SH OPTIONS
+.TP
+.BI \-a \ number
+Alpha factor that determines embedding strength of the signature.
+Allows to override the setting in the signature file.
+.TP
+.BI \-e \ number
+Wavelet filtering method for forward transformation. 
+Allows to override the setting in the signature file.
+.TP
+.BI \-f \ number
+Wavelet filter number. 
+Allows to override the setting in the signature file.
+.TP
+.BI \-F \ ffile
+Wavelet filter definition file.
+Allows to override the setting in the signature file.
+.TP
+.BI \-g \ number
+Wavelet filtering method for inverse transformation. 
+Allows to override the setting in the signature file.
+.TP
+.B \-h
+Print a help message.
+.TP
+.BI \-o \ ofile
+Output watermarked image to the specified
+.I file
+instead of standard output.
+.TP
+.BI \-q \ number
+Set quantization/quality factor. Overrides the setting in the signature
+file.
+.TP
+.BI \-s \ sfile
+The signature file to embed into the input image. See
+.B gen_corvi_sig
+(1) for a description of the file format. Mandatory parameter.
+.IR file
+Input image in PGM format to sign (watermark). Default: standard input.
+.TP
+.BI \-v \ number
+Verbosity level. Specify higher numbers for more informatative
+output. Default value: 0.
+.TP
+.I file
+The image in PGM format to be watermarked.
+.PP
+.SH OUTPUT
+The signed (watermarked) image in PGM format is written to standard output
+or, optionally, to
+.I ofile.
+The length of the signature (watermark) determines the level of the 
+image residue (coarse image) where the signature is embedded.
+.PP
+.SH AUTHOR
+Peter Meerwald. Email bug reports to pmeerw@cosy.sbg.ac.at.
+.SH AVAILABILITY
+The most recent released version of
+.B wm_corvi_e
+is always available
+at http://www.cosy.sbg.ac.at/~pmeerw/Watermarking or via anonymous ftp from ftp.cosy.sbg.ac.at in the
+directory /pub/people/pmeerw/Watermarking.
+.SH "SEE ALSO"
+.BR gen_corvi_sig
+(1),
+.BR wm_corvi_d
+(1),
+.BR wm_corvi_s
+(1),
+.BR cmp_corvi_sig
+(1)
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Meerwald/wm_corvi_e.c	Sun Aug 12 13:14:34 2007 +0200
@@ -0,0 +1,236 @@
+#include "wm.h"
+#include "dwt.h"
+#include "pgm.h"
+
+char *progname;
+
+void usage(void) {
+  fprintf(stderr, "usage: %s [-a n] [-e n] [-f n] [-F n] [-h] [-o file] [-v n] -s file file\n\n", progname);
+  fprintf(stderr, "\t-a n\t\talpha factor/embedding strength\n");
+  fprintf(stderr, "\t-e n\t\twavelet filtering method\n");
+  fprintf(stderr, "\t-f n\t\tfilter number\n");
+  fprintf(stderr, "\t-F file\t\tfilter definition file\n");
+  fprintf(stderr, "\t-h\t\tprint usage\n");
+  fprintf(stderr, "\t-o file\t\toutput (watermarked) file\n");
+  fprintf(stderr, "\t-s file\t\tsignature to embed in input image\n");
+  fprintf(stderr, "\t-v n\t\tverbosity level\n");
+  exit(0);
+}
+
+int main(int argc, char *argv[]) {
+
+  FILE *in = stdin;
+  FILE *out = stdout;
+  FILE *sig = NULL;
+
+  char output_name[MAXPATHLEN] = "(stdout)";
+  char input_name[MAXPATHLEN] = "(stdin)";
+  char signature_name[MAXPATHLEN];
+
+  int c;
+  int row, col;
+
+  int n;
+
+  double alpha = 0.0;
+
+  int filter = 0;
+  int method = -1;
+  int level;
+  char filter_name[MAXPATHLEN] = "";
+
+  int verbose = 0;
+
+  gray **image;
+  Image_tree dwts;
+
+  gray maxval;
+  int rows, cols, colors, format;
+
+  progname = argv[0];
+
+  pgm_init(&argc, argv); wm_init();
+
+  while ((c = getopt(argc, argv, "a:e:f:F:h?o:s:v:")) != EOF) {
+    switch (c) {
+      case 'a':
+        alpha = atof(optarg);
+        if (alpha <= 0.0) {
+          fprintf(stderr, "%s: alpha factor %f out of range\n", progname, alpha);
+          exit(1);
+        }
+        break;
+      case 'e':
+        method = atoi(optarg);
+        if (method < 0) {
+          fprintf(stderr, "%s: wavelet filtering method %d out of range\n", progname, method);
+          exit(1);
+        }
+        break;
+      case 'f':
+        filter = atoi(optarg);
+        if (filter <= 0) {
+          fprintf(stderr, "%s: filter number %d out of range\n", progname, filter);
+          exit(1);
+        }
+        break;
+      case 'F':
+        strcpy(filter_name, optarg);
+        break;
+      case 'h':
+      case '?':
+        usage();
+        break;
+      case 'o':
+        if ((out = fopen(optarg, "wb")) == NULL) {
+          fprintf(stderr, "%s: unable to open output file %s\n", progname, optarg);
+          exit(1);
+        }
+        strcpy(output_name, optarg);
+        break;
+      case 's':
+        if ((sig = fopen(optarg, "r")) == NULL) {
+          fprintf(stderr, "%s: unable to open signature file %s\n", progname, optarg);
+          exit(1);
+        }
+        strcpy(signature_name, optarg);
+        break;
+      case 'v':
+        verbose = atoi(optarg);
+        if (verbose < 0) {
+          fprintf(stderr, "%s: verbosity level %d out of range\n", progname, verbose);
+          exit(1);
+        }
+        break;
+    }
+  }
+
+  argc -= optind;
+  argv += optind;
+
+  if (argc > 1) {
+    usage();
+    exit(1);
+  }
+
+  if (argc == 1 && *argv[0] != '-')
+    if ((in = fopen(argv[0], "rb")) == NULL) {
+      fprintf(stderr, "%s: unable to open input file %s\n", progname, argv[0]);
+      exit(1);
+    }
+    else
+      strcpy(input_name, argv[0]);
+
+  if (sig) {
+    char line[32];
+    fgets(line, sizeof(line), sig);
+    if (strspn(line, "CVSG") >= 4) {
+      fscanf(sig, "%d\n", &n);
+      if (alpha == 0.0)
+        fscanf(sig, "%lf\n", &alpha);
+      else
+        fscanf(sig, "%*lf\n");
+      if (method < 0)
+        fscanf(sig, "%d\n", &method);
+      else
+        fscanf(sig, "%*d\n");
+      if (filter == 0)
+        fscanf(sig, "%d\n", &filter);
+      else
+        fscanf(sig, "%*d\n");
+      if (!strcmp(filter_name, ""))
+        fscanf(sig, "%[^\n\r]\n", &filter_name);
+      else
+        fscanf(sig, "%*[^\n\r]\n");
+    }
+    else {
+      fprintf(stderr, "%s: invalid signature file %s\n", progname, signature_name);
+      exit(1);
+    }
+  }
+  else {
+    fprintf(stderr, "%s: signature file not specified, use -s file option\n", progname);
+    exit(1);
+  }
+
+  pgm_readpgminit(in, &cols, &rows, &maxval, &format);
+
+  image = pgm_allocarray(cols, rows);
+
+  for (row = 0; row < rows; row++)
+    pgm_readpgmrow(in, image[row], cols, maxval, format);
+
+  fclose(in);
+
+  level = 0;
+  row = rows;
+  col = cols;
+  while (n < row * col / 4.0 && row >= 2 && col >= 2) {
+    row /= 2;
+    col /= 2;
+    level++;
+  }
+
+  if (verbose >= 2) {
+    fprintf(stderr, "%s: embedding into coarse image (x %d/y %d) at level %d\n", progname, col, row, level);
+  }
+
+  init_dwt(cols, rows, filter_name, filter, level, method);
+#ifdef POLLEN_STUFF
+#include "pollen_stuff.xxx"
+#endif
+#ifdef PARAM_STUFF
+#include "param_stuff.xxx"
+#endif
+
+  dwts = fdwt(image);
+
+  {
+    Image_tree p = dwts;
+    Image img;
+    double med;
+
+    while (!p->image)
+      p = p->coarse;
+
+    img = p->image;
+
+    med = 0.0;
+    for (row = 0; row < img->height; row++)
+      for (col = 0; col < img->width; col++)
+        med += get_pixel(img, col, row);
+
+    med /= (double) (img->height * img->width);
+
+    row = 0;
+    col = 0;
+    while (n > 0) {
+      double pix;
+      double g;
+
+      fscanf(sig, "%lf\n", &g);
+
+      pix = get_pixel(img, col, row);
+      pix = med + (pix - med) * (1.0 + alpha * g);
+      set_pixel(img, col, row, pix);
+
+      if (++col == img->width) { col = 0; row++; }
+      n--;
+    }
+  }
+
+  fclose(sig);
+
+  idwt(dwts, image);
+
+  pgm_writepgminit(out, cols, rows, maxval, 0);
+
+  for (row = 0; row < rows; row++)
+    pgm_writepgmrow(out, image[row], cols, maxval, 0);
+
+  fclose(out);
+
+  pgm_freearray(image, rows);
+
+  exit(0);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Meerwald/wm_corvi_s.1	Sun Aug 12 13:14:34 2007 +0200
@@ -0,0 +1,171 @@
+.\"
+.\" wm_corvi_s.1 - the *roff document processor man page source
+.\"
+.TH wm_corvi_s 1 "98/07/29" "Watermarking, Version 1.0"
+.SH NAME
+.B wm_corvi_s
+\- a program to extract a signature from the DWT residue of a watermarked
+image
+.SH SYNOPSIS
+.B wm_corvi_s
+[
+.BI \-a \ number
+]
+[
+.BI \-e \ number
+]
+[
+.BI \-f \ number
+]
+[
+.BI \-F \ ffile
+]
+[
+.BI \-g \ number
+]
+[
+.B \-h
+]
+[
+.BI \-i \ ifile
+]
+.br
+[
+.BI \-n \ number
+]
+[
+.BI \-o \ ofile
+]
+[
+.BI \-q \ number
+]
+[
+.BI \-v \ number
+]
+.BI \-s \ sfile
+.I file
+.SH DESCRIPTION
+.B wm_corvi_s
+is a program to extract a signature from the DWT residue of
+a watermarked image
+.I file.
+The
+.B cmp_corvi_sig
+program is used to test the extracted signature against the original signature.
+The input image is in PGM (portable graymap) format.
+.PP
+If
+.I file
+or
+.I ofile
+is not specified, then standard input or standard output is
+used.
+.PP
+.B gen_corvi_sig
+is used to generate a signature file,
+.B wm_corvi_e
+embeds the signature into an image.
+.PP
+Please refer to Marco Corvi's paper "Wavelet-based image watermarking
+for copyright protection", to get an idea about the algorithm.
+.PP
+.SH OPTIONS
+.TP
+.BI \-a \ number
+Alpha factor that determines embedding strength of the signature.
+Allows to override the setting in the signature file.
+.TP
+.BI \-e \ number
+Wavelet filtering method for forward transformation.
+Allows to override the setting in the signature file.
+.TP
+.BI \-f \ number
+Wavelet filter number.
+Allows to override the setting in the signature file.
+.TP
+.BI \-F \ ffile
+Wavelet filter definition file.
+Allows to override the setting in the signature file.
+.TP
+.BI \-g \ number
+Wavelet filtering method for inverse transformation.
+Allows to override the setting in the signature file.
+.TP
+.B \-h
+Print a help message.
+.TP
+.BI \-i \ ifile
+The original image.
+.TP
+.BI \-o \ ofile
+Output watermarked image to the specified
+.I file
+instead of standard output.
+.TP
+.BI \-q \ number
+Set quantization/quality factor. Overrides the setting in the signature
+file.
+.TP
+.BI \-v \ number
+Verbosity level. Default value: 0.
+.TP
+.BI \-s \ sfile
+The signature file to embed into the input image. See
+.B gen_corvi_sig
+(1) for a description of the file format. Mandatory parameter.
+.IR file
+Input image in PGM format to sign (watermark). Default: standard input.
+.TP
+.I file
+The watermarked image in PGM format.
+.PP
+.SH OUTPUT
+The signed (watermarked) image in PGM format is written to standard output
+or ,optionally, to
+.I ofile.
+.PP
+The output file has the following format:
+.TP
+.B CVSG
+Magic to identify file type.
+.TP
+.I number
+The length of the signature in bits.
+.TP
+.I number
+The alpha factor (embedding strength).
+.TP
+.I number
+The quantization/quality factor.
+.TP
+.I number
+The wavelet forward transform filtering method.
+.TP
+.I number
+The wavelet filter number.
+.I file
+The wavelet filter definition file name.
+.TP
+.I number
+The wavelet inverse transform filtering method.
+.TP
+.I numbers
+The actual normal distributed signature values, one per line.
+.PP
+.SH AUTHOR
+Peter Meerwald. Email bug reports to pmeerw@cosy.sbg.ac.at.
+.SH AVAILABILITY
+The most recent released version of
+.B wm_corvi_s
+is always available
+at http://www.cosy.sbg.ac.at/~pmeerw/Watermarking or via anonymous ftp from ftp.cosy.sbg.ac.at in the
+directory /pub/people/pmeerw/Watermarking.
+.SH "SEE ALSO"
+.BR gen_corvi_sig
+(1),
+.BR wm_corvi_e
+(1),
+.BR wm_corvi_d
+(1),
+.BR cmp_corvi_sig
+(1)
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Meerwald/wm_corvi_s.c	Sun Aug 12 13:14:34 2007 +0200
@@ -0,0 +1,295 @@
+#include "wm.h"
+#include "wm_dwt.h"
+#include "pgm.h"
+
+char *progname;
+
+void usage(void) {
+  fprintf(stderr, "usage: %s [-a n] [-h] [-n n] [-o file] [-q n] [-s file] [-v n] -i file file\n\n", progname);
+  fprintf(stderr, "\t-a n\t\talpha factor\n");
+  fprintf(stderr, "\t-e n\t\twavelet filtering method\n");
+  fprintf(stderr, "\t-f n\t\tfilter number\n");
+  fprintf(stderr, "\t-F file\t\tfilter definition file\n");
+  fprintf(stderr, "\t-h\t\tprint usage\n");
+  fprintf(stderr, "\t-i file\t\toriginal image file\n");
+  fprintf(stderr, "\t-n n\t\twatermark length\n");
+  fprintf(stderr, "\t-o file\t\textracted signature file\n");
+  fprintf(stderr, "\t-q n\t\tquantization/quality factor\n");
+  fprintf(stderr, "\t-s file\t\toriginal signature file\n");
+  fprintf(stderr, "\t-v n\t\tverbosity level\n");
+  exit(0);
+}
+
+int main(int argc, char *argv[]) {
+
+  FILE *in = stdin;
+  FILE *out = stdout;
+  FILE *orig = NULL;
+  FILE *sig = NULL;
+
+  gray **input_image;
+  gray **orig_image;
+
+  char signature_name[MAXPATHLEN];
+  char output_name[MAXPATHLEN] = "(stdout)";
+  char input_name[MAXPATHLEN] = "(stdin)";
+  char orig_name[MAXPATHLEN];
+
+  int c;
+  int i;
+  int quantization = 0;
+  int n = 0;
+  int method = -1;
+  int filter = 0;
+  char filter_name[MAXPATHLEN] = "";
+
+  int level;
+  double alpha = 0.0;
+
+  int in_rows, in_cols, in_format;
+  gray in_maxval;
+  int orig_rows, orig_cols, orig_format;
+  gray orig_maxval;
+  int rows, cols;
+  int row, col;
+
+  Image_tree input_dwts;
+  Image_tree orig_dwts;
+
+  int verbose = 0;
+
+  progname = argv[0];
+
+  pgm_init(&argc, argv); wm_init2();
+
+  while ((c = getopt(argc, argv, "a:e:f:F:h?i:n:o:s:v:")) != EOF) {
+    switch (c) {
+      case 'a':
+        alpha = atof(optarg);
+        if (alpha <= 0.0) {
+          fprintf(stderr, "%s: alpha factor %f out of range\n", progname, alpha);
+          exit(1);
+        }
+        break;
+      case 'e':
+        method = atoi(optarg);
+        if (method < 0) {
+          fprintf(stderr, "%s: wavelet filtering method %d out of range\n", progname, method);
+          exit(1);
+        }
+        break;
+      case 'f':
+        filter = atoi(optarg);
+        if (filter <= 0) {
+          fprintf(stderr, "%s: filter number %d out of range\n", progname, filter);
+          exit(1);
+        }
+        break;
+      case 'F':
+        strcpy(filter_name, optarg);
+        break;
+      case 'h':
+      case '?':
+        usage();
+        break;
+      case 'i':
+        if ((orig = fopen(optarg, "rb")) == NULL) {
+          fprintf(stderr, "%s: unable to open original image file %s\n", progname, optarg);
+          exit(1);
+        }
+        strcpy(orig_name, optarg);
+        break;
+      case 'n':
+        n = atoi(optarg);
+        if (n < 1 || n > 1000) {
+          fprintf(stderr, "%s: watermark length %d out of range\n", progname, n);
+          exit(1);
+        }
+        break;
+      case 'o':
+        if ((out = fopen(optarg, "w")) == NULL) {
+          fprintf(stderr, "%s: unable to open output file %s\n", progname, optarg);
+          exit(1);
+        }
+        strcpy(output_name, optarg);
+        break;
+      case 's':
+        if ((sig = fopen(optarg, "r")) == NULL) {
+          fprintf(stderr, "%s: unable to open signature file %s\n", progname, optarg);
+          exit(1);
+        }
+        strcpy(signature_name, optarg);
+        break;
+      case 'v':
+        verbose = atoi(optarg);
+        if (verbose < 0) {
+          fprintf(stderr, "%s: verbosity level %d out of range\n", progname, verbose);
+          exit(1);
+        }
+        break;
+    }
+  }
+
+  argc -= optind;
+  argv += optind;
+
+  if (argc > 1) {
+    usage();
+    exit(1);
+  }
+
+  if (argc == 1 && *argv[0] != '-')
+    if ((in = fopen(argv[0], "rb")) == NULL) {
+      fprintf(stderr, "%s: unable to open input file %s\n", progname, argv[0]);
+      exit(1);
+    }
+    else
+      strcpy(input_name, argv[0]);
+
+  if (!orig) {
+    fprintf(stderr, "%s: original image file not specified, use -i file option\n", progname);
+    exit(1);
+  }
+
+  if (sig) {
+    char line[32];
+    fgets(line, sizeof(line), sig);
+    if (strspn(line, "CVSG") >= 4) {
+      fscanf(sig, "%d\n", &n);
+      if (alpha == 0.0)
+        fscanf(sig, "%lf\n", &alpha);
+      else
+        fscanf(sig, "%*lf\n");
+      if (quantization == 0)
+        fscanf(sig, "%d\n", &quantization);
+      else
+        fscanf(sig, "%*d\n");
+      if (method < 0)
+        fscanf(sig, "%d\n", &method);
+      else
+        fscanf(sig, "%*d\n");
+      if (filter == 0)
+        fscanf(sig, "%d\n", &filter);
+      else
+        fscanf(sig, "%*d\n");
+      if (!strcmp(filter_name, ""))
+        fscanf(sig, "%[^\n\r]\n", &filter_name);
+      else
+        fscanf(sig, "%*[^\n\r]\n");
+    }
+    else {
+      fprintf(stderr, "%s: invalid signature file %s\n", progname, signature_name);
+      exit(1);
+    }
+    fclose(sig);
+  }
+  else {
+    fprintf(stderr, "%s: signature file not specified, use -s file option\n", progname);
+    exit(1);
+  }
+
+  pgm_readpgminit(in, &in_cols, &in_rows, &in_maxval, &in_format);
+  pgm_readpgminit(orig, &orig_cols, &orig_rows, &orig_maxval, &orig_format);
+
+  if (in_cols != orig_cols || in_rows != orig_rows) {
+    fprintf(stderr, "%s: input image %s does not match dimensions of original image %s\n", progname, input_name, orig_name);
+    exit(1);
+  }
+
+  cols = in_cols;
+  rows = in_rows;
+
+  input_image = pgm_allocarray(in_cols, in_rows);
+
+  orig_image = pgm_allocarray(orig_cols, orig_rows);
+
+  for (row = 0; row < in_rows; row++)
+    pgm_readpgmrow(in, input_image[row], in_cols, in_maxval, in_format);
+
+  fclose(in);
+
+  for (row = 0; row < orig_rows; row++)
+    pgm_readpgmrow(orig, orig_image[row], orig_cols, orig_maxval, orig_format);
+
+  fclose(orig);
+
+  level = 0;
+  row = rows;
+  col = cols;
+  while (n < row * col / 4.0 && row >= 2 && col >= 2) {
+    row /= 2;
+    col /= 2;
+    level++;
+  }
+
+  if (verbose >= 2) {
+    fprintf(stderr, "%s: extracting from coarse image (x %d/y %d) at level %d\n", progname, col, row, level);
+  }
+
+  init_dwt(cols, rows, filter_name, filter, level, method);
+  input_dwts = fdwt(input_image);
+  orig_dwts = fdwt(orig_image);
+
+  fprintf(out, "CVSG\n");
+  fprintf(out, "%d\n", n);
+  fprintf(out, "%f\n", alpha);
+  fprintf(out, "%d\n", quantization);
+  fprintf(out, "%d\n", method);
+  fprintf(out, "%d\n", filter);
+  fprintf(out, "%s\n", filter_name);
+
+  {
+    Image_tree p = input_dwts;
+    Image_tree q = orig_dwts;
+    Image input_img;
+    Image orig_img;
+    double input_med;
+    double orig_med;
+
+    while (!p->image)
+      p = p->coarse;
+
+    while (!q->image)
+      q = q->coarse;
+
+    input_img = p->image;
+    orig_img = q->image;
+
+    input_med = 0.0;
+    for (row = 0; row < input_img->height; row++)
+      for (col = 0; col < input_img->width; col++)
+        input_med += get_pixel(input_img, col, row);
+    input_med /= input_img->height * input_img->width;
+
+    orig_med = 0.0;
+    for (row = 0; row < orig_img->height; row++)
+      for (col = 0; col < orig_img->width; col++)
+        orig_med += get_pixel(orig_img, col, row);
+    orig_med /= orig_img->height * orig_img->width;
+
+    row = 0;
+    col = 0;
+    while (n > 0) {
+      Pixel input_pix;
+      Pixel orig_pix;
+      double x;
+
+      input_pix = get_pixel(input_img, col, row);
+      orig_pix = get_pixel(orig_img, col, row);
+
+      x = ((input_pix - orig_pix) / (orig_pix - orig_med)) / alpha;
+
+      fprintf(out, "%f\n", x);
+
+      if (++col == orig_img->width) { col = 0; row++; }
+      n--;
+    }
+  }
+
+  fclose(out);
+
+  pgm_freearray(input_image, rows);
+  pgm_freearray(orig_image, rows);
+
+  exit(0);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Meerwald/wm_cox_d.1	Sun Aug 12 13:14:34 2007 +0200
@@ -0,0 +1,132 @@
+.\"
+.\" wm_cox_d.1 - the *roff document processor man page source
+.\"
+.TH wm_cox_d 1 "98/07/05" "Watermarking, Version 1.0"
+.SH NAME
+.B wm_cox_d
+\- a program to extract a signature from the DCT coefficients of a watermarked image
+.SH SYNOPSIS
+.B wm_cox_d
+[
+.BI \-a \ number
+]
+[
+.B \-h
+]
+[
+.BI \-i \ ifile
+]
+[
+.BI \-n \ number
+]
+[
+.BI \-o \ ofile
+]
+[
+.BI \-q \ number
+]
+[
+.BI \-v \ number
+]
+.br
+.BI \-s \ sfile
+.I file
+.SH DESCRIPTION
+.B wm_cox_d
+is a program to extract a signature from the DCT coefficients of the watermarked image
+.I file.
+The
+.B cmp_cox_sig
+program is used to test the extracted signature against the original signature.
+The input image is in PGM (portable graymap) format.
+.PP
+If
+.I file
+or
+.I ofile
+is not specified, then standard input or standard output is
+used.
+.PP
+.B gen_cox_sig
+is used to generate a signature file,
+.B wm_cox_e
+embeds the signature into an image.
+.PP
+Please refer to Ingemar J. Cox's paper "Secure Spread Spectrum
+Watermarking for Multimedia", 1995, to get an idea about the algorithm.
+.PP
+.SH OPTIONS
+.TP
+.BI \-a \ number
+Alpha factor that determines embedding strength of the signature.
+Allows to override the setting in the signature file.
+.TP
+.B \-h
+Print a help message.
+.TP
+.BI \-i \ ifile
+The original image.
+.TP
+.BI \-o \ ofile
+Output watermarked image to the specified
+.I file
+instead of standard output.
+.TP
+.BI \-q \ number
+Set quantization/quality factor. Overrides the setting in the signature
+file.
+.TP
+.BI \-v \ number
+Verbosity level. Default value: 0.
+.TP
+.BI \-s \ sfile
+The signature file to embed into the input image. See
+.B gen_cox_sig
+(1) for a description of the file format. Mandatory parameter.
+.IR file
+Input image in PGM format to sign (watermark). Default: standard input.
+.TP
+.I
+The watermarked image file in PGM format.
+.PP
+.SH OUTPUT
+The signed (watermarked) image in PGM format is written to standard output
+or ,optionally, to
+.I ofile.
+The embedding process may take some time on large images since the DCT
+is performed on the whole image in one step (not block-wise).
+.PP
+.PP
+The output file has the following format:
+.TP
+.B CXSG
+Magic to identify file type.
+.TP
+.I number
+The length of the signature in bits.
+.TP
+.I number
+The alpha factor (embedding strength).
+.TP
+.I number
+The quantization/quality factor.
+.TP
+.I numbers
+The actual normal distributed signature values, one per line.
+.PP
+.SH AUTHOR
+Peter Meerwald. 
+Email bug reports to pmeerw@cosy.sbg.ac.at.
+.SH AVAILABILITY
+The most recent released version of
+.B wm_cox_d
+is always available
+at http://www.cosy.sbg.ac.at/~pmeerw/Watermarking or via anonymous ftp from ftp.cosy.sbg.ac.at in the
+directory /pub/people/pmeerw/Watermarking.
+.SH "SEE ALSO"
+.BR gen_cox_sig
+(1),
+.BR wm_cox_e
+(1),
+.BR cmp_cox_sig
+(1)
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Meerwald/wm_cox_d.c	Sun Aug 12 13:14:34 2007 +0200
@@ -0,0 +1,227 @@
+#include "wm.h"
+#include "dct.h"
+#include "pgm.h"
+
+char *progname;
+
+void usage(void) {
+  fprintf(stderr, "usage: %s [-a n] [-h] [-n n] [-o file] [-s file] [-v n] -i file file\n\n", progname);
+  fprintf(stderr, "\t-a n\t\talpha factor (default 0.3)\n");
+  fprintf(stderr, "\t-h\t\tprint usage\n");
+  fprintf(stderr, "\t-i file\t\toriginal image file\n");
+  fprintf(stderr, "\t-n n\t\twatermark length (default 100)\n");
+  fprintf(stderr, "\t-o file\t\textracted signature file\n");
+  fprintf(stderr, "\t-s file\t\toriginal signature file\n");
+  fprintf(stderr, "\t-v n\t\tverbosity level\n");
+  exit(0);
+}
+
+int main(int argc, char *argv[]) {
+
+  FILE *in = stdin;
+  FILE *out = stdout;
+  FILE *orig = NULL;
+  FILE *sig = NULL;
+
+  gray **input_image;
+  gray **orig_image;
+
+  char signature_name[MAXPATHLEN];
+  char output_name[MAXPATHLEN] = "(stdout)";
+  char input_name[MAXPATHLEN] = "(stdin)";
+  char orig_name[MAXPATHLEN];
+
+  int c;
+  int r;
+  int i, j;
+  int n = 100;
+
+  double a = 0.3;
+
+  int warn_n = 1;
+  int warn_a = 1;
+
+  int in_rows, in_cols, in_format;
+  gray in_maxval;
+  int orig_rows, orig_cols, orig_format;
+  gray orig_maxval;
+  int rows, cols;
+  int row, col;
+
+  double threshold;
+  double *largest;
+
+  double **input_dcts;
+  double **orig_dcts;
+  
+  int verbose = 0;
+
+  progname = argv[0];
+
+  pgm_init(&argc, argv); wm_init2();
+
+  while ((c = getopt(argc, argv, "h?i:n:o:s:v:")) != EOF) {
+    switch (c) {
+      case 'a':
+        a = atof(optarg);
+        if (a <= 0.0) {
+          fprintf(stderr, "%s: alpha factor %f out of range\n", progname, a);
+          exit(1);
+        }
+        warn_a = 0;
+        break;
+      case 'h':
+      case '?':
+        usage();
+        break;
+      case 'i':
+        if ((orig = fopen(optarg, "rb")) == NULL) {
+          fprintf(stderr, "%s: unable to open original image file %s\n", progname, optarg);
+          exit(1);
+        }
+        strcpy(orig_name, optarg);
+        break;
+      case 'n':
+        n = atoi(optarg);
+        if (n < 1 || n > 1000) {
+          fprintf(stderr, "%s: watermark length %d out of range\n", progname, n);
+          exit(1);
+        }
+        warn_n = 0;
+        break;
+      case 'o':
+        if ((out = fopen(optarg, "w")) == NULL) {
+          fprintf(stderr, "%s: unable to open output file %s\n", progname, optarg);
+          exit(1);
+        }
+        strcpy(output_name, optarg);
+        break;
+      case 's':
+        if ((sig = fopen(optarg, "r")) == NULL) {
+          fprintf(stderr, "%s: unable to open signature file %s\n", progname, optarg);
+          exit(1);
+        }
+        strcpy(signature_name, optarg);
+        break;
+      case 'v':
+        verbose = atoi(optarg);
+        if (verbose < 0) {
+          fprintf(stderr, "%s: verbosity level %d out of range\n", progname, verbose);
+          exit(1);
+        }
+        break;
+    }
+  }
+
+  argc -= optind;
+  argv += optind;
+
+  if (argc > 1) {
+    usage();
+    exit(1);
+  }
+
+  if (argc == 1 && *argv[0] != '-')
+    if ((in = fopen(argv[0], "rb")) == NULL) {
+      fprintf(stderr, "%s: unable to open input file %s\n", progname, argv[0]);
+      exit(1);
+    }
+    else
+      strcpy(input_name, argv[0]);
+
+  if (!orig) {
+    fprintf(stderr, "%s: original image file not specified, use -i file option\n", progname);
+    exit(1);
+  }
+
+  if (sig) {
+    char line[32];
+    fgets(line, sizeof(line), sig);
+    if (strspn(line, "CXSG") >= 4) {
+      fscanf(sig, "%d\n", &n);
+      if (warn_a)
+        fscanf(sig, "%lf\n", &a);
+      else
+        fscanf(sig, "%*lf\n");
+      fscanf(sig, "%*lf\n");
+      fscanf(sig, "%*lf\n");
+    }
+    else {
+      fprintf(stderr, "%s: invalid signature file %s\n", progname, signature_name);
+      exit(1);
+    }
+    fclose(sig);
+  }
+  else {
+    if (warn_a)
+      fprintf(stderr, "%s: warning - alpha factor not specified, using default %f\n", progname, a);
+    if (warn_n)
+      fprintf(stderr, "%s: warning - watermark length not specified, using default %d\n", progname, n);
+  }
+
+  pgm_readpgminit(in, &in_cols, &in_rows, &in_maxval, &in_format);
+  pgm_readpgminit(orig, &orig_cols, &orig_rows, &orig_maxval, &orig_format);
+
+  if (in_cols != orig_cols || in_rows != orig_rows) {
+    fprintf(stderr, "%s: input image %s does not match dimensions of original image %s\n", progname, input_name, orig_name);
+    exit(1);
+  }
+
+  cols = in_cols;
+  rows = in_rows;
+
+  init_dct_NxN(cols, rows);
+
+  input_image = pgm_allocarray(in_cols, in_rows);
+
+  orig_image = pgm_allocarray(orig_cols, orig_rows);
+
+  for (row = 0; row < in_rows; row++)
+    pgm_readpgmrow(in, input_image[row], in_cols, in_maxval, in_format);
+
+  fclose(in);
+
+  for (row = 0; row < orig_rows; row++)
+    pgm_readpgmrow(orig, orig_image[row], orig_cols, orig_maxval, orig_format);
+
+  fclose(orig);
+
+  input_dcts = alloc_coeffs(cols, rows);
+  orig_dcts = alloc_coeffs(cols, rows);
+
+  fdct_NxN(input_image, input_dcts);
+  fdct_NxN(orig_image, orig_dcts);
+
+  largest = malloc((n + 1) * sizeof(double));
+  select_largest_coeffs(orig_dcts[0], cols * rows, n+1, largest);
+  threshold = largest[0];
+  free(largest);
+
+  fprintf(out, "CXWM\n");
+  fprintf(out, "%d\n", n);
+
+  j = 0;
+  for (i = 0; i < n; i++) {
+    double d, o, p;
+
+    while ((o = orig_dcts[j / cols][j % cols]) < threshold) j++;
+
+    p = input_dcts[j / cols][j % cols]; 
+ 
+    d = (p / o - 1.0) / a;
+    if (verbose >= 1)
+      fprintf(stderr, "input %f orig %f alpha %f d %f\n", p, o, a, d);
+    fprintf(out, "%f\n", d);
+    j++;
+  }
+
+  fclose(out);
+
+  free_coeffs(input_dcts);
+  free_coeffs(orig_dcts);
+
+  pgm_freearray(input_image, rows);
+  pgm_freearray(orig_image, rows);
+
+  exit(0);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Meerwald/wm_cox_e.1	Sun Aug 12 13:14:34 2007 +0200
@@ -0,0 +1,110 @@
+.\"
+.\" wm_cox_e.1 - the *roff document processor man page source
+.\"
+.TH wm_cox_e 1 "98/07/01" "Watermarking, Version 1.0"
+.SH NAME
+.B wm_cox_e
+\- a program to embed a signature in the DCT coefficients of an image
+.SH SYNOPSIS
+.B wm_cox_e
+[
+.BI \-a \ number
+]
+[
+.B \-h
+]
+[
+.BI \-o \ ofile
+]
+[
+.BI \-q \ number
+]
+.BI \-s \ sfile
+.I file
+.SH DESCRIPTION
+.B wm_cox_e
+is a program to embed a signature (watermark) from
+.I sfile
+into the DCT coefficients of an image
+.I file
+and output a signed (watermarked) image
+.I ofile.
+Both, input and output image,
+are in PGM (portable graymap) format.
+.PP
+If
+.I file
+or
+.I ofile
+is not specified, then standard input or standard output is
+used. The signature
+.I sfile
+is a mandatory parameter however.
+.PP
+.B gen_cox_sig
+is used to generate a signature file,
+.B wm_cox_d
+extracts a signature from a watermarked image and
+.B cmp_cox_sig
+allows to compare and test an extracted watermark against the original
+signature.
+.PP
+Please refer to Ingemar J. Cox's paper "Secure Spread Spectrum
+Watermarking for Multimedia", 1995, to get an idea about the algorithm.
+.PP
+.SH OPTIONS
+.TP
+.BI \-a \ number
+Alpha factor that determines embedding strength of the signature.
+Allows to override the setting in the signature file.
+.TP
+.B \-h
+Print a help message.
+.TP
+.BI \-o \ ofile
+Output watermarked image to the specified
+.I file
+instead of standard output.
+.TP
+.BI \-q \ number
+Set quantization/quality factor. Overrides the setting in the signature
+file.
+.TP
+.BI \-s \ sfile
+The signature file to embed into the input image. See
+.B gen_cox_sig
+(1) for a description of the file format. Mandatory parameter.
+.IR file
+Input image in PGM format to sign (watermark). Default: standard input.
+.TP
+.I file
+The input image in PGM format.
+.PP
+.SH OUTPUT
+The signed (watermarked) image in PGM format is written to standard output
+or, optionally, to
+.I ofile.
+The embedding process may take some time on large images since the DCT
+is performed on the whole image in one step (not block-wise).
+.PP
+The
+.I n
+largest coefficients are pulsed to embed the
+.I n
+bit watermark.
+.PP
+.SH AUTHOR
+Peter Meerwald. Email bug reports to pmeerw@cosy.sbg.ac.at.
+.SH AVAILABILITY
+The most recent released version of
+.B wm_cox_e
+is always available
+at http://www.cosy.sbg.ac.at/~pmeerw/Watermarking or via anonymous ftp from ftp.cosy.sbg.ac.at in the
+directory /pub/people/pmeerw/Watermarking.
+.SH "SEE ALSO"
+.BR gen_cox_sig
+(1),
+.BR wm_cox_d
+(1),
+.BR cmp_cox_sig
+(1)
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Meerwald/wm_cox_e.c	Sun Aug 12 13:14:34 2007 +0200
@@ -0,0 +1,164 @@
+#include "wm.h"
+#include "dct.h"
+#include "pgm.h"
+#include "sort.h"
+
+char *progname;
+
+void usage(void) {
+  fprintf(stderr, "usage: %s [-a n] [-h] [-o file] -s file file\n\n", progname);
+  fprintf(stderr, "\t-a n\t\talpha factor/embedding strength\n");
+  fprintf(stderr, "\t-h\t\tprint usage\n");
+  fprintf(stderr, "\t-o file\t\toutput (watermarked) file\n");
+  fprintf(stderr, "\t-s file\t\tsignature to embed in input image\n");
+  exit(0);
+}
+
+int main(int argc, char *argv[]) {
+
+  FILE *in = stdin;
+  FILE *out = stdout;
+  FILE *sig = NULL;
+
+  char output_name[MAXPATHLEN] = "(stdout)";
+  char input_name[MAXPATHLEN] = "(stdin)";
+  char signature_name[MAXPATHLEN];
+
+  int c;
+  int row, col;
+  int i,j;
+
+  int n;
+
+  double alpha = 0.0;
+  double threshold;
+
+  double *largest;
+  gray **input_image;
+  gray **output_image;
+  double **dcts;
+
+  gray maxval;
+  int rows, cols, colors, format;
+
+  progname = argv[0];
+
+  pgm_init(&argc, argv); wm_init();
+
+  while ((c = getopt(argc, argv, "a:h?o:s:")) != EOF) {
+    switch (c) {
+      case 'a':
+        alpha = atof(optarg);
+        if (alpha <= 0.0) {
+          fprintf(stderr, "%s: alpha factor %f out of range\n", progname, alpha);
+          exit(1);
+        }
+        break;
+      case 'h':
+      case '?':
+        usage();
+        break;
+      case 'o':
+        if ((out = fopen(optarg, "wb")) == NULL) {
+          fprintf(stderr, "%s: unable to open output file %s\n", progname, optarg);
+          exit(1);
+        }
+        strcpy(output_name, optarg);
+        break;
+      case 's':
+        if ((sig = fopen(optarg, "r")) == NULL) {
+          fprintf(stderr, "%s: unable to open signature file %s\n", progname, optarg);
+          exit(1);
+        }
+        strcpy(signature_name, optarg);
+        break;
+    }
+  }
+
+  argc -= optind;
+  argv += optind;
+
+  if (argc > 1) {
+    usage();
+    exit(1);
+  }
+
+  if (argc == 1 && *argv[0] != '-')
+    if ((in = fopen(argv[0], "rb")) == NULL) {
+      fprintf(stderr, "%s: unable to open input file %s\n", progname, argv[0]);
+      exit(1);
+    }
+    else
+      strcpy(input_name, argv[0]);
+
+  if (sig) {
+    char line[32];
+    fgets(line, sizeof(line), sig);
+    if (strspn(line, "CXSG") >= 4) {
+      fscanf(sig, "%d\n", &n);
+      if (alpha == 0.0)
+        fscanf(sig, "%lf\n", &alpha);
+      else
+        fscanf(sig, "%*lf\n");
+      fscanf(sig, "%*lf\n");
+      fscanf(sig, "%*lf\n");
+    }
+    else {
+      fprintf(stderr, "%s: invalid signature file %s\n", progname, signature_name);
+      exit(1);
+    }
+  }
+  else {
+    fprintf(stderr, "%s: signature file not specified, use -s file option\n", progname);
+    exit(1);
+  }
+
+  pgm_readpgminit(in, &cols, &rows, &maxval, &format);
+
+  init_dct_NxN(cols, rows);
+
+  dcts = alloc_coeffs(cols, rows);
+  input_image = pgm_allocarray(cols, rows);
+
+  for (row = 0; row < rows; row++)
+    pgm_readpgmrow(in, input_image[row], cols, maxval, format);
+
+  fclose(in);
+
+  output_image = pgm_allocarray(cols, rows);
+
+  fdct_NxN(input_image, dcts);
+
+  largest = malloc((n + 1) * sizeof(double));
+  select_largest_coeffs(dcts[0], cols * rows, n+1, largest);
+  threshold = largest[0];
+  free(largest);
+
+  j = 0;
+  for (i = 0; i < n; i++) {
+    double v;
+
+    while (dcts[j / cols][j % cols] < threshold) j++;
+
+    fscanf(sig, "%lf\n", &v);
+    dcts[j / cols][j % cols] *= (1.0 + alpha * v);
+    j++;
+  }
+
+  idct_NxN(dcts, output_image);
+  free_coeffs(dcts);
+
+  pgm_writepgminit(out, cols, rows, maxval, 0);
+
+  for (row = 0; row < rows; row++)
+    pgm_writepgmrow(out, output_image[row], cols, maxval, 0);
+
+  fclose(out);
+
+  fclose(sig);
+
+  pgm_freearray(output_image, rows);
+  pgm_freearray(input_image, rows);
+
+  exit(0);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Meerwald/wm_dugad_d.c	Sun Aug 12 13:14:34 2007 +0200
@@ -0,0 +1,260 @@
+#include "wm.h"
+#include "dwt.h"
+#include "dwt_util.h"
+#include "pgm.h"
+
+char *progname;
+
+void usage(void) {
+  fprintf(stderr, "usage: %s [-a n] [-e n] [-f n] [-F file] [-h] [-l n] [-n n] [-o file] [-v n] [-t n] -s file file\n\n", progname);
+  fprintf(stderr, "\t-a n\t\talpha factor\n");
+  fprintf(stderr, "\t-e n\t\twavelet filtering method\n");
+  fprintf(stderr, "\t-f n\t\tfilter number\n");
+  fprintf(stderr, "\t-F file\t\tfilter definition file\n");
+  fprintf(stderr, "\t-h\t\tprint usage\n");
+  fprintf(stderr, "\t-l n\t\tdecomposition levels\n");
+  fprintf(stderr, "\t-n n\t\twatermark length\n");
+  fprintf(stderr, "\t-o file\t\tfile for extracted watermark\n");
+  fprintf(stderr, "\t-s file\t\toriginal signature file\n");
+  fprintf(stderr, "\t-t n\t\tdetection threshold\n");
+  fprintf(stderr, "\t-v n\t\tverbosity level\n");
+  exit(0);
+}
+
+void wm_subband(Image s, double *w, int n, double t2, int *m, double *z, double *v) {
+  int i;
+  
+  *m = 0;
+  *z = 0.0;
+  *v = 0.0;
+  for (i = 0; i < s->width * s->height; i++)
+    if (s->data[i] > t2) {
+      (*z) += (s->data[i] * w[i % n]);
+      (*v) += fabs(s->data[i]);
+      (*m)++;
+    }
+}
+
+int main(int argc, char *argv[]) {
+
+  FILE *in = stdin;
+  FILE *out = stdout;
+  FILE *sig = NULL;
+
+  gray **input_image;
+
+  char signature_name[MAXPATHLEN];
+  char output_name[MAXPATHLEN] = "(stdout)";
+  char input_name[MAXPATHLEN] = "(stdin)";
+
+  int c, w;
+  int i;
+  int n = 0;
+  int method = -1;
+  int levels = 0;
+  int filter = 0;
+  char filter_name[MAXPATHLEN] = "";
+
+  double alpha = 0.0;
+  double t2 = 0.0;
+
+  int in_rows, in_cols, in_format;
+  gray in_maxval;
+  int rows, cols;
+  int row, col;
+
+  double *watermark;
+
+  Image_tree dwts, s;
+
+  int verbose = 0;
+
+  progname = argv[0];
+
+  pgm_init(&argc, argv); wm_init2();
+
+  while ((c = getopt(argc, argv, "a:e:f:F:h?l:n:o:s:v:t")) != EOF) {
+    switch (c) {
+      case 'a':
+        alpha = atof(optarg);
+        if (alpha <= 0.0) {
+          fprintf(stderr, "%s: alpha factor %f out of range\n", progname, alpha);
+          exit(1);
+        }
+        break;
+      case 'e':
+        method = atoi(optarg);
+        if (method < 0) {
+          fprintf(stderr, "%s: wavelet filtering method %d out of range\n", progname, method);
+          exit(1);
+        }
+        break;
+      case 'f':
+        filter = atoi(optarg);
+        if (filter <= 0) {
+          fprintf(stderr, "%s: filter number %d out of range\n", progname, filter);
+          exit(1);
+        }
+        break;
+      case 'F':
+        strcpy(filter_name, optarg);
+        break;
+      case 'h':
+      case '?':
+        usage();
+        break;
+      case 'l':      
+        levels = atoi(optarg);
+        if (levels <= 0) {
+          fprintf(stderr, "%s: decomposition level %d out of range\n", levels);
+          exit(1);
+        }
+        break;
+
+      case 'n':
+        n = atoi(optarg);
+        if (n < 1 || n > 32000) {
+          fprintf(stderr, "%s: watermark length %d out of range\n", progname, n);
+          exit(1);
+        }
+        break;
+      case 'o':
+        if ((out = fopen(optarg, "w")) == NULL) {
+          fprintf(stderr, "%s: unable to open output file %s\n", progname, optarg);
+          exit(1);
+        }
+        strcpy(output_name, optarg);
+        break;
+      case 's':
+        if ((sig = fopen(optarg, "r")) == NULL) {
+          fprintf(stderr, "%s: unable to open signature file %s\n", progname, optarg);
+          exit(1);
+        }
+        strcpy(signature_name, optarg);
+        break;
+      case 't':
+        t2 = atof(optarg);
+        if (t2 <= 0.0) {  
+          fprintf(stderr, "%s: detection threshold %f out of range\n", progname, t2); 
+          exit(1);
+        }
+        break;
+      case 'v':
+        verbose = atoi(optarg);
+        if (verbose < 0) {
+          fprintf(stderr, "%s: verbosity level %d out of range\n", progname, verbose);
+          exit(1);
+        }
+        break;
+    }
+  }
+
+  argc -= optind;
+  argv += optind;
+
+  if (argc > 1) {
+    usage();
+    exit(1);
+  }
+
+  if (argc == 1 && *argv[0] != '-')
+    if ((in = fopen(argv[0], "rb")) == NULL) {
+      fprintf(stderr, "%s: unable to open input file %s\n", progname, argv[0]);
+      exit(1);
+    }
+    else
+      strcpy(input_name, argv[0]);
+
+  if (sig) {
+    char line[32];
+    fgets(line, sizeof(line), sig);
+    if (strspn(line, "DGSG") >= 4) {
+      fscanf(sig, "%d\n", &n);
+      if (levels == 0)
+        fscanf(sig, "%d\n", &levels);
+      else
+        fscanf(sig, "%*d\n");
+      if (alpha == 0.0)
+        fscanf(sig, "%lf\n", &alpha);
+      else
+        fscanf(sig, "%*lf\n");
+      fscanf(sig, "%*lf\n");
+      if (t2 == 0.0)
+        fscanf(sig, "%lf\n", &t2);
+      else
+        fscanf(sig, "%*lf\n");
+      if (method < 0)
+        fscanf(sig, "%d\n", &method);
+      else
+        fscanf(sig, "%*d\n");
+      if (filter == 0)
+        fscanf(sig, "%d\n", &filter);
+      else
+        fscanf(sig, "%*d\n");
+      if (!strcmp(filter_name, ""))
+        fscanf(sig, "%[^\n\r]\n", &filter_name);
+      else
+        fscanf(sig, "%*[^\n\r]\n");
+    }
+    else {
+      fprintf(stderr, "%s: invalid signature file %s\n", progname, signature_name);
+      exit(1);
+    }
+  }
+  else {
+    fprintf(stderr, "%s: signature file not specified, use -s file option\n", progname);
+    exit(1);
+  }
+
+  watermark = malloc(n * sizeof(double));
+  for (i = 0; i < n; i++)
+    fscanf(sig, "%lf\n", &watermark[i]);
+  fclose(sig);
+
+  pgm_readpgminit(in, &in_cols, &in_rows, &in_maxval, &in_format);
+
+  cols = in_cols;
+  rows = in_rows;
+
+  input_image = pgm_allocarray(in_cols, in_rows);
+
+  for (row = 0; row < in_rows; row++) {
+    pgm_readpgmrow(in, input_image[row], in_cols, in_maxval, in_format);
+  }
+
+  fclose(in);
+
+  init_dwt(cols, rows, filter_name, filter, levels, method);
+#ifdef POLLEN_STUFF
+#include "pollen_stuff.xxx"
+#endif
+#ifdef PARAM_STUFF
+#include "param_stuff.xxx"
+#endif
+
+  dwts = fdwt(input_image);
+
+  fprintf(out, "DGWM\n");
+  fprintf(out, "%d\n", levels);
+  fprintf(out, "%f\n", alpha);
+
+  for (i = 0, s = dwts; i < levels; i++, s = s->coarse) {
+    int m;
+    double z, v;
+
+    wm_subband(s->horizontal->image, watermark, n, t2, &m, &z, &v);
+    fprintf(out, "%d %f %f\n", m, z, v);
+    wm_subband(s->vertical->image, watermark, n, t2, &m, &z, &v);
+    fprintf(out, "%d %f %f\n", m, z, v);
+    wm_subband(s->diagonal->image, watermark, n, t2, &m, &z, &v);
+    fprintf(out, "%d %f %f\n", m, z, v);
+  }
+
+  fclose(out);
+
+  free(watermark);
+
+  pgm_freearray(input_image, rows);
+
+  exit(0);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Meerwald/wm_dugad_e.c	Sun Aug 12 13:14:34 2007 +0200
@@ -0,0 +1,240 @@
+#include "wm.h"
+#include "dwt.h"
+#include "pgm.h"
+
+char *progname;
+
+void usage(void) {
+  fprintf(stderr, "usage: %s [-a n] [-e n] [-f n] [-F file] [-h] [-l n] [-o file] [-t n] [-v n] -s file file\n\n", progname);
+  fprintf(stderr, "\t-a n\t\talpha factor/embedding strength\n");
+  fprintf(stderr, "\t-e n\t\twavelet filtering method\n");
+  fprintf(stderr, "\t-f n\t\tfilter number\n");
+  fprintf(stderr, "\t-F file\t\tfilter definition file\n");
+  fprintf(stderr, "\t-h\t\tprint usage\n");
+  fprintf(stderr, "\t-l n\t\tdecomposition levels\n");
+  fprintf(stderr, "\t-o file\t\toutput (watermarked) file\n");
+  fprintf(stderr, "\t-s file\t\tsignature to embed in input image\n");
+  fprintf(stderr, "\t-t n\t\tcasting threshold\n");
+  fprintf(stderr, "\t-v n\t\tverbosity level\n");
+  exit(0);
+}
+
+// actual watermarking procedure: embeds a watermark of n normally
+// distributed values into a coefficients > threshold t1 of a subband
+void wm_subband(Image s, double *w, int n, double a, double t1) {
+  int i;
+
+  for (i = 0; i < s->width * s->height; i++) 
+    if (fabs(s->data[i]) > t1)
+      s->data[i] += (a * fabs(s->data[i]) * w[i % n]);
+}
+
+int main(int argc, char *argv[]) {
+
+  FILE *in = stdin;
+  FILE *out = stdout;
+  FILE *sig = NULL;
+
+  char output_name[MAXPATHLEN] = "(stdout)";
+  char input_name[MAXPATHLEN] = "(stdin)";
+  char signature_name[MAXPATHLEN];
+
+  int i, c;
+  int row, col;
+
+  int n;
+
+  double alpha = 0.0;
+  double t1 = 0.0;
+
+  int levels = 0;
+  int filter = 0;
+  int method = -1;
+  char filter_name[MAXPATHLEN] = "";
+
+  int verbose = 0;
+
+  gray **image;
+  Image_tree dwts, s;
+
+  gray maxval;
+  int rows, cols, colors, format;
+
+  double *watermark;
+
+  progname = argv[0];
+
+  pgm_init(&argc, argv); wm_init();
+
+  while ((c = getopt(argc, argv, "a:e:f:F:h?l:o:s:t:v:")) != EOF) {
+    switch (c) {
+      case 'a':
+        alpha = atof(optarg);
+        if (alpha <= 0.0) {
+          fprintf(stderr, "%s: alpha factor %f out of range\n", progname, alpha);
+          exit(1);
+        }
+        break;
+      case 'e':
+        method = atoi(optarg);
+        if (method < 0) {
+          fprintf(stderr, "%s: wavelet filtering method %d out of range\n", progname, method);
+          exit(1);
+        }
+        break;
+      case 'f':
+        filter = atoi(optarg);
+        if (filter <= 0) {
+          fprintf(stderr, "%s: filter number %d out of range\n", progname, filter);
+          exit(1);
+        }
+        break;
+      case 'F':
+        strcpy(filter_name, optarg);
+        break;
+      case 'h':
+      case '?':
+        usage();
+        break;
+      case 'l': 
+        levels = atoi(optarg);
+        if (levels <= 0) {
+          fprintf(stderr, "%s: decomposition level %d out of range\n", levels);
+          exit(1);
+        }
+        break;
+      case 'o':
+        if ((out = fopen(optarg, "wb")) == NULL) {
+          fprintf(stderr, "%s: unable to open output file %s\n", progname, optarg);
+          exit(1);
+        }
+        strcpy(output_name, optarg);
+        break;
+      case 's':
+        if ((sig = fopen(optarg, "r")) == NULL) {
+          fprintf(stderr, "%s: unable to open signature file %s\n", progname, optarg);
+          exit(1);
+        }
+        strcpy(signature_name, optarg);
+        break;
+      case 't':
+        t1 = atof(optarg);
+        if (t1 <= 0.0) {
+          fprintf(stderr, "%s: casting threshold %f out of range\n", progname, t1);
+          exit(1);
+        }
+        break;
+      case 'v':
+        verbose = atoi(optarg);
+        if (verbose < 0) {
+          fprintf(stderr, "%s: verbosity level %d out of range\n", progname, verbose);
+          exit(1);
+        }
+        break;
+    }
+  }
+
+  argc -= optind;
+  argv += optind;
+
+  if (argc > 1) {
+    usage();
+    exit(1);
+  }
+
+  if (argc == 1 && *argv[0] != '-')
+    if ((in = fopen(argv[0], "rb")) == NULL) {
+      fprintf(stderr, "%s: unable to open input file %s\n", progname, argv[0]);
+      exit(1);
+    }
+    else
+      strcpy(input_name, argv[0]);
+
+  if (sig) {
+    char line[32];
+    fgets(line, sizeof(line), sig);
+    if (strspn(line, "DGSG") >= 4) {
+      fscanf(sig, "%d\n", &n);
+      if (levels == 0)
+        fscanf(sig, "%d\n", &levels);
+      else
+        fscanf(sig, "%*d\n");
+      if (alpha == 0.0)
+        fscanf(sig, "%lf\n", &alpha);
+      else
+        fscanf(sig, "%*lf\n");
+      if (t1 == 0.0)
+        fscanf(sig, "%lf\n", &t1);
+      else
+        fscanf(sig, "%*lf\n");
+      fscanf(sig, "%*lf\n");
+      if (method < 0)
+        fscanf(sig, "%d\n", &method);
+      else
+        fscanf(sig, "%*d\n");
+      if (filter == 0)
+        fscanf(sig, "%d\n", &filter);
+      else
+        fscanf(sig, "%*d\n");
+      if (!strcmp(filter_name, ""))
+        fscanf(sig, "%[^\n\r]\n", &filter_name);
+      else
+        fscanf(sig, "%*[^\n\r]\n");
+    }
+    else {
+      fprintf(stderr, "%s: invalid signature file %s\n", progname, signature_name);
+      exit(1);
+    }
+  }
+  else {
+    fprintf(stderr, "%s: signature file not specified, use -s file option\n", progname);
+    exit(1);
+  }
+
+  watermark = malloc(n * sizeof(double));
+  for (i = 0; i < n; i++) 
+    fscanf(sig, "%lf\n", &watermark[i]);
+  fclose(sig);
+
+  pgm_readpgminit(in, &cols, &rows, &maxval, &format);
+
+  image = pgm_allocarray(cols, rows);
+
+  for (row = 0; row < rows; row++)
+    pgm_readpgmrow(in, image[row], cols, maxval, format);
+
+  fclose(in);
+
+  // wavelet transform
+  init_dwt(cols, rows, filter_name, filter, 3, method);
+#ifdef POLLEN_STUFF
+#include "pollen_stuff.xxx"
+#endif
+#ifdef PARAM_STUFF
+#include "param_stuff.xxx"
+#endif
+
+  dwts = fdwt(image);
+
+  // embed watermark in all subbands of a decomposition level
+  for (i = 0, s = dwts; i < 3; i++, s = s->coarse) {
+    wm_subband(s->horizontal->image, watermark, n, alpha, t1);
+    wm_subband(s->vertical->image, watermark, n, alpha, t1);
+    wm_subband(s->diagonal->image, watermark, n, alpha, t1);
+  }
+
+  free(watermark);
+
+  idwt(dwts, image);
+
+  pgm_writepgminit(out, cols, rows, maxval, 0);
+
+  for (row = 0; row < rows; row++)
+    pgm_writepgmrow(out, image[row], cols, maxval, 0);
+
+  fclose(out);
+
+  pgm_freearray(image, rows);
+
+  exit(0);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Meerwald/wm_frid2_d.c	Sun Aug 12 13:14:34 2007 +0200
@@ -0,0 +1,212 @@
+#include "wm.h"
+#include "dct.h"
+#include "pgm.h"
+#include "signature.h"
+#include "frid2_common.h"
+
+char *progname;
+
+void usage(void) {
+  fprintf(stderr, "usage: %s [-a n] [-h] [-b n] [-n n] [-o file] [-v n] -s file file\n\n", progname);
+  fprintf(stderr, "\t-a n\t\talpha factor low freq. embedding strength\n");
+  fprintf(stderr, "\t-b n\t\tbeta factor for weighted correlation (default 0)\n");
+  fprintf(stderr, "\t-h\t\tprint usage\n");
+  fprintf(stderr, "\t-n n\t\tnormalisation factor (default 1024.0)\n");
+  fprintf(stderr, "\t-o file\t\tfile for extracted watermark information\n");
+  fprintf(stderr, "\t-s file\t\toriginal signature file\n");
+  fprintf(stderr, "\t-v n\t\tverbosity level\n");
+  exit(0);
+}
+
+int main(int argc, char *argv[]) {
+  FILE *in = stdin;
+  FILE *out = stdout;
+  FILE *sig = NULL;
+
+  char output_name[MAXPATHLEN] = "(stdout)";
+  char input_name[MAXPATHLEN] = "(stdin)";
+  char signature_name[MAXPATHLEN];
+
+  int c;
+  int row, col;
+  int n;
+  double normalization = 1024.0;
+  int seed, format;
+
+  double alpha = 0.0;
+  double beta = 0.0;
+
+  double correlation;
+
+  gray **image;
+  double **coeffs;
+
+  double mean, derivation, mult_factor;
+  int rows, cols;
+
+  gray maxval;
+  int verbose = 0;
+
+  progname = argv[0];
+
+  pgm_init(&argc, argv); wm_init2();
+
+  while ((c = getopt(argc, argv, "a:b:n:h?s:o:v:")) != EOF) {
+    switch (c) {
+      case 'a':
+        alpha = atof(optarg);
+        if (alpha <= 0.0) {
+          fprintf(stderr, "%s: alpha factor %f out of range\n", progname, alpha);
+          exit(1);
+        }
+        break;
+      case 'b':
+        beta = atof(optarg);
+        if (beta <= 0.0) {
+          fprintf(stderr, "%s: beta factor %f out of range\n", progname, beta);
+          exit(1);
+        }
+        break;
+      case 'n':
+        normalization = atof(optarg);
+        if (normalization < 0) {
+          fprintf(stderr, "%s: normalisation factor %f out of range\n", progname, normalization);
+          exit(1);
+        }
+        break;
+      case 'h':
+      case '?':
+        usage();
+        break;
+      case 'o':
+        if ((out = fopen(optarg, "wb")) == NULL) {
+          fprintf(stderr, "%s: unable to open output file %s\n", progname, optarg);
+          exit(1);
+        }
+        strcpy(output_name, optarg);
+        break;
+      case 's':
+        if ((sig = fopen(optarg, "r")) == NULL) {
+          fprintf(stderr, "%s: unable to open signature file %s\n", progname, optarg);
+          exit(1);
+        }
+        strcpy(signature_name, optarg);
+        break;
+      case 'v':
+        verbose = atoi(optarg);
+        if (verbose < 0) {
+          fprintf(stderr, "%s: verbosity level %d out of range\n", progname, verbose);
+          exit(1);
+        }
+        break;
+    }
+  }
+
+  argc -= optind;
+  argv += optind;
+
+  if (argc > 1) {
+    usage();
+    exit(1);
+  }
+	
+  if (argc == 1 && *argv[0] != '-')
+    if ((in = fopen(argv[0], "rb")) == NULL) {
+      fprintf(stderr, "%s: unable to open input file %s\n", progname, argv[0]);
+      exit(1);
+    }
+    else
+      strcpy(input_name, argv[0]);
+
+  if (sig) {
+    char line[32];
+    fgets(line, sizeof(line), sig);
+    if (strspn(line, "FR2SG") >= 5) {
+      fscanf(sig, "%d\n", &nbit_signature1);
+      if (alpha == 0.0)
+        fscanf(sig, "%lf\n", &alpha);
+      else
+        fscanf(sig, "%*lf\n");
+      fscanf(sig, "%*lf\n");
+      fscanf(sig, "%d\n", &seed);
+      n_signature1 = NBITSTOBYTES(nbit_signature1);
+      fread(signature1, sizeof(char), n_signature1, sig);
+      fscanf(sig, "\n");
+      srandom(seed);
+    }
+    else {
+      fprintf(stderr, "%s: invalid signature file %s\n", progname, signature_name);
+      exit(1);
+    }
+    fclose(sig);
+  }
+  else {
+    fprintf(stderr, "%s: signature file not specified, use -s file option\n", progname);
+    exit(1);
+  }
+
+  pgm_readpgminit(in, &cols, &rows, &maxval, &format);
+  image = pgm_allocarray(cols, rows);
+  for (row = 0; row < rows; row++)
+    pgm_readpgmrow(in, image[row], cols, maxval, format);
+  fclose(in);
+
+  // calculate mean malue
+  mean = 0.0;
+  for (row = 0; row < rows; row++) 
+    for (col = 0; col < cols; col++)
+      mean += image[row][col];
+
+  mean /=  cols * rows;
+
+  // calculate derivation
+  derivation = 0.0;
+  for (row = 0; row < rows; row++) 
+    for (col = 0; col < cols; col++)
+      derivation += sqr(image[row][col] - mean);
+
+  derivation = sqrt(derivation / (cols * rows - 1));
+  mult_factor = normalization / (sqrt(cols * rows) * derivation); 
+
+  if (verbose > 5)
+    fprintf(stderr, "%s: mean %f, derivation %f, mult_factor %f\n", progname, mean, derivation, mult_factor);
+	
+  // normalize image
+  coeffs = alloc_coeffs(cols, rows);
+  for (row = 0; row < rows; row++) 
+    for (col = 0; col < cols; col++)
+      coeffs[row][col] = (image[row][col] - mean) * mult_factor;
+	
+  if (rows == cols) {
+    init_dct_NxN(cols, rows);
+    fdct_inplace_NxN(coeffs);
+  }
+//  else {
+//    init_dct_NxM(cols, rows);
+//    fdct_NxM(coeffs);
+//  }
+
+
+  fprintf(out, "FR2WM\n");
+
+  fprintf(out, "%d\n", nbit_signature1);
+  correlation = detect_low_freq(coeffs, cols, rows, alpha, beta, verbose);
+  if (verbose > 2)
+    fprintf(stderr, "low_freq correlation: %f\n", correlation);
+  fwrite(signature2, sizeof(char), NBITSTOBYTES(nbit_signature1), out);
+  fprintf(out, "\n");
+
+  fprintf(out, "%d\n", nbit_signature1);
+  correlation = detect_med_freq(coeffs, cols, rows, seed, verbose);
+  if (verbose > 2)
+    fprintf(stderr, "med_freq correlation: %f\n", correlation);
+  fwrite(signature2, sizeof(char), NBITSTOBYTES(nbit_signature1), out);
+  fprintf(out, "\n");
+  
+  fclose(out);
+
+  free_coeffs(coeffs);
+  pgm_freearray(image, rows);
+
+  exit(0);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Meerwald/wm_frid2_e.c	Sun Aug 12 13:14:34 2007 +0200
@@ -0,0 +1,218 @@
+#include "wm.h"
+#include "dct.h"
+#include "pgm.h"
+#include "signature.h"
+#include "frid2_common.h"
+
+char *progname;
+
+void usage(void) {
+  fprintf(stderr, "usage: %s [-a n] [-g n] [-n n] [-h] [-o file] [-v n] -s file file\n\n", progname);
+  fprintf(stderr, "\t-a n\t\talpha factor low freq. embedding strength\n");
+  fprintf(stderr, "\t-g n\t\tgamma factor med freq. embedding strength\n");
+  fprintf(stderr, "\t-h\t\tprint usage\n");
+  fprintf(stderr, "\t-n n\t\tnormalisation factor (default 1024.0)\n");
+  fprintf(stderr, "\t-o file\t\toutput (watermarked) file\n");
+  fprintf(stderr, "\t-s file\t\tsignature to embed in input image\n");
+  fprintf(stderr, "\t-v n\t\tverbosity level\n");
+  exit(0);
+}
+
+int main(int argc, char *argv[]) {
+
+  FILE *in = stdin;
+  FILE *out = stdout;
+  FILE *sig = NULL;
+
+  char output_name[MAXPATHLEN] = "(stdout)";
+  char input_name[MAXPATHLEN] = "(stdin)";
+  char signature_name[MAXPATHLEN];
+
+  int c;
+  int row, col;
+  int n;
+  double normalization = 1024.0;
+  int seed, format;
+
+  double alpha = 0.0;
+  double gamma = 0.0;
+
+  gray **image;
+  double **coeffs;
+
+  double mean, derivation;
+  double mult_factor;
+
+  int rows, cols;
+  int verbose = 0;
+  gray maxval;
+
+  progname = argv[0];
+
+  pgm_init(&argc, argv); wm_init();
+
+  while ((c = getopt(argc, argv, "a:g:n:h?o:s:v:")) != EOF) {
+    switch (c) {
+      case 'a':
+        alpha = atof(optarg);
+        if (alpha <= 0.0) {
+          fprintf(stderr, "%s: alpha factor %f out of range\n", progname, alpha);
+          exit(1);
+        }
+        break;
+      case 'g':
+        gamma = atof(optarg);
+        if (gamma <= 0.0) {
+          fprintf(stderr, "%s: gamma factor %f out of range\n", progname, alpha);
+          exit(1);
+        }
+        break;
+      case 'n':
+        normalization = atof(optarg);
+        if (normalization < 0) {
+          fprintf(stderr, "%s: normalisation factor %f out of range\n", progname, normalization);
+          exit(1);
+        }
+        break;
+      case 'h':
+      case '?':
+        usage();
+        break;
+      case 'o':
+        if ((out = fopen(optarg, "wb")) == NULL) {
+          fprintf(stderr, "%s: unable to open output file %s\n", progname, optarg);
+          exit(1);
+        }
+        strcpy(output_name, optarg);
+        break;
+      case 's':
+        if ((sig = fopen(optarg, "r")) == NULL) {
+          fprintf(stderr, "%s: unable to open signature file %s\n", progname, optarg);
+          exit(1);
+        }
+        strcpy(signature_name, optarg);
+        break;
+      case 'v':
+        verbose = atoi(optarg);
+        if (verbose < 0) {
+          fprintf(stderr, "%s: verbosity level %d out of range\n", progname, verbose);
+          exit(1);
+        }
+        break;
+    }
+  }
+
+  argc -= optind;
+  argv += optind;
+
+  if (argc > 1) {
+    usage();
+    exit(1);
+  }
+
+  if (argc == 1 && *argv[0] != '-')
+    if ((in = fopen(argv[0], "rb")) == NULL) {
+      fprintf(stderr, "%s: unable to open input file %s\n", progname, argv[0]);
+      exit(1);
+    }
+    else
+      strcpy(input_name, argv[0]);
+
+  if (sig) {
+    char line[32];
+    fgets(line, sizeof(line), sig);
+    if (strspn(line, "FR2SG") >= 5) {
+      fscanf(sig, "%d\n", &nbit_signature);
+      if (alpha == 0.0)
+        fscanf(sig, "%lf\n", &alpha);
+      else
+        fscanf(sig, "%*lf\n");
+      if (gamma == 0.0)
+        fscanf(sig, "%lf\n", &gamma);
+      else
+        fscanf(sig, "%*lf\n");
+      
+      fscanf(sig, "%d\n", &seed);
+      n_signature = NBITSTOBYTES(nbit_signature);
+      fread(signature, sizeof(char), n_signature, sig);
+      fscanf(sig, "\n");
+      srandom(seed);
+    }
+    else {
+      fprintf(stderr, "%s: invalid signature file %s\n", progname, signature_name);
+      exit(1);
+    }
+    fclose(sig);
+  }
+  else {
+    fprintf(stderr, "%s: signature file not specified, use -s file option\n", progname);
+    exit(1);
+  }
+
+  pgm_readpgminit(in, &cols, &rows, &maxval, &format);
+
+  if (rows == cols)
+    init_dct_NxN(cols, rows);
+  else
+    init_dct_NxM(cols, rows);
+
+  image = pgm_allocarray(cols, rows);
+  for (row = 0; row < rows; row++)
+    pgm_readpgmrow(in, image[row], cols, maxval, format);
+  fclose(in);
+
+  // calculate mean value
+  mean = 0.0;
+  for (row = 0; row < rows; row++)
+    for (col = 0; col < cols; col++)
+      mean += image[row][col];
+
+  mean /= cols * rows;
+
+  // calculate derivation
+  derivation = 0.0;
+  for (row = 0; row < rows; row++)
+    for (col = 0; col < cols; col++)
+      derivation += sqr(image[row][col] - mean);
+    
+  derivation = sqrt(derivation / (cols * rows - 1));
+  mult_factor = normalization / (sqrt(cols * rows) * derivation); 
+
+  if (verbose > 5)
+    fprintf(stderr, "%s: mean %f, derivation %f, mult_factor %f\n", progname, mean, derivation, mult_factor);
+
+  // normalize image
+  coeffs = alloc_coeffs(cols, rows);
+  for (row = 0; row < rows; row++)
+    for (col = 0; col < cols; col++)
+      coeffs[row][col] = (image[row][col] - mean) * mult_factor;
+    
+  if (cols == rows)
+    fdct_inplace_NxN(coeffs);
+//  else
+//    fdct_NxM(image, dcts);    
+
+  embed_low_freq(coeffs, cols, rows, alpha, verbose);
+  embed_med_freq(coeffs, cols, rows, gamma, seed, verbose);
+    
+  if (cols == rows)
+    idct_inplace_NxN(coeffs);
+//  else
+//    idct_NxM(dcts, image);
+
+  for (row = 0; row < rows; row++)
+    for (col = 0; col < cols; col++)
+      image[row][col] = PIXELRANGE(coeffs[row][col] / mult_factor + mean + 0.5);
+  
+  free_coeffs(coeffs);
+
+  pgm_writepgminit(out, cols, rows, maxval, 0);
+  for (row = 0; row < rows; row++)
+    pgm_writepgmrow(out, image[row], cols, maxval, 0);
+
+  fclose(out);
+
+  pgm_freearray(image, rows);
+
+  exit(0);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Meerwald/wm_kim_a.c	Sun Aug 12 13:14:34 2007 +0200
@@ -0,0 +1,292 @@
+#include "wm.h"
+#include "wm_dwt.h"
+#include "pgm.h"
+#include "dwt_util.h"
+#include "kim_common.h"
+
+char *progname;
+
+void usage(void) {
+  fprintf(stderr, "usage: %s [-a n] [-A n] [-e n] [-f n] [-F n] [-h] [-l n] [-o file] [-v n] -s file file\n\n", progname);
+  fprintf(stderr, "\t-a n\t\talpha factor/embedding strength for detail subbands\n");
+  fprintf(stderr, "\t-a n\t\talpha factor/embedding strength for approximation subband\n");
+  fprintf(stderr, "\t-e n\t\twavelet filtering method\n");
+  fprintf(stderr, "\t-f n\t\tfilter number\n");
+  fprintf(stderr, "\t-F file\t\tfilter definition file\n");
+  fprintf(stderr, "\t-h\t\tprint usage\n");
+  fprintf(stderr, "\t-l n\t\tdecomposition level\n");
+  fprintf(stderr, "\t-o file\t\toutput (watermarked) file\n");
+  fprintf(stderr, "\t-s file\t\tsignature to embed in input image\n");
+  fprintf(stderr, "\t-v n\t\tverbosity level\n");
+  exit(0);
+}
+
+int mark_subband(Image_tree s, int name, double alpha, double watermark[], double threshold, int w, int n, int verbose) {
+  int i, j;
+  double last = 0.0;
+
+  for (i = 5; i < s->image->height-5; i++)
+    for (j = 5; j < s->image->width-5; j++) {
+      double coeff, newcoeff;
+
+      coeff = get_pixel(s->image, i, j);   
+      if (fabs(coeff) > threshold / 1.5 ) {
+        newcoeff = coeff - coeff * alpha * watermark[w++ % n];
+        set_pixel(s->image, i, j, newcoeff);
+
+        fprintf(stderr, "%s: (%d/%d) %f: %f -> %f; a=%f\n", progname, j, i, watermark[w % n], coeff, newcoeff, alpha);
+        w++;
+      }
+    }
+
+  if (verbose > 5)
+    fprintf(stderr, "%s: watermarking %s%d, size %d x %d; embedded %d coeffs. total\n",
+      progname, subband_name(name), s->level, s->image->width, s->image->height, w);
+
+  return w;
+}
+
+int main(int argc, char *argv[]) {
+
+  FILE *in = stdin;
+  FILE *out = stdout;
+  FILE *sig = NULL;
+
+  char output_name[MAXPATHLEN] = "(stdout)";
+  char input_name[MAXPATHLEN] = "(stdin)";
+  char signature_name[MAXPATHLEN];
+
+  int i, c, w;
+  int row, col;
+
+  int n;
+
+  double alpha_detail = 0.0;
+  double alpha_approx = 0.0;
+  int level;
+
+  int filter = 0;
+  int method = -1;
+  int levels;
+  char filter_name[MAXPATHLEN] = "";
+
+  int verbose = 0;
+
+  gray **image;
+  Image_tree p, dwts;
+
+  gray maxval;
+  int rows, cols, colors, format;
+
+  double *watermark;
+
+  progname = argv[0];
+
+  pgm_init(&argc, argv);
+
+#ifdef __EMX__
+  _fsetmode(in, "b");
+  _fsetmode(out, "b");
+#endif
+
+  while ((c = getopt(argc, argv, "a:A:e:f:F:h?o:l:s:v:")) != EOF) {
+    switch (c) {
+      case 'a':
+        alpha_detail = atof(optarg);
+        if (alpha_detail <= 0.0) {
+          fprintf(stderr, "%s: alpha factor %f out of range\n", progname, alpha_detail);
+          exit(1);
+        }
+        break;
+      case 'A':
+        alpha_approx = atof(optarg);
+        if (alpha_approx <= 0.0) {
+          fprintf(stderr, "%s: alpha factor %f out of range\n", progname, alpha_approx);
+          exit(1);
+        }
+        break;
+      case 'l':
+        level = atoi(optarg);
+        if (level <= 0) {
+          fprintf(stderr, "%s: decomposition level %d out of range\n", progname, level);
+          exit(1);
+        }
+        break;
+      case 'e':
+        method = atoi(optarg);
+        if (method < 0) {
+          fprintf(stderr, "%s: wavelet filtering method %d out of range\n", progname, method);
+          exit(1);
+        }
+        break;
+      case 'f':
+        filter = atoi(optarg);
+        if (filter <= 0) {
+          fprintf(stderr, "%s: filter number %d out of range\n", progname, filter);
+          exit(1);
+        }
+        break;
+      case 'F':
+        strcpy(filter_name, optarg);
+        break;
+      case 'h':
+      case '?':
+        usage();
+        break;
+      case 'o':
+        if ((out = fopen(optarg, "wb")) == NULL) {
+          fprintf(stderr, "%s: unable to open output file %s\n", progname, optarg);
+          exit(1);
+        }
+        strcpy(output_name, optarg);
+        break;
+      case 's':
+        if ((sig = fopen(optarg, "r")) == NULL) {
+          fprintf(stderr, "%s: unable to open signature file %s\n", progname, optarg);
+          exit(1);
+        }
+        strcpy(signature_name, optarg);
+        break;
+      case 'v':
+        verbose = atoi(optarg);
+        if (verbose < 0) {
+          fprintf(stderr, "%s: verbosity level %d out of range\n", progname, verbose);
+          exit(1);
+        }
+        break;
+    }
+  }
+
+  argc -= optind;
+  argv += optind;
+
+  if (argc > 1) {
+    usage();
+    exit(1);
+  }
+
+  if (argc == 1 && *argv[0] != '-')
+    if ((in = fopen(argv[0], "rb")) == NULL) {
+      fprintf(stderr, "%s: unable to open input file %s\n", progname, argv[0]);
+      exit(1);
+    }
+    else
+      strcpy(input_name, argv[0]);
+
+  if (sig) {
+    char line[32];
+    fgets(line, sizeof(line), sig);
+    if (strspn(line, "KISG") >= 4) {
+      fscanf(sig, "%d\n", &n);
+      if (alpha_detail == 0.0)
+        fscanf(sig, "%lf\n", &alpha_detail);
+      else
+        fscanf(sig, "%*lf\n");
+      if (alpha_approx == 0.0)
+        fscanf(sig, "%lf\n", &alpha_approx);
+      else
+        fscanf(sig, "%*lf\n");
+      if (level == 0)
+        fscanf(sig, "%d\n", &level);
+      else
+        fscanf(sig, "%*d\n");
+      if (method < 0)
+        fscanf(sig, "%d\n", &method);
+      else
+        fscanf(sig, "%*d\n");
+      if (filter == 0)
+        fscanf(sig, "%d\n", &filter);
+      else
+        fscanf(sig, "%*d\n");
+      if (!strcmp(filter_name, ""))
+        fscanf(sig, "%[^\n\r]\n", &filter_name);
+      else
+        fscanf(sig, "%*[^\n\r]\n");
+    }
+    else {
+      fprintf(stderr, "%s: invalid signature file %s\n", progname, signature_name);
+      exit(1);
+    }
+  }
+  else {
+    fprintf(stderr, "%s: signature file not specified, use -s file option\n", progname);
+    exit(1);
+  }
+
+  watermark = malloc(n * sizeof(double));
+  for (i = 0; i < n; i++) 
+    fscanf(sig, "%lf\n", &watermark[i]);
+  fclose(sig);
+
+  pgm_readpgminit(in, &cols, &rows, &maxval, &format);
+  image = pgm_allocarray(cols, rows);
+  for (row = 0; row < rows; row++)
+    pgm_readpgmrow(in, image[row], cols, maxval, format);
+  fclose(in);
+
+  // complete decomposition
+  levels = find_deepest_level(cols, rows) - 1;
+  if (level > levels) {
+    fprintf(stderr, "%s: decomposition level %d not possible (max. %d), image size is %d x %d\n", progname, level, levels, cols, rows);
+    exit(1);
+  }
+
+  // wavelet transform
+  init_dwt(cols, rows, filter_name, filter, level, method);
+#ifdef POLLEN_STUFF
+#include "pollen_stuff.xxx"
+#endif
+#ifdef PARAM_STUFF
+#include "param_stuff.xxx"
+#endif
+
+  dwts = fdwt(image);
+
+  p = dwts;
+  w = 0;
+
+  // process each decomposition level
+  while (p->coarse) {
+    int current_level;
+    double threshold;
+    double max_coeff;
+    double alpha;
+
+    // get current decomposition level number
+    current_level = p->horizontal->level;
+
+    // find largest absolute coefficient in detail subbands of current decomposition level
+    max_coeff = find_level_largest_coeff(p, verbose);
+
+    // calculate significance threshold for current decomposition level
+    threshold = calc_level_threshold(max_coeff, verbose);
+
+    // calculate embedding strength alpha for current decomposition level
+    alpha = calc_level_alpha_detail(alpha_detail, level, current_level, verbose);
+
+    if (verbose > 1)
+      fprintf(stderr, "%s: level %d, threshold %f, alpha %f\n", progname, current_level, threshold, alpha);
+
+    // embed watermark sequence into detail subbands of current decomposition level
+    w = mark_subband(p->horizontal, HORIZONTAL, alpha, watermark, threshold, w, n, verbose);
+    w = mark_subband(p->vertical, VERTICAL, alpha, watermark, threshold, w, n, verbose);
+    w = mark_subband(p->diagonal, DIAGONAL, alpha, watermark, threshold, w, n, verbose);
+
+    p = p->coarse;
+  }
+
+  // mark approximation image using calculated significance threshold and embedding strength
+  w = mark_subband(p, COARSE, alpha_approx, watermark, calc_level_threshold(find_subband_largest_coeff(p, COARSE, verbose), verbose), w, n, verbose);
+
+  free(watermark);
+  idwt(dwts, image);
+
+  pgm_writepgminit(out, cols, rows, maxval, 0);
+  for (row = 0; row < rows; row++)
+    pgm_writepgmrow(out, image[row], cols, maxval, 0);
+  fclose(out);
+
+  pgm_freearray(image, rows);
+
+  exit(0);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Meerwald/wm_kim_d.c	Sun Aug 12 13:14:34 2007 +0200
@@ -0,0 +1,326 @@
+#include "wm.h"
+#include "dwt.h"
+#include "pgm.h"
+#include "dwt_util.h"
+#include "kim_common.h"
+
+char *progname;
+
+void usage(void) {
+  fprintf(stderr, "usage: %s [-a n] [-A n] [-e n] [-f n] [-F file] [-h] [-l n] [-o file] [-v n] -s file -i file file\n\n", progname);
+  fprintf(stderr, "\t-a n\t\talpha factor for detail subband\n");
+  fprintf(stderr, "\t-A n\t\talpha factor for approximation image\n");
+  fprintf(stderr, "\t-e n\t\twavelet filtering method\n");
+  fprintf(stderr, "\t-f n\t\tfilter number\n");
+  fprintf(stderr, "\t-F file\t\tfilter definition file\n");
+  fprintf(stderr, "\t-h\t\tprint usage\n");
+  fprintf(stderr, "\t-i file\t\toriginal image file\n");
+  fprintf(stderr, "\t-l n\t\tdecomposition level\n");
+  fprintf(stderr, "\t-o file\t\tfile for extracted watermark\n");
+  fprintf(stderr, "\t-s file\t\toriginal signature file\n");
+  fprintf(stderr, "\t-v n\t\tverbosity level\n");
+  exit(0);
+}
+
+int extract_subband(Image_tree s, Image_tree t, int name, double alpha, double watermark[], double threshold, int w, int n, int verbose) {
+  int i, j;
+
+  for (i = 5; i < s->image->height-5; i++)
+    for (j = 5; j < s->image->width-5; j++) {
+      double orig_coeff, input_coeff;
+
+      orig_coeff = get_pixel(s->image, i, j);
+      input_coeff = get_pixel(t->image, i, j);
+      if (fabs(orig_coeff) > threshold) {
+        watermark[w++] = (input_coeff - orig_coeff) / (alpha * orig_coeff);
+      }
+    }
+
+  if (verbose > 5)
+    fprintf(stderr, "%s: extracted %s%d, size %d x %d; %d coeffs. total\n",
+      progname, subband_name(name), s->level, s->image->width, s->image->height, w);
+
+  return w;
+}
+
+void write_mark(FILE *out, double watermark[], int n) {
+  int i;
+
+  fprintf(out, "%d\n", n);
+  for (i = 0; i < n; i++) 
+    fprintf(out, "%f\n", watermark[i]);
+}
+
+int main(int argc, char *argv[]) {
+
+  FILE *in = stdin;
+  FILE *out = stdout;
+  FILE *orig = NULL;
+  FILE *sig = NULL;
+
+  gray **input_image;
+  gray **orig_image;
+
+  char signature_name[MAXPATHLEN];
+  char output_name[MAXPATHLEN] = "(stdout)";
+  char input_name[MAXPATHLEN] = "(stdin)";
+  char orig_name[MAXPATHLEN];
+
+  int c, w;
+  int i;
+  int n = 0;
+  int method = -1;
+  int filter = 0;
+  char filter_name[MAXPATHLEN] = "";
+
+  int level = 0, levels;
+  double alpha_detail = 0.0;
+  double alpha_approx = 0.0;
+
+  int in_rows, in_cols, in_format;
+  gray in_maxval;
+  int orig_rows, orig_cols, orig_format;
+  gray orig_maxval;
+  int rows, cols;
+  int row, col;
+
+  double *watermark;
+
+  Image_tree input_dwts, orig_dwts, p, q;
+
+  int verbose = 0;
+
+  progname = argv[0];
+
+  pgm_init(&argc, argv); wm_init2();
+
+  while ((c = getopt(argc, argv, "a:A:e:f:F:h?i:l:o:s:v:")) != EOF) {
+    switch (c) {
+      case 'a':
+        alpha_detail = atof(optarg);
+        if (alpha_detail <= 0.0) {
+          fprintf(stderr, "%s: alpha factor %f out of range\n", progname, alpha_detail);
+          exit(1);
+        }
+        break;
+      case 'A':
+        alpha_approx = atof(optarg);
+        if (alpha_approx <= 0.0) {
+          fprintf(stderr, "%s: alpha factor %f out of range\n", progname, alpha_approx);
+          exit(1);
+        }
+        break;
+      case 'e':
+        method = atoi(optarg);
+        if (method < 0) {
+          fprintf(stderr, "%s: wavelet filtering method %d out of range\n", progname, method);
+          exit(1);
+        }
+        break;
+      case 'f':
+        filter = atoi(optarg);
+        if (filter <= 0) {
+          fprintf(stderr, "%s: filter number %d out of range\n", progname, filter);
+          exit(1);
+        }
+        break;
+      case 'F':
+        strcpy(filter_name, optarg);
+        break;
+      case 'h':
+      case '?':
+        usage();
+        break;
+      case 'i':
+        if ((orig = fopen(optarg, "rb")) == NULL) {
+          fprintf(stderr, "%s: unable to open original image file %s\n", progname, optarg);
+          exit(1);
+        }
+        strcpy(orig_name, optarg);
+        break;
+      case 'l':
+        level = atoi(optarg);  
+        if (level <= 0) { 
+          fprintf(stderr, "%s: decomposition level %d out of range\n", progname, level);
+          exit(1);
+        }
+        break;
+      case 'o':
+        if ((out = fopen(optarg, "w")) == NULL) {
+          fprintf(stderr, "%s: unable to open output file %s\n", progname, optarg);
+          exit(1);
+        }
+        strcpy(output_name, optarg);
+        break;
+      case 's':
+        if ((sig = fopen(optarg, "r")) == NULL) {
+          fprintf(stderr, "%s: unable to open signature file %s\n", progname, optarg);
+          exit(1);
+        }
+        strcpy(signature_name, optarg);
+        break;
+      case 'v':
+        verbose = atoi(optarg);
+        if (verbose < 0) {
+          fprintf(stderr, "%s: verbosity level %d out of range\n", progname, verbose);
+          exit(1);
+        }
+        break;
+    }
+  }
+
+  argc -= optind;
+  argv += optind;
+
+  if (argc > 1) {
+    usage();
+    exit(1);
+  }
+
+  if (argc == 1 && *argv[0] != '-')
+    if ((in = fopen(argv[0], "rb")) == NULL) {
+      fprintf(stderr, "%s: unable to open input file %s\n", progname, argv[0]);
+      exit(1);
+    }
+    else
+      strcpy(input_name, argv[0]);
+
+  if (!orig) {
+    fprintf(stderr, "%s: original image file not specified, use -i file option\n", progname);
+    exit(1);
+  }
+
+  if (sig) {
+    char line[32];
+    fgets(line, sizeof(line), sig);
+    if (strspn(line, "KISG") >= 4) {
+      fscanf(sig, "%d\n", &n);
+      if (alpha_detail == 0.0)
+        fscanf(sig, "%lf\n", &alpha_detail);
+      else
+        fscanf(sig, "%*lf\n");
+      if (alpha_approx == 0.0)
+        fscanf(sig, "%lf\n", &alpha_approx);
+      else
+        fscanf(sig, "%*lf\n");
+      if (level == 0)
+        fscanf(sig, "%d\n", &level);
+      else
+        fscanf(sig, "%*d\n");
+      if (method < 0)
+        fscanf(sig, "%d\n", &method);
+      else
+        fscanf(sig, "%*d\n");
+      if (filter == 0)
+        fscanf(sig, "%d\n", &filter);
+      else
+        fscanf(sig, "%*d\n");
+      if (!strcmp(filter_name, ""))
+        fscanf(sig, "%[^\n\r]\n", &filter_name);
+      else
+        fscanf(sig, "%*[^\n\r]\n");
+    }
+    else {
+      fprintf(stderr, "%s: invalid signature file %s\n", progname, signature_name);
+      exit(1);
+    }
+    fclose(sig);
+  }
+  else {
+    fprintf(stderr, "%s: signature file not specified, use -s file option\n", progname);
+    exit(1);
+  }
+
+  pgm_readpgminit(in, &in_cols, &in_rows, &in_maxval, &in_format);
+  pgm_readpgminit(orig, &orig_cols, &orig_rows, &orig_maxval, &orig_format);
+
+  if (in_cols != orig_cols || in_rows != orig_rows) {
+    fprintf(stderr, "%s: input image %s does not match dimensions of original image %s\n", progname, input_name, orig_name);
+    exit(1);
+  }
+
+  cols = in_cols;
+  rows = in_rows;
+
+  input_image = pgm_allocarray(in_cols, in_rows);
+  orig_image = pgm_allocarray(orig_cols, orig_rows);
+
+  for (row = 0; row < in_rows; row++) {
+    pgm_readpgmrow(in, input_image[row], in_cols, in_maxval, in_format);
+    pgm_readpgmrow(orig, orig_image[row], orig_cols, orig_maxval, orig_format);
+  }
+
+  fclose(in);
+  fclose(orig);
+
+  // complete decomposition
+  levels = find_deepest_level(cols, rows) - 1;
+  if (level > levels) {
+    fprintf(stderr, "%s: decomposition level %d not possible (max. %d), image size is %d x %d\n", progname, level, levels, cols, rows);
+    exit(1);
+  }
+
+  init_dwt(cols, rows, filter_name, filter, level, method);
+#ifdef POLLEN_STUFF
+#include "pollen_stuff.xxx"
+#endif
+#ifdef PARAM_STUFF
+#include "param_stuff.xxx"
+#endif
+
+  input_dwts = fdwt(input_image);
+  orig_dwts = fdwt(orig_image);
+
+  watermark = malloc((rows * cols) * sizeof(double));
+  if (!watermark) {
+    fprintf(stderr, "%s: malloc() failed\n\n", progname);
+    exit(1);
+  }
+
+  p = input_dwts;
+  q = orig_dwts;
+  w = 0;
+  while (p->coarse && q->coarse) { 
+    int current_level;
+    double threshold;
+    double max_coeff;
+    double alpha;
+
+    // get current decomposition level number
+    current_level = q->horizontal->level;
+
+    // find largest absolute coefficient in detail subbands of current decomposition level
+    max_coeff = find_level_largest_coeff(q, verbose);
+
+    // calculate significance threshold for current decomposition level
+    threshold = calc_level_threshold(max_coeff, verbose);
+
+    // calculate embedding strength alpha for current decomposition level
+    alpha = calc_level_alpha_detail(alpha_detail, level, current_level, verbose);
+
+    if (verbose > 1)
+      fprintf(stderr, "%s: level %d, threshold %f, alpha %f\n", progname, current_level, threshold, alpha);
+
+    w = extract_subband(q->horizontal, p->horizontal, HORIZONTAL, alpha, watermark, threshold, w, n, verbose);
+    w = extract_subband(q->vertical, p->vertical, VERTICAL, alpha, watermark, threshold, w, n, verbose);
+    w = extract_subband(q->diagonal, p->diagonal, DIAGONAL, alpha, watermark, threshold, w, n, verbose);
+
+    p = p->coarse;
+    q = q->coarse;
+  }
+
+  // extract watermark from approximation image using calculated significance threshold and embedding strength
+  w = extract_subband(q, p, COARSE, alpha_approx, watermark, calc_level_threshold(find_subband_largest_coeff(q, COARSE, verbose), verbose), w, n, verbose);
+
+  fprintf(out, "KIWM\n");
+  write_mark(out, watermark, w);
+
+  fclose(out);
+
+  free(watermark);
+
+  pgm_freearray(input_image, rows);
+  pgm_freearray(orig_image, rows);
+
+  exit(0);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Meerwald/wm_kim_e.c	Sun Aug 12 13:14:34 2007 +0200
@@ -0,0 +1,288 @@
+#include "wm.h"
+#include "dwt.h"
+#include "pgm.h"
+#include "dwt_util.h"
+#include "kim_common.h"
+
+char *progname;
+
+void usage(void) {
+  fprintf(stderr, "usage: %s [-a n] [-A n] [-e n] [-f n] [-F n] [-h] [-l n] [-o file] [-v n] -s file file\n\n", progname);
+  fprintf(stderr, "\t-a n\t\talpha factor/embedding strength for detail subbands\n");
+  fprintf(stderr, "\t-a n\t\talpha factor/embedding strength for approximation subband\n");
+  fprintf(stderr, "\t-e n\t\twavelet filtering method\n");
+  fprintf(stderr, "\t-f n\t\tfilter number\n");
+  fprintf(stderr, "\t-F file\t\tfilter definition file\n");
+  fprintf(stderr, "\t-h\t\tprint usage\n");
+  fprintf(stderr, "\t-l n\t\tdecomposition level\n");
+  fprintf(stderr, "\t-o file\t\toutput (watermarked) file\n");
+  fprintf(stderr, "\t-s file\t\tsignature to embed in input image\n");
+  fprintf(stderr, "\t-v n\t\tverbosity level\n");
+  exit(0);
+}
+
+int mark_subband(Image_tree s, int name, double alpha, double watermark[], double threshold, int w, int n, int verbose) {
+  int i, j;
+
+  for (i = 5; i < s->image->height-5; i++)
+    for (j = 5; j < s->image->width-5; j++) {
+      double coeff, newcoeff;
+
+      coeff = get_pixel(s->image, i, j);   
+      if (fabs(coeff) > threshold) {
+        newcoeff = coeff + alpha * coeff * watermark[w % n];
+        set_pixel(s->image, i, j, newcoeff);
+ 
+        if (verbose >= 9) 
+          fprintf(stderr, "%s: (%d/%d) %f: %f -> %f\n", progname, j, i, watermark[w % n], coeff, newcoeff);
+
+        w++;
+      }
+    }
+
+  if (verbose > 5)
+    fprintf(stderr, "%s: watermarking %s%d, size %d x %d; embedded %d coeffs. total\n",
+      progname, subband_name(name), s->level, s->image->width, s->image->height, w);
+
+  return w;
+}
+
+int main(int argc, char *argv[]) {
+
+  FILE *in = stdin;
+  FILE *out = stdout;
+  FILE *sig = NULL;
+
+  char output_name[MAXPATHLEN] = "(stdout)";
+  char input_name[MAXPATHLEN] = "(stdin)";
+  char signature_name[MAXPATHLEN];
+
+  int i, c, w;
+  int row, col;
+
+  int n;
+
+  double alpha_detail = 0.0;
+  double alpha_approx = 0.0;
+  int level = 0;
+
+  int filter = 0;
+  int method = -1;
+  int levels;
+  char filter_name[MAXPATHLEN] = "";
+
+  int verbose = 0;
+
+  gray **image;
+  Image_tree p, dwts;
+
+  gray maxval;
+  int rows, cols, colors, format;
+
+  double *watermark;
+
+  progname = argv[0];
+
+  pgm_init(&argc, argv); wm_init();
+
+  while ((c = getopt(argc, argv, "a:A:e:f:F:h?o:l:s:v:")) != EOF) {
+    switch (c) {
+      case 'a':
+        alpha_detail = atof(optarg);
+        if (alpha_detail <= 0.0) {
+          fprintf(stderr, "%s: alpha factor %f out of range\n", progname, alpha_detail);
+          exit(1);
+        }
+        break;
+      case 'A':
+        alpha_approx = atof(optarg);
+        if (alpha_approx <= 0.0) {
+          fprintf(stderr, "%s: alpha factor %f out of range\n", progname, alpha_approx);
+          exit(1);
+        }
+        break;
+      case 'l':
+        level = atoi(optarg);
+        if (level <= 0) {
+          fprintf(stderr, "%s: decomposition level %d out of range\n", progname, level);
+          exit(1);
+        }
+        break;
+      case 'e':
+        method = atoi(optarg);
+        if (method < 0) {
+          fprintf(stderr, "%s: wavelet filtering method %d out of range\n", progname, method);
+          exit(1);
+        }
+        break;
+      case 'f':
+        filter = atoi(optarg);
+        if (filter <= 0) {
+          fprintf(stderr, "%s: filter number %d out of range\n", progname, filter);
+          exit(1);
+        }
+        break;
+      case 'F':
+        strcpy(filter_name, optarg);
+        break;
+      case 'h':
+      case '?':
+        usage();
+        break;
+      case 'o':
+        if ((out = fopen(optarg, "wb")) == NULL) {
+          fprintf(stderr, "%s: unable to open output file %s\n", progname, optarg);
+          exit(1);
+        }
+        strcpy(output_name, optarg);
+        break;
+      case 's':
+        if ((sig = fopen(optarg, "r")) == NULL) {
+          fprintf(stderr, "%s: unable to open signature file %s\n", progname, optarg);
+          exit(1);
+        }
+        strcpy(signature_name, optarg);
+        break;
+      case 'v':
+        verbose = atoi(optarg);
+        if (verbose < 0) {
+          fprintf(stderr, "%s: verbosity level %d out of range\n", progname, verbose);
+          exit(1);
+        }
+        break;
+    }
+  }
+
+  argc -= optind;
+  argv += optind;
+
+  if (argc > 1) {
+    usage();
+    exit(1);
+  }
+
+  if (argc == 1 && *argv[0] != '-')
+    if ((in = fopen(argv[0], "rb")) == NULL) {
+      fprintf(stderr, "%s: unable to open input file %s\n", progname, argv[0]);
+      exit(1);
+    }
+    else
+      strcpy(input_name, argv[0]);
+
+  if (sig) {
+    char line[32];
+    fgets(line, sizeof(line), sig);
+    if (strspn(line, "KISG") >= 4) {
+      fscanf(sig, "%d\n", &n);
+      if (alpha_detail == 0.0)
+        fscanf(sig, "%lf\n", &alpha_detail);
+      else
+        fscanf(sig, "%*lf\n");
+      if (alpha_approx == 0.0)
+        fscanf(sig, "%lf\n", &alpha_approx);
+      else
+        fscanf(sig, "%*lf\n");
+      if (level == 0)
+        fscanf(sig, "%d\n", &level);
+      else
+        fscanf(sig, "%*d\n");
+      if (method < 0)
+        fscanf(sig, "%d\n", &method);
+      else
+        fscanf(sig, "%*d\n");
+      if (filter == 0)
+        fscanf(sig, "%d\n", &filter);
+      else
+        fscanf(sig, "%*d\n");
+      if (!strcmp(filter_name, ""))
+        fscanf(sig, "%[^\n\r]\n", &filter_name);
+      else
+        fscanf(sig, "%*[^\n\r]\n");
+    }
+    else {
+      fprintf(stderr, "%s: invalid signature file %s\n", progname, signature_name);
+      exit(1);
+    }
+  }
+  else {
+    fprintf(stderr, "%s: signature file not specified, use -s file option\n", progname);
+    exit(1);
+  }
+
+  watermark = malloc(n * sizeof(double));
+  for (i = 0; i < n; i++) 
+    fscanf(sig, "%lf\n", &watermark[i]);
+  fclose(sig);
+
+  pgm_readpgminit(in, &cols, &rows, &maxval, &format);
+  image = pgm_allocarray(cols, rows);
+  for (row = 0; row < rows; row++)
+    pgm_readpgmrow(in, image[row], cols, maxval, format);
+  fclose(in);
+
+  // complete decomposition
+  levels = find_deepest_level(cols, rows) - 1;
+  if (level > levels) {
+    fprintf(stderr, "%s: decomposition level %d not possible (max. %d), image size is %d x %d\n", progname, level, levels, cols, rows);
+    exit(1);
+  }
+
+  // wavelet transform
+  init_dwt(cols, rows, filter_name, filter, level, method);
+#ifdef POLLEN_STUFF
+#include "pollen_stuff.xxx"
+#endif
+#ifdef PARAM_STUFF
+#include "param_stuff.xxx"
+#endif
+
+  dwts = fdwt(image);
+
+  p = dwts;
+  w = 0;
+
+  // process each decomposition level
+  while (p->coarse) {
+    int current_level;
+    double threshold;
+    double max_coeff;
+    double alpha;
+
+    // get current decomposition level number
+    current_level = p->horizontal->level;
+
+    // find largest absolute coefficient in detail subbands of current decomposition level
+    max_coeff = find_level_largest_coeff(p, verbose);
+
+    // calculate significance threshold for current decomposition level
+    threshold = calc_level_threshold(max_coeff, verbose);
+
+    // calculate embedding strength alpha for current decomposition level
+    alpha = calc_level_alpha_detail(alpha_detail, level, current_level, verbose);
+
+    if (verbose > 1)
+      fprintf(stderr, "%s: level %d, threshold %f, alpha %f\n", progname, current_level, threshold, alpha);
+
+    // embed watermark sequence into detail subbands of current decomposition level
+    w = mark_subband(p->horizontal, HORIZONTAL, alpha, watermark, threshold, w, n, verbose);
+    w = mark_subband(p->vertical, VERTICAL, alpha, watermark, threshold, w, n, verbose);
+    w = mark_subband(p->diagonal, DIAGONAL, alpha, watermark, threshold, w, n, verbose);
+
+    p = p->coarse;
+  }
+
+  // mark approximation image using calculated significance threshold and embedding strength
+  w = mark_subband(p, COARSE, alpha_approx, watermark, calc_level_threshold(find_subband_largest_coeff(p, COARSE, verbose), verbose), w, n, verbose);
+
+  free(watermark);
+  idwt(dwts, image);
+
+  pgm_writepgminit(out, cols, rows, maxval, 0);
+  for (row = 0; row < rows; row++)
+    pgm_writepgmrow(out, image[row], cols, maxval, 0);
+  fclose(out);
+
+  pgm_freearray(image, rows);
+
+  exit(0);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Meerwald/wm_koch_d.1	Sun Aug 12 13:14:34 2007 +0200
@@ -0,0 +1,114 @@
+.\"
+.\" wm_koch_d.1 - the *roff document processor man page source
+.\"
+.TH wm_koch_d 1 "98/07/05" "Watermarking, Version 1.0"
+.SH NAME
+.B wm_koch_d
+\- a program to extract signature bits that have been embedded into
+the DCT coefficients of an image
+.SH SYNOPSIS
+.B wm_koch_d
+[
+.B \-h
+]
+[
+.BI \-o \ ofile
+]
+[
+.BI \-q \ number
+]
+[
+.BI \-v \ number
+]
+.BI \-s \ sfile
+.IR file
+.SH DESCRIPTION
+.B wm_koch_d
+is a program to extract signature bits from the 8x8 DCT coefficients of
+an image, embedded with the
+.B wm_koch_e
+watermarking program.
+.B cmp_koch_sig
+program compares and tests the extracted signature against the original signature.
+.PP
+The input image is in PGM (portable graymap) format.
+.PP
+If
+.I file
+or
+.I ofile
+is not specified, then standard input or standard output is
+used. The signature
+.I sfile
+is a mandatory parameter however.
+.PP
+Please refer to E. Koch's paper "Towards Robust and Hidden
+Image Copyright", 1995, to get an idea about the algorithm.
+.PP
+.SH OPTIONS
+.TP
+.B \-h
+Print a help message.
+.TP
+.BI \-o \ ofile
+Output the extracted signature to
+.I ofile
+instead of standard output.
+.TP
+.BI \-q \ number
+Quality/robustness factor used to extract the signature.
+Overrides setting from signature file.
+.TP
+.BI \-s \ sfile
+The original signature file. See
+.B gen_koch_sig
+(1) for a description of the file format. Mandatory parameter.
+.BI \-v \ number
+Verbosity level. 0 for quiet operation, higher numbers for more 
+output. Default value: 0.
+.TP
+.IR file
+Signed (watermarked) input image in PGM format. Default: standard input.
+.PP
+.SH OUTPUT
+The extracted signature is written to standard output
+or, optionally, to
+.I ofile.
+.PP
+The extraction algorithm examines the relationship between two random
+coefficients of randomly selected 8x8 DCT blocks to reconstruct the
+signature bits.
+.PP
+The output file has the following format:
+.TP
+.B KCSG
+Magic to identify file type.
+.TP
+.I number
+The length of the signature in bits.
+.TP
+.I number
+The quality/robustness factor.
+.TP
+.I number
+The seed value for the pseudo-random number generator.
+.TP
+.I string
+The actual signature bytes.
+.PP
+.SH AUTHOR
+Peter Meerwald. 
+Email bug reports to pmeerw@cosy.sbg.ac.at.
+.SH AVAILABILITY
+The most recent released version of
+.B wm_koch_d
+is always available
+at http://www.cosy.sbg.ac.at/~pmeerw/Watermarking or via anonymous ftp from ftp.cosy.sbg.ac.at in the
+directory /pub/people/pmeerw/Watermarking.
+.SH "SEE ALSO"
+.BR gen_koch_sig
+(1),
+.BR wm_koch_e
+(1),
+.BR cmp_koch_sig
+(1)
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Meerwald/wm_koch_d.c	Sun Aug 12 13:14:34 2007 +0200
@@ -0,0 +1,238 @@
+#include "wm.h"
+#include "dct.h"
+#include "signature.h"
+#include "coord.h"
+#include "pgm.h"
+
+char *progname;
+
+void usage(void) {
+  fprintf(stderr, "usage: %s [-h] [-l n] [-o file] [-q n] [-v n] -s file file\n\n", progname);
+  fprintf(stderr, "\t-h\t\tprint usage\n");
+  fprintf(stderr, "\t-l n\t\tsignature robustness factor\n");
+  fprintf(stderr, "\t-o file\t\textracted signature file\n");
+  fprintf(stderr, "\t-q n\t\tquantization (JPEG quality) factor\n");
+  fprintf(stderr, "\t-s file\t\toriginal signature file\n");
+  fprintf(stderr, "\t-v n\t\tverbosity level\n");
+  exit(0);
+}
+
+int main(int argc, char *argv[]) {
+
+  FILE *in = stdin;
+  FILE *out = stdout;
+  FILE *sig = NULL;
+
+  gray **image;
+  struct coords *coords;
+
+  char signature_name[MAXPATHLEN];
+  char input_name[MAXPATHLEN] = "(stdin)";
+  char output_name[MAXPATHLEN] = "(stdout)";
+
+  int i;
+  int j;
+  int c;
+  int n;
+  int x;
+  int y;
+
+  int rows, cols, format;
+  gray maxval;
+  int row, col;
+
+  int seed;
+  int verbose = 0;
+
+  double quality = 0.0;
+  int quantization = 0;
+
+  double **dcts;
+
+  progname = argv[0];
+
+  pgm_init(&argc, argv); wm_init();
+
+  while ((c = getopt(argc, argv, "h?i:l:o:q:s:v:")) != EOF) {
+    switch (c) {
+      case 'h':
+      case '?':
+        usage();
+        break;
+      case 'l':
+        quality = atof(optarg);
+        if (quality <= 0.0) {
+          fprintf(stderr, "%s: signature strength factor %f out of range\n", progname, quality);
+          exit(1);
+        }
+        break;
+      case 'o':
+        if ((out = fopen(optarg, "wb")) == NULL) {
+          fprintf(stderr, "%s: unable to open output file %s\n", progname, optarg);
+          exit(1);
+        }
+        strcpy(output_name, optarg);
+        break;
+      case 'q':
+        quantization = atoi(optarg);
+        if (quantization <= 0 || quantization > 100) {
+          fprintf(stderr, "%s: quantization factor %d out of range\n", progname, quantization);
+          exit(1);
+        }
+        break;
+      case 's':
+        if ((sig = fopen(optarg, "r")) == NULL) {
+          fprintf(stderr, "%s: unable to open signature file %s\n", progname, optarg);
+          exit(1);
+        }
+        strcpy(signature_name, optarg);
+        break;
+      case 'v':
+        verbose = atoi(optarg);
+        if (verbose < 0) {
+          fprintf(stderr, "%s: verbosity level %d out of range\n", progname, verbose);
+          exit(1);
+        }
+        break;
+    }
+  }
+
+  argc -= optind;
+  argv += optind;
+
+  if (argc > 1) {
+    usage();
+    exit(1);
+  }
+
+  if (argc == 1 && *argv[0] != '-')
+    if ((in = fopen(argv[0], "rb")) == NULL) {
+      fprintf(stderr, "%s: unable to open input file %s\n", progname, argv[0]);
+      exit(1);
+    }
+    else
+      strcpy(input_name, argv[0]);
+
+  if (sig) {
+    char line[128];
+    fgets(line, sizeof(line), sig);
+    if (strspn(line, "KCSG") >= 4) {
+      fscanf(sig, "%d\n", &nbit_signature);
+      n_signature = NBITSTOBYTES(nbit_signature);
+      if (quality == 0.0)
+        fscanf(sig, "%lf\n", &quality);
+      else
+        fscanf(sig, "%*lf\n");
+      if (quantization == 0)
+        fscanf(sig, "%d\n", &quantization);
+      else
+        fscanf(sig, "%*d\n");
+      fscanf(sig, "%d\n", &seed);
+      srandom(seed);
+      fread(signature, sizeof(char), n_signature, sig);
+      init_signature_bits();
+      fscanf(sig, "\n");
+    }
+    else {
+      fprintf(stderr, "%s: invalid signature file %s\n", progname, signature_name);
+      exit(1);
+    }
+    fclose(sig);
+  }
+  else {
+    fprintf(stderr, "%s: signature file not specified, use -s file option\n", progname);
+    exit(1);
+  }
+
+  pgm_readpgminit(in, &cols, &rows, &maxval, &format);
+
+  if (cols % NJPEG) {
+    fprintf(stderr, "%s: image width %d not a multiple of %d\n", progname, cols, NJPEG);
+    exit(1);
+  }
+
+  if (rows % NJPEG) {
+    fprintf(stderr, "%s: image height %d not a multiple of %d\n", progname, rows, NJPEG);
+    exit(1);
+  }
+
+  if ((rows * cols) / (NJPEG * NJPEG) < nbit_signature) {
+    fprintf(stderr, "%s: image too small to extract %d bits of signature\n", progname, nbit_signature);
+    exit(1);
+  }
+
+  init_dct_8x8();
+  init_quantum_JPEG_lumin(quantization);
+
+  dcts = alloc_coeffs_8x8();
+
+  if ((coords = alloc_coords(nbit_signature)) == NULL) {
+    fprintf(stderr, "%s: unable to allocate memory\n", progname);
+    exit(1);
+  }
+
+  image = pgm_allocarray(cols, rows);
+
+  for (row = 0; row < rows; row++)
+    pgm_readpgmrow(in, image[row], cols, maxval, format);
+
+  fclose(in);
+
+  n = 0;
+  while (n < nbit_signature) {
+    int xb;
+    int yb;
+    int c1, c2;
+    double v1, v2;
+    double q = 1.0;
+
+    do {
+      xb = random() % (cols / NJPEG);
+      yb = random() % (rows / NJPEG);
+    } while (add_coord(coords, xb, yb) < 0);
+
+    fdct_block_8x8(image, xb * NJPEG, yb * NJPEG, dcts);
+
+    do {
+      c1 = (random() % (NJPEG * NJPEG - 2)) + 1;
+      c2 = (random() % (NJPEG * NJPEG - 2)) + 1;
+    } while (c1 == c2 || !is_middle_frequency_coeff_8x8(c1) || !is_middle_frequency_coeff_8x8(c2));
+
+    quantize_8x8(dcts);
+
+    if (verbose >= 1)
+      fprintf(stderr, "%d: quantized DCT block (x %d/y %d), extracting (x %d/y %d), (x %d/y %d) ", n, xb * NJPEG, yb * NJPEG, c1 % NJPEG, c1 / NJPEG, c2 % NJPEG, c2 / NJPEG);
+
+    v1 = dcts[c1 / NJPEG][c1 % NJPEG];
+    v2 = dcts[c2 / NJPEG][c2 % NJPEG];
+
+    if (fabs(v1) > fabs(v2)) {
+      set_signature_bit(n, 1);
+      if (verbose >= 1)
+        fprintf(stderr, "HIGH\n");
+    }
+    else {
+      set_signature_bit(n, 0);
+      if (verbose >= 1)
+        fprintf(stderr, "LOW\n");
+    }
+
+    if (verbose >= 2)
+      print_coeffs_8x8(dcts);
+
+    n++;
+  }
+
+  fprintf(out, "KCWM\n");
+  fprintf(out, "%d\n", nbit_signature);
+  fwrite(signature, sizeof(char), n_signature, out);
+  fprintf(out, "\n");
+
+  fclose(out);
+
+  free_coeffs(dcts);
+
+  pbm_freearray(image, rows);
+
+  exit(0);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Meerwald/wm_koch_e.1	Sun Aug 12 13:14:34 2007 +0200
@@ -0,0 +1,98 @@
+.\"
+.\" wm_koch_e.1 - the *roff document processor man page source
+.\"
+.TH wm_koch_e 1 "98/07/05" "Watermarking, Version 1.0"
+.SH NAME
+.B wm_koch_e
+\- a program to embed signature bits in the DCT coefficients of an image
+.SH SYNOPSIS
+.B wm_koch_e
+[
+.B \-h
+]
+[
+.BI \-o \ ofile
+]
+[
+.BI \-q \ number
+]
+[
+.BI \-v \ number
+]
+.BI \-s \ sfile
+.IR file
+.SH DESCRIPTION
+.B wm_koch_e
+is a program to embed signature bits in 8x8 DCT coefficients of
+an image. The signature has to be generated by the
+.B gen_koch_sig
+program. The
+.B wm_koch_d
+program is used to extract a signature from a signed (watermarked) image. The
+.B cmp_koch_sig
+program compares and tests the extracted signature against the original signature.
+.PP
+Both, input and output image,
+are in PGM (portable graymap) format.
+.PP
+If
+.I file
+or
+.I ofile
+is not specified, then standard input or standard output is
+used. The signature
+.I sfile
+is a mandatory parameter however.
+.PP
+Please refer to E. Koch's paper "Towards Robust and Hidden
+Image Copyright", 1995, to get an idea about the algorithm.
+.PP
+.SH OPTIONS
+.TP
+.B \-h
+Print a help message.
+.TP
+.BI \-o \ ofile
+Output signed (watermarked) image to
+.I ofile
+instead of standard output.
+.TP
+.BI \-q \ number
+Quality/robustness factor used to embed signature into image.
+Overrides setting from signature file.
+.TP
+.BI \-s \ sfile
+The signature file to embed into image. See
+.B gen_koch_sig
+(1) for a description of the file format. Mandatory parameter.
+.TP
+.BI \-v \ number
+Verbosity level. 0 for quiet operation, higher numbers for more
+output. Default value: 0.
+.TP
+.IR file
+Input image in PGM format to sign (watermark). Default: standard input.
+.PP
+.SH OUTPUT
+The signed (watermarked) image in PGM format is written to standard output
+or, optionally, to
+.I ofile.
+.PP
+Two coefficients of an 8x8 DCT block are selected at random to embed a
+single signature bit.
+.PP
+.SH AUTHOR
+Peter Meerwald. Email bug reports to pmeerw@cosy.sbg.ac.at.
+.SH AVAILABILITY
+The most recent released version of
+.B wm_koch_e
+is always available
+at http://www.cosy.sbg.ac.at/~pmeerw/Watermarking or via anonymous ftp from ftp.cosy.sbg.ac.at in the
+directory /pub/people/pmeerw/Watermarking.
+.SH "SEE ALSO"
+.BR gen_koch_sig
+(1),
+.BR wm_koch_d
+(1),
+.BR cmp_koch_sig
+(1)
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Meerwald/wm_koch_e.c	Sun Aug 12 13:14:34 2007 +0200
@@ -0,0 +1,274 @@
+#include "wm.h"
+#include "dct.h"
+#include "signature.h"
+#include "coord.h"
+#include "pgm.h"
+
+char *progname;
+
+void usage(void) {
+  fprintf(stderr, "usage: %s [-h] [-l n] [-o file] [-q n] [-v n] -s file file\n", progname);
+  fprintf(stderr, "\t-h\t\tprint usage\n");
+  fprintf(stderr, "\t-l n\t\tsignature robustness factor\n");
+  fprintf(stderr, "\t-o file\t\toutput (watermarked) file\n");
+  fprintf(stderr, "\t-q n\t\tquantization (JPEG quality) factor\n");
+  fprintf(stderr, "\t-s file\t\tsignature to embed in input image\n");
+  fprintf(stderr, "\t-v n\t\tverbosity level\n");
+  exit(0);
+}
+
+int main(int argc, char *argv[]) {
+
+  FILE *in = stdin;
+  FILE *out = stdout;
+  FILE *sig = NULL;
+
+  char signature_name[MAXPATHLEN];
+  char input_name[MAXPATHLEN] = "(stdin)";
+  char output_name[MAXPATHLEN] = "(stdout)";
+
+  int i;
+  int j;
+  int c;
+  int n;
+  int x;
+  int y;
+
+  int seed;
+  int verbose = 0;
+
+  int rows, cols, format;
+  gray maxval;
+  int row, col;
+
+  int quantization = 0;
+  double quality = 0.0;
+
+  struct coords *coords;
+
+  gray **image;
+  double **dcts;
+
+  progname = argv[0]; 
+
+  pgm_init(&argc, argv); wm_init();
+
+  while ((c = getopt(argc, argv, "h?i:l:o:q:s:v:")) != EOF) {
+    switch (c) {
+      case 'h':
+      case '?':
+        usage();
+        break;
+      case 'l':
+        quality = atof(optarg);
+        if (quality <= 0.0) {
+          fprintf(stderr, "%s: signature strength factor %f out of range\n", progname, quality);
+          exit(1);
+        }
+        break;
+      case 'o':
+        if ((out = fopen(optarg, "wb")) == NULL) {
+          fprintf(stderr, "%s: unable to open output file %s\n", progname, optarg);
+          exit(1);
+        }
+        strcpy(output_name, optarg);
+        break;
+      case 'q':
+        quantization = atoi(optarg);
+        if (quantization <= 0 || quantization > 100) {
+          fprintf(stderr, "%s: quantization factor %d out of range\n", progname, quantization);
+          exit(1);
+        }
+        break;
+      case 's':
+        if ((sig = fopen(optarg, "r")) == NULL) {
+          fprintf(stderr, "%s: unable to open signature file %s\n", progname, optarg);
+          exit(1);
+        }
+        strcpy(signature_name, optarg);
+        break;
+      case 'v':
+        verbose = atoi(optarg);
+        if (verbose < 0) {
+          fprintf(stderr, "%s: verbosity level %d out of range\n", progname, verbose);
+          exit(1);
+        }
+        break;
+    }
+  }
+
+  argc -= optind;
+  argv += optind;
+
+  if (argc > 1) {
+    usage();
+    exit(1);
+  }
+
+  if (argc == 1 && *argv[0] != '-')
+    if ((in = fopen(argv[0], "rb")) == NULL) {
+      fprintf(stderr, "%s: unable to open input file %s\n", progname, argv[0]);
+      exit(1);
+    }
+    else
+      strcpy(input_name, argv[0]);
+
+  if (sig) {
+    char line[128];
+    fgets(line, sizeof(line), sig);
+    if (strspn(line, "KCSG") >= 4) {
+      fscanf(sig, "%d\n", &nbit_signature);
+      if (quality == 0.0)
+        fscanf(sig, "%lf\n", &quality);
+      else
+        fscanf(sig, "%*lf\n");
+      if (quantization == 0)
+        fscanf(sig, "%d\n", &quantization);
+      else
+        fscanf(sig, "%*d\n");
+      fscanf(sig, "%d\n", &seed);
+      n_signature = NBITSTOBYTES(nbit_signature);
+      fread(signature, sizeof(char), n_signature, sig);
+      fscanf(sig, "\n");
+      srandom(seed);
+    }
+    else {
+      fprintf(stderr, "%s: invalid signature file %s\n", progname, signature_name);
+      exit(1);
+    }
+    fclose(sig);
+  }
+  else {
+    fprintf(stderr, "%s: signature file not specified, use -s file option\n", progname);
+    exit(1);
+  }
+
+  pgm_readpgminit(in, &cols, &rows, &maxval, &format);
+
+  if (cols % NJPEG) {
+    fprintf(stderr, "%s: image width %d not a multiple of %d\n", progname, cols, NJPEG);
+    exit(1);
+  }
+
+  if (rows % NJPEG) {
+    fprintf(stderr, "%s: image height %d not a multiple of %d\n", progname, rows, NJPEG);
+    exit(1);
+  }
+
+  if ((cols * rows) / (NJPEG * NJPEG) < nbit_signature) {
+    fprintf(stderr, "%s: image not large enough to embed %d bits of signature\n", progname, nbit_signature);
+    exit(1);
+  }
+
+  init_dct_8x8();
+  init_quantum_JPEG_lumin(quantization);
+
+  dcts = alloc_coeffs_8x8();
+
+  if ((coords = alloc_coords(nbit_signature)) == NULL) {
+    fprintf(stderr, "%s: unable to allocate memory\n", progname);
+    exit(1);
+  }
+
+  image = pgm_allocarray(cols, rows);
+
+  for (row = 0; row < rows; row++)
+    pgm_readpgmrow(in, image[row], cols, maxval, format);
+
+  fclose(in);
+
+  // embedding signature bits by modifying two coefficient relationship,
+  // one bit for each block
+  n = 0;
+  while (n < nbit_signature) {
+    int xb;
+    int yb;
+    int c1, c2;
+    double v1, v2;
+    double w1, w2;
+    double diff, abs_diff;
+
+    // randomly select a block, check to get distinct blocks
+    // (don't watermark a block twice)
+    do {
+      xb = random() % (cols / NJPEG);
+      yb = random() % (rows / NJPEG);
+    } while (add_coord(coords, xb, yb) < 0);
+
+    // do the forward 8x8 DCT of that block
+    fdct_block_8x8(image, xb * NJPEG, yb * NJPEG, dcts);
+
+    // randomly select two distinct coefficients from block
+    // only accept coefficients in the middle frequency range
+    do {
+      c1 = (random() % (NJPEG * NJPEG - 2)) + 1;
+      c2 = (random() % (NJPEG * NJPEG - 2)) + 1;
+    } while (c1 == c2 || !is_middle_frequency_coeff_8x8(c1) || !is_middle_frequency_coeff_8x8(c2));
+
+    // quantize block according to quantization quality parameter
+    quantize_8x8(dcts);
+
+    if (verbose > 0)
+      fprintf(stderr, "%d: quantized DCT block (x %d/y %d), modifying (x %d/y %d), (x %d/y %d) for %s\n", n, xb * NJPEG, yb * NJPEG, c1 % NJPEG, c1 / NJPEG, c2 % NJPEG, c2 / NJPEG, get_signature_bit(n) ? "HIGH" : "LOW");
+    if (verbose > 5)
+      print_coeffs_8x8(dcts);
+
+    v1 = dcts[c1 / NJPEG][c1 % NJPEG];
+    v2 = dcts[c2 / NJPEG][c2 % NJPEG];
+
+    diff = fabs(v1) - fabs(v2);
+    abs_diff = (fabs(diff) + quality) / 2.0;
+
+    // modify coefficient's relationship to embed signature bit
+    // using mean square error to minimize error
+    if (get_signature_bit(n)) {
+      if (diff < quality) {
+        // we have to impose the relationship, does not occur naturally
+        w1 = (v1 > 0.0) ? (v1 + abs_diff) : (v1 - abs_diff);
+        w2 = (v2 > 0.0) ? (v2 - abs_diff) : (v2 + abs_diff);
+      }
+      else {
+        w1 = v1;
+        w2 = v2;
+      }
+    }
+    else {
+      if (diff > -quality) {
+        // force the relationship
+        w1 = (v1 > 0.0) ? (v1 - abs_diff) : (v1 + abs_diff);
+        w2 = (v2 > 0.0) ? (v2 + abs_diff) : (v2 - abs_diff);
+      }
+      else {
+        w1 = v1;
+        w2 = v2;
+      }
+    }
+
+    if (verbose > 1)
+      fprintf(stderr, "  %f -> %f, %f -> %f\n", v1, w1, v2, w2);
+
+    // put the changed coefficients back to black
+    dcts[c1 / NJPEG][c1 % NJPEG] = w1;
+    dcts[c2 / NJPEG][c2 % NJPEG] = w2;
+
+    // the obvious :-)
+    dequantize_8x8(dcts);
+
+    // do the inverse DCT on the modified 8x8 block
+    idct_block_8x8(dcts, image, xb * NJPEG, yb * NJPEG);
+
+    n++;
+  }
+
+  free_coeffs(dcts);
+
+  pgm_writepgminit(out, cols, rows, maxval, 0);
+  for (row = 0; row < rows; row++)
+    pgm_writepgmrow(out, image[row], cols, maxval, 0);
+
+  fclose(out);
+
+  pgm_freearray(image, rows);
+
+  exit(0);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Meerwald/wm_wang_d.c	Sun Aug 12 13:14:34 2007 +0200
@@ -0,0 +1,302 @@
+#include "wm.h"
+#include "dwt.h"
+#include "wang_common.h"
+#include "dwt_util.h"
+#include "pgm.h"
+
+char *progname;
+
+void usage(void) {
+  fprintf(stderr, "usage: %s [-a n] [-b n] [-e n] [-f n] [-F file] [-h] [-n n] [-o file] [-v n] -s file -i file file\n\n", progname);
+  fprintf(stderr, "\t-a n\t\talpha factor\n");
+  fprintf(stderr, "\t-b n\t\tbeta factor\n");
+  fprintf(stderr, "\t-e n\t\twavelet filtering method\n");
+  fprintf(stderr, "\t-f n\t\tfilter number\n");
+  fprintf(stderr, "\t-F file\t\tfilter definition file\n");
+  fprintf(stderr, "\t-h\t\tprint usage\n");
+  fprintf(stderr, "\t-i file\t\toriginal image file\n");
+  fprintf(stderr, "\t-n n\t\twatermark length\n");
+  fprintf(stderr, "\t-o file\t\tfile for extracted watermark\n");
+  fprintf(stderr, "\t-s file\t\toriginal signature file\n");
+  fprintf(stderr, "\t-v n\t\tverbosity level\n");
+  exit(0);
+}
+
+int main(int argc, char *argv[]) {
+
+  FILE *in = stdin;
+  FILE *out = stdout;
+  FILE *orig = NULL;
+  FILE *sig = NULL;
+
+  gray **input_image;
+  gray **orig_image;
+
+  char signature_name[MAXPATHLEN];
+  char output_name[MAXPATHLEN] = "(stdout)";
+  char input_name[MAXPATHLEN] = "(stdin)";
+  char orig_name[MAXPATHLEN];
+
+  int c, w;
+  int i;
+  int n = 0;
+  int method = -1;
+  int filter = 0;
+  char filter_name[MAXPATHLEN] = "";
+
+  int level, levels;
+  double alpha = 0.0;
+  double beta = 0.0;
+
+  int in_rows, in_cols, in_format;
+  gray in_maxval;
+  int orig_rows, orig_cols, orig_format;
+  gray orig_maxval;
+  int rows, cols;
+  int row, col;
+
+  double *watermark;
+
+  Image_tree input_dwts;
+  Image_tree orig_dwts;
+
+  int verbose = 0;
+
+  progname = argv[0];
+
+  pgm_init(&argc, argv); wm_init2();
+
+  while ((c = getopt(argc, argv, "a:b:e:f:F:h?i:n:o:s:v:")) != EOF) {
+    switch (c) {
+      case 'a':
+        alpha = atof(optarg);
+        if (alpha <= 0.0) {
+          fprintf(stderr, "%s: alpha factor %f out of range\n", progname, alpha);
+          exit(1);
+        }
+        break;
+      case 'b':
+        beta = atof(optarg);
+        if (beta <= 0.0) {
+          fprintf(stderr, "%s: beta factor %f out of range\n", progname, alpha);
+          exit(1);
+        }
+        break;
+      case 'e':
+        method = atoi(optarg);
+        if (method < 0) {
+          fprintf(stderr, "%s: wavelet filtering method %d out of range\n", progname, method);
+          exit(1);
+        }
+        break;
+      case 'f':
+        filter = atoi(optarg);
+        if (filter <= 0) {
+          fprintf(stderr, "%s: filter number %d out of range\n", progname, filter);
+          exit(1);
+        }
+        break;
+      case 'F':
+        strcpy(filter_name, optarg);
+        break;
+      case 'h':
+      case '?':
+        usage();
+        break;
+      case 'i':
+        if ((orig = fopen(optarg, "rb")) == NULL) {
+          fprintf(stderr, "%s: unable to open original image file %s\n", progname, optarg);
+          exit(1);
+        }
+        strcpy(orig_name, optarg);
+        break;
+      case 'n':
+        n = atoi(optarg);
+        if (n < 1 || n > 32000) {
+          fprintf(stderr, "%s: watermark length %d out of range\n", progname, n);
+          exit(1);
+        }
+        break;
+      case 'o':
+        if ((out = fopen(optarg, "w")) == NULL) {
+          fprintf(stderr, "%s: unable to open output file %s\n", progname, optarg);
+          exit(1);
+        }
+        strcpy(output_name, optarg);
+        break;
+      case 's':
+        if ((sig = fopen(optarg, "r")) == NULL) {
+          fprintf(stderr, "%s: unable to open signature file %s\n", progname, optarg);
+          exit(1);
+        }
+        strcpy(signature_name, optarg);
+        break;
+      case 'v':
+        verbose = atoi(optarg);
+        if (verbose < 0) {
+          fprintf(stderr, "%s: verbosity level %d out of range\n", progname, verbose);
+          exit(1);
+        }
+        break;
+    }
+  }
+
+  argc -= optind;
+  argv += optind;
+
+  if (argc > 1) {
+    usage();
+    exit(1);
+  }
+
+  if (argc == 1 && *argv[0] != '-')
+    if ((in = fopen(argv[0], "rb")) == NULL) {
+      fprintf(stderr, "%s: unable to open input file %s\n", progname, argv[0]);
+      exit(1);
+    }
+    else
+      strcpy(input_name, argv[0]);
+
+  if (!orig) {
+    fprintf(stderr, "%s: original image file not specified, use -i file option\n", progname);
+    exit(1);
+  }
+
+  if (sig) {
+    char line[32];
+    fgets(line, sizeof(line), sig);
+    if (strspn(line, "WGSG") >= 4) {
+      fscanf(sig, "%d\n", &n);
+      if (alpha == 0.0)
+        fscanf(sig, "%lf\n", &alpha);
+      else
+        fscanf(sig, "%*lf\n");
+      if (beta == 0.0)
+        fscanf(sig, "%lf\n", &beta);
+      else
+        fscanf(sig, "%*lf\n");
+      if (method < 0)
+        fscanf(sig, "%d\n", &method);
+      else
+        fscanf(sig, "%*d\n");
+      if (filter == 0)
+        fscanf(sig, "%d\n", &filter);
+      else
+        fscanf(sig, "%*d\n");
+      if (!strcmp(filter_name, ""))
+        fscanf(sig, "%[^\n\r]\n", &filter_name);
+      else
+        fscanf(sig, "%*[^\n\r]\n");
+    }
+    else {
+      fprintf(stderr, "%s: invalid signature file %s\n", progname, signature_name);
+      exit(1);
+    }
+    fclose(sig);
+  }
+  else {
+    fprintf(stderr, "%s: signature file not specified, use -s file option\n", progname);
+    exit(1);
+  }
+
+  watermark = malloc(n * sizeof(double));
+
+  pgm_readpgminit(in, &in_cols, &in_rows, &in_maxval, &in_format);
+  pgm_readpgminit(orig, &orig_cols, &orig_rows, &orig_maxval, &orig_format);
+
+  if (in_cols != orig_cols || in_rows != orig_rows) {
+    fprintf(stderr, "%s: input image %s does not match dimensions of original image %s\n", progname, input_name, orig_name);
+    exit(1);
+  }
+
+  cols = in_cols;
+  rows = in_rows;
+
+  input_image = pgm_allocarray(in_cols, in_rows);
+
+  orig_image = pgm_allocarray(orig_cols, orig_rows);
+
+  for (row = 0; row < in_rows; row++) {
+    pgm_readpgmrow(in, input_image[row], in_cols, in_maxval, in_format);
+    pgm_readpgmrow(orig, orig_image[row], orig_cols, orig_maxval, orig_format);
+  }
+
+  fclose(in);
+  fclose(orig);
+
+  // complete decomposition
+  levels = find_deepest_level(cols, rows) - 1;
+
+  init_dwt(cols, rows, filter_name, filter, levels, method);
+#ifdef POLLEN_STUFF
+#include "pollen_stuff.xxx"
+#endif
+#ifdef PARAM_STUFF
+#include "param_stuff.xxx"
+#endif
+
+  input_dwts = fdwt(input_image);
+  orig_dwts = fdwt(orig_image);
+
+  // build tree for subband selection, calculate subband thresholds
+  init_subbands(orig_dwts);
+  set_subbands_type_beta(HORIZONTAL, beta);
+  set_subbands_type_beta(VERTICAL, beta);
+  calc_subbands_threshold();
+
+  fprintf(out, "WGWM\n");
+  fprintf(out, "%d\n", n);
+
+  w = 0;
+  while (w < n) {
+    Subband_data s;
+
+    // select subband with max. threshold
+    s = select_subband();
+    if (verbose > 1)
+      fprintf(stderr, "%s: selected subband %s%d, T=%lf, beta=%lf\n", progname, subband_name(s->type), s->level, s->T, s->beta);
+
+    // watermark significant coefficients and set them selected
+    // check is entire signature has been embedded
+    c = select_subband_coeff(s);
+    do {
+      Pixel p;
+      Pixel q;
+      if (c < 0)
+        // no more significant coefficients in subband
+        break;
+
+      p = get_subband_coeff(s, c);
+      if (p < s->Cmax) {
+        q = get_dwt_coeff(input_dwts, s->level, s->type, c);
+        watermark[w] = (q - p) / (alpha * s->beta * s->T);
+        fprintf(out, "%lf\n", watermark[w]);
+
+        if (verbose > 2)
+          fprintf(stderr, "%s: detected sig. coeff. #%d (= %lf)\n  from %s%d coeff. #%d\n",
+            progname, w, watermark[w], subband_name(s->type), s->level, c);
+
+        w++;
+      }
+      mark_subband_coeff(s, c);
+
+      // select next significant coefficient
+      c = select_subband_coeff_from(s, c);
+    } while (w < n);
+
+    // update subband threshold
+    s->T /= 2.0;
+
+  }
+
+  fclose(out);
+
+  free_subbands();
+
+  free(watermark);
+
+  pgm_freearray(input_image, rows);
+  pgm_freearray(orig_image, rows);
+
+  exit(0);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Meerwald/wm_wang_e.c	Sun Aug 12 13:14:34 2007 +0200
@@ -0,0 +1,262 @@
+#include "wm.h"
+#include "dwt.h"
+#include "wang_common.h"
+#include "dwt_util.h"
+#include "pgm.h"
+
+char *progname;
+
+void usage(void) {
+  fprintf(stderr, "usage: %s [-a n] [-b n] [-e n] [-f n] [-F n] [-h] [-o file] [-v n] -s file file\n\n", progname);
+  fprintf(stderr, "\t-a n\t\talpha factor/embedding strength\n");
+  fprintf(stderr, "\t-b n\t\tsubband weighting factor\n");
+  fprintf(stderr, "\t-e n\t\twavelet filtering method\n");
+  fprintf(stderr, "\t-f n\t\tfilter number\n");
+  fprintf(stderr, "\t-F file\t\tfilter definition file\n");
+  fprintf(stderr, "\t-h\t\tprint usage\n");
+  fprintf(stderr, "\t-o file\t\toutput (watermarked) file\n");
+  fprintf(stderr, "\t-s file\t\tsignature to embed in input image\n");
+  fprintf(stderr, "\t-v n\t\tverbosity level\n");
+  exit(0);
+}
+
+int main(int argc, char *argv[]) {
+
+  FILE *in = stdin;
+  FILE *out = stdout;
+  FILE *sig = NULL;
+
+  char output_name[MAXPATHLEN] = "(stdout)";
+  char input_name[MAXPATHLEN] = "(stdin)";
+  char signature_name[MAXPATHLEN];
+
+  int i, c, w;
+  int row, col;
+
+  int n;
+
+  double alpha = 0.0;
+  double beta = 0.0;
+
+  int filter = 0;
+  int method = -1;
+  int levels;
+  char filter_name[MAXPATHLEN] = "";
+
+  int verbose = 0;
+
+  gray **image;
+  Image_tree dwts;
+
+  gray maxval;
+  int rows, cols, colors, format;
+
+  double *watermark;
+
+  progname = argv[0];
+
+  pgm_init(&argc, argv); wm_init();
+
+  while ((c = getopt(argc, argv, "a:b:e:f:F:h?o:s:v:")) != EOF) {
+    switch (c) {
+      case 'a':
+        alpha = atof(optarg);
+        if (alpha <= 0.0) {
+          fprintf(stderr, "%s: alpha factor %f out of range\n", progname, alpha);
+          exit(1);
+        }
+        break;
+      case 'b':
+        beta = atof(optarg);
+        if (beta <= 0.0) {
+          fprintf(stderr, "%s: beta factor %f out of range\n", progname, beta);
+          exit(1);
+        }
+        break;
+      case 'e':
+        method = atoi(optarg);
+        if (method < 0) {
+          fprintf(stderr, "%s: wavelet filtering method %d out of range\n", progname, method);
+          exit(1);
+        }
+        break;
+      case 'f':
+        filter = atoi(optarg);
+        if (filter <= 0) {
+          fprintf(stderr, "%s: filter number %d out of range\n", progname, filter);
+          exit(1);
+        }
+        break;
+      case 'F':
+        strcpy(filter_name, optarg);
+        break;
+      case 'h':
+      case '?':
+        usage();
+        break;
+      case 'o':
+        if ((out = fopen(optarg, "wb")) == NULL) {
+          fprintf(stderr, "%s: unable to open output file %s\n", progname, optarg);
+          exit(1);
+        }
+        strcpy(output_name, optarg);
+        break;
+      case 's':
+        if ((sig = fopen(optarg, "r")) == NULL) {
+          fprintf(stderr, "%s: unable to open signature file %s\n", progname, optarg);
+          exit(1);
+        }
+        strcpy(signature_name, optarg);
+        break;
+      case 'v':
+        verbose = atoi(optarg);
+        if (verbose < 0) {
+          fprintf(stderr, "%s: verbosity level %d out of range\n", progname, verbose);
+          exit(1);
+        }
+        break;
+    }
+  }
+
+  argc -= optind;
+  argv += optind;
+
+  if (argc > 1) {
+    usage();
+    exit(1);
+  }
+
+  if (argc == 1 && *argv[0] != '-')
+    if ((in = fopen(argv[0], "rb")) == NULL) {
+      fprintf(stderr, "%s: unable to open input file %s\n", progname, argv[0]);
+      exit(1);
+    }
+    else
+      strcpy(input_name, argv[0]);
+
+  if (sig) {
+    char line[32];
+    fgets(line, sizeof(line), sig);
+    if (strspn(line, "WGSG") >= 4) {
+      fscanf(sig, "%d\n", &n);
+      if (alpha == 0.0)
+        fscanf(sig, "%lf\n", &alpha);
+      else
+        fscanf(sig, "%*lf\n");
+      if (beta == 0.0)
+        fscanf(sig, "%lf\n", &beta);
+      else
+        fscanf(sig, "%*lf\n");
+      if (method < 0)
+        fscanf(sig, "%d\n", &method);
+      else
+        fscanf(sig, "%*d\n");
+      if (filter == 0)
+        fscanf(sig, "%d\n", &filter);
+      else
+        fscanf(sig, "%*d\n");
+      if (!strcmp(filter_name, ""))
+        fscanf(sig, "%[^\n\r]\n", &filter_name);
+      else
+        fscanf(sig, "%*[^\n\r]\n");
+    }
+    else {
+      fprintf(stderr, "%s: invalid signature file %s\n", progname, signature_name);
+      exit(1);
+    }
+  }
+  else {
+    fprintf(stderr, "%s: signature file not specified, use -s file option\n", progname);
+    exit(1);
+  }
+
+  watermark = malloc(n * sizeof(double));
+  for (i = 0; i < n; i++) 
+    fscanf(sig, "%lf\n", &watermark[i]);
+  fclose(sig);
+
+  pgm_readpgminit(in, &cols, &rows, &maxval, &format);
+
+  image = pgm_allocarray(cols, rows);
+
+  for (row = 0; row < rows; row++)
+    pgm_readpgmrow(in, image[row], cols, maxval, format);
+
+  fclose(in);
+
+  // complete decomposition
+  levels = find_deepest_level(cols, rows) - 1;
+
+  // wavelet transform
+  init_dwt(cols, rows, filter_name, filter, levels, method); 
+#ifdef POLLEN_STUFF
+#include "pollen_stuff.xxx"
+#endif
+#ifdef PARAM_STUFF
+#include "param_stuff.xxx"
+#endif
+
+  dwts = fdwt(image);
+
+  // build tree for subband selection, calculate subband thresholds
+  init_subbands(dwts);
+  set_subbands_type_beta(HORIZONTAL, beta);
+  set_subbands_type_beta(VERTICAL, beta);
+  calc_subbands_threshold();
+
+  w = 0;
+  while (w < n) {
+    Subband_data s;
+
+    // select subband with max. threshold
+    s = select_subband();
+    if (verbose > 1)
+      fprintf(stderr, "%s: selected subband %s%d, T=%lf, beta=%lf\n", progname, subband_name(s->type), s->level, s->T, s->beta);
+ 
+    // watermark significant coefficients and set them selected
+    // check is entire signature has been embedded
+    c = select_subband_coeff(s);
+    do {
+      double p;
+      if (c < 0) 
+        // no more significant coefficients in subband
+        break;
+
+      p = get_subband_coeff(s, c);
+      if (p < s->Cmax) {
+        if (verbose > 2)
+          fprintf(stderr, "%s: embedding sig. coeff. #%d (= %lf)\n  into %s%d coeff. #%d\n", 
+            progname, w, watermark[w], subband_name(s->type), s->level, c);
+
+        p = p + alpha * s->beta * s->T * watermark[w];
+        set_subband_coeff(s, c, p);
+        w++;
+      }
+      mark_subband_coeff(s, c);
+
+      // select next significant coefficient
+      c = select_subband_coeff_from(s, c);
+    } while (w < n);
+
+    // update subband threshold
+    s->T /= 2.0;
+
+  }
+
+  free_subbands();
+
+  free(watermark);
+
+  idwt(dwts, image);
+
+  pgm_writepgminit(out, cols, rows, maxval, 0);
+
+  for (row = 0; row < rows; row++)
+    pgm_writepgmrow(out, image[row], cols, maxval, 0);
+
+  fclose(out);
+
+  pgm_freearray(image, rows);
+
+  exit(0);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Meerwald/wm_xia_d.c	Sun Aug 12 13:14:34 2007 +0200
@@ -0,0 +1,295 @@
+#include "wm.h"
+#include "dwt.h"
+#include "pgm.h"
+#include "dwt_util.h"
+
+char *progname;
+
+void usage(void) {
+  fprintf(stderr, "usage: %s [-a n] [-e n] [-f n] [-F file] [-h] [-l n] [-o file] [-v n] -s file -i file file\n\n", progname);
+  fprintf(stderr, "\t-a n\t\talpha factor\n");
+  fprintf(stderr, "\t-e n\t\twavelet filtering method\n");
+  fprintf(stderr, "\t-f n\t\tfilter number\n");
+  fprintf(stderr, "\t-F file\t\tfilter definition file\n");
+  fprintf(stderr, "\t-h\t\tprint usage\n");
+  fprintf(stderr, "\t-i file\t\toriginal image file\n");
+  fprintf(stderr, "\t-l n\t\tdecomposition level\n");
+  fprintf(stderr, "\t-o file\t\tfile for extracted watermark\n");
+  fprintf(stderr, "\t-s file\t\toriginal signature file\n");
+  fprintf(stderr, "\t-v n\t\tverbosity level\n");
+  exit(0);
+}
+
+int extract_subband(Image_tree s, Image_tree t, int name, double alpha, double watermark[], int n, int verbose) {
+  int i, j;
+  int w;
+
+  w = 0;
+  for (i = 5; i < s->image->height-5; i++)
+    for (j = 5; j < s->image->width-5; j++) {
+      double input_coeff, orig_coeff;
+
+      input_coeff = get_pixel(s->image, i, j);
+      orig_coeff = get_pixel(t->image, i, j);
+      if (fabs(orig_coeff) > 20.0)
+        watermark[w++] = (input_coeff - orig_coeff) / (alpha * pow(fabs(orig_coeff), 1.0 / 1.2));
+    }
+
+  if (verbose > 3)
+    fprintf(stderr, "%s: extracting %s%d, size %d x %d; extracted %d coeffs.\n",
+      progname, subband_name(name), s->level, s->image->width, s->image->height, w);
+      
+  return w;
+}
+
+void write_mark(FILE *out, double watermark[], int n) {
+  int i;
+
+  fprintf(out, "%d\n", n);
+  for (i = 0; i < n; i++) 
+    fprintf(out, "%f\n", watermark[i]);
+}
+
+int main(int argc, char *argv[]) {
+
+  FILE *in = stdin;
+  FILE *out = stdout;
+  FILE *orig = NULL;
+  FILE *sig = NULL;
+
+  gray **input_image;
+  gray **orig_image;
+
+  char signature_name[MAXPATHLEN];
+  char output_name[MAXPATHLEN] = "(stdout)";
+  char input_name[MAXPATHLEN] = "(stdin)";
+  char orig_name[MAXPATHLEN];
+
+  int c, w;
+  int i;
+  int n = 0;
+  int method = -1;
+  int filter = 0;
+  char filter_name[MAXPATHLEN] = "";
+
+  int level = 0, levels;
+  double alpha = 0.0;
+
+  int in_rows, in_cols, in_format;
+  gray in_maxval;
+  int orig_rows, orig_cols, orig_format;
+  gray orig_maxval;
+  int rows, cols;
+  int row, col;
+
+  double *watermark;
+
+  Image_tree input_dwts, orig_dwts, p, q;
+
+  int verbose = 0;
+
+  progname = argv[0];
+
+  pgm_init(&argc, argv); wm_init2();
+
+  while ((c = getopt(argc, argv, "a:e:f:F:h?i:l:o:s:v:")) != EOF) {
+    switch (c) {
+      case 'a':
+        alpha = atof(optarg);
+        if (alpha <= 0.0) {
+          fprintf(stderr, "%s: alpha factor %f out of range\n", progname, alpha);
+          exit(1);
+        }
+        break;
+      case 'e':
+        method = atoi(optarg);
+        if (method < 0) {
+          fprintf(stderr, "%s: wavelet filtering method %d out of range\n", progname, method);
+          exit(1);
+        }
+        break;
+      case 'f':
+        filter = atoi(optarg);
+        if (filter <= 0) {
+          fprintf(stderr, "%s: filter number %d out of range\n", progname, filter);
+          exit(1);
+        }
+        break;
+      case 'F':
+        strcpy(filter_name, optarg);
+        break;
+      case 'h':
+      case '?':
+        usage();
+        break;
+      case 'i':
+        if ((orig = fopen(optarg, "rb")) == NULL) {
+          fprintf(stderr, "%s: unable to open original image file %s\n", progname, optarg);
+          exit(1);
+        }
+        strcpy(orig_name, optarg);
+        break;
+      case 'l':
+        level = atoi(optarg);  
+        if (level <= 0) { 
+          fprintf(stderr, "%s: decomposition level %d out of range\n", progname, level);
+          exit(1);
+        }
+        break;
+      case 'o':
+        if ((out = fopen(optarg, "w")) == NULL) {
+          fprintf(stderr, "%s: unable to open output file %s\n", progname, optarg);
+          exit(1);
+        }
+        strcpy(output_name, optarg);
+        break;
+      case 's':
+        if ((sig = fopen(optarg, "r")) == NULL) {
+          fprintf(stderr, "%s: unable to open signature file %s\n", progname, optarg);
+          exit(1);
+        }
+        strcpy(signature_name, optarg);
+        break;
+      case 'v':
+        verbose = atoi(optarg);
+        if (verbose < 0) {
+          fprintf(stderr, "%s: verbosity level %d out of range\n", progname, verbose);
+          exit(1);
+        }
+        break;
+    }
+  }
+
+  argc -= optind;
+  argv += optind;
+
+  if (argc > 1) {
+    usage();
+    exit(1);
+  }
+
+  if (argc == 1 && *argv[0] != '-')
+    if ((in = fopen(argv[0], "rb")) == NULL) {
+      fprintf(stderr, "%s: unable to open input file %s\n", progname, argv[0]);
+      exit(1);
+    }
+    else
+      strcpy(input_name, argv[0]);
+
+  if (!orig) {
+    fprintf(stderr, "%s: original image file not specified, use -i file option\n", progname);
+    exit(1);
+  }
+
+  if (sig) {
+    char line[32];
+    fgets(line, sizeof(line), sig);
+    if (strspn(line, "XASG") >= 4) {
+      fscanf(sig, "%d\n", &n);
+      if (alpha == 0.0)
+        fscanf(sig, "%lf\n", &alpha);
+      else
+        fscanf(sig, "%*lf\n");
+      if (level == 0)
+        fscanf(sig, "%d\n", &level);
+      else
+        fscanf(sig, "%*d\n");
+      if (method < 0)
+        fscanf(sig, "%d\n", &method);
+      else
+        fscanf(sig, "%*d\n");
+      if (filter == 0)
+        fscanf(sig, "%d\n", &filter);
+      else
+        fscanf(sig, "%*d\n");
+      if (!strcmp(filter_name, ""))
+        fscanf(sig, "%[^\n\r]\n", &filter_name);
+      else
+        fscanf(sig, "%*[^\n\r]\n");
+    }
+    else {
+      fprintf(stderr, "%s: invalid signature file %s\n", progname, signature_name);
+      exit(1);
+    }
+    fclose(sig);
+  }
+  else {
+    fprintf(stderr, "%s: signature file not specified, use -s file option\n", progname);
+    exit(1);
+  }
+
+  pgm_readpgminit(in, &in_cols, &in_rows, &in_maxval, &in_format);
+  pgm_readpgminit(orig, &orig_cols, &orig_rows, &orig_maxval, &orig_format);
+
+  if (in_cols != orig_cols || in_rows != orig_rows) {
+    fprintf(stderr, "%s: input image %s does not match dimensions of original image %s\n", progname, input_name, orig_name);
+    exit(1);
+  }
+
+  cols = in_cols;
+  rows = in_rows;
+
+  input_image = pgm_allocarray(in_cols, in_rows);
+  orig_image = pgm_allocarray(orig_cols, orig_rows);
+
+  for (row = 0; row < in_rows; row++) {
+    pgm_readpgmrow(in, input_image[row], in_cols, in_maxval, in_format);
+    pgm_readpgmrow(orig, orig_image[row], orig_cols, orig_maxval, orig_format);
+  }
+
+  fclose(in);
+  fclose(orig);
+
+  // complete decomposition
+  levels = find_deepest_level(cols, rows) - 1;
+  if (level > levels) {
+    fprintf(stderr, "%s: decomposition level %d not possible (max. %d), image size is %d x %d\n", progname, level, levels, cols, rows);
+    exit(1);
+  }
+
+  init_dwt(cols, rows, filter_name, filter, level, method);
+#ifdef POLLEN_STUFF
+#include "pollen_stuff.xxx"
+#endif
+#ifdef PARAM_STUFF
+#include "param_stuff.xxx"
+#endif
+
+  input_dwts = fdwt(input_image);
+  orig_dwts = fdwt(orig_image);
+
+  watermark = malloc((rows * cols / 4.0) * sizeof(double));
+  if (!watermark) {
+    fprintf(stderr, "%s: malloc() failed\n\n", progname);
+    exit(1);
+  }
+
+  fprintf(out, "XAWM\n");
+  fprintf(out, "%d\n", n);
+  fprintf(out, "%d\n", level * 3);
+
+  p = input_dwts;
+  q = orig_dwts;
+  while (p->coarse && q->coarse) { 
+    int size;
+    
+    size = extract_subband(p->horizontal, q->horizontal, HORIZONTAL, alpha, watermark, n, verbose);
+    write_mark(out, watermark, size);
+    size = extract_subband(p->vertical, q->vertical, VERTICAL, alpha, watermark, n, verbose);
+    write_mark(out, watermark, size);
+    size = extract_subband(p->diagonal, q->diagonal, DIAGONAL, alpha, watermark, n, verbose);
+    write_mark(out, watermark, size);
+        
+    p = p->coarse;
+    q = q->coarse;
+  }
+
+  fclose(out);
+
+  free(watermark);
+
+  pgm_freearray(input_image, rows);
+  pgm_freearray(orig_image, rows);
+
+  exit(0);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Meerwald/wm_xia_e.c	Sun Aug 12 13:14:34 2007 +0200
@@ -0,0 +1,243 @@
+#include "wm.h"
+#include "dwt.h"
+#include "pgm.h"
+#include "dwt_util.h"
+
+char *progname;
+
+void usage(void) {
+  fprintf(stderr, "usage: %s [-a n] [-e n] [-f n] [-F n] [-h] [-l n] [-o file] [-v n] -s file file\n\n", progname);
+  fprintf(stderr, "\t-a n\t\talpha factor/embedding strength\n");
+  fprintf(stderr, "\t-e n\t\twavelet filtering method\n");
+  fprintf(stderr, "\t-f n\t\tfilter number\n");
+  fprintf(stderr, "\t-F file\t\tfilter definition file\n");
+  fprintf(stderr, "\t-h\t\tprint usage\n");
+  fprintf(stderr, "\t-l n\t\tdecomposition level\n");
+  fprintf(stderr, "\t-o file\t\toutput (watermarked) file\n");
+  fprintf(stderr, "\t-s file\t\tsignature to embed in input image\n");
+  fprintf(stderr, "\t-v n\t\tverbosity level\n");
+  exit(0);
+}
+
+void mark_subband(Image_tree s, int name, double alpha, double watermark[], int n, int verbose) {
+  int i, j;
+  int w;
+
+  w = 0;
+  for (i = 5; i < s->image->height-5; i++) 
+    for (j = 5; j < s->image->width-5; j++) {
+      double coeff, newcoeff;
+
+      coeff = get_pixel(s->image, i, j);
+      if (fabs(coeff) > 20.0) {
+        newcoeff = coeff +  alpha * pow(fabs(coeff), 1.2) * watermark[w++ % n];
+        set_pixel(s->image, i, j, newcoeff);
+      }
+    }
+
+  if (verbose > 3)
+    fprintf(stderr, "%s: watermarking %s%d, size %d x %d; embedded %d coeffs.\n", 
+      progname, subband_name(name), s->level, s->image->width, s->image->height, w);
+}
+
+int main(int argc, char *argv[]) {
+
+  FILE *in = stdin;
+  FILE *out = stdout;
+  FILE *sig = NULL;
+
+  char output_name[MAXPATHLEN] = "(stdout)";
+  char input_name[MAXPATHLEN] = "(stdin)";
+  char signature_name[MAXPATHLEN];
+
+  int i, c, w;
+  int row, col;
+
+  int n;
+
+  double alpha = 0.0;
+  int level = 0;
+
+  int filter = 0;
+  int method = -1;
+  int levels;
+  char filter_name[MAXPATHLEN] = "";
+
+  int verbose = 0;
+
+  gray **image;
+  Image_tree p, dwts;
+
+  gray maxval;
+  int rows, cols, colors, format;
+
+  double *watermark;
+
+  progname = argv[0];
+
+  pgm_init(&argc, argv); wm_init();
+
+  while ((c = getopt(argc, argv, "a:e:f:F:h?o:l:s:v:")) != EOF) {
+    switch (c) {
+      case 'a':
+        alpha = atof(optarg);
+        if (alpha <= 0.0) {
+          fprintf(stderr, "%s: alpha factor %f out of range\n", progname, alpha);
+          exit(1);
+        }
+        break;
+      case 'l':
+        level = atoi(optarg);
+        if (level <= 0) {
+          fprintf(stderr, "%s: decomposition level %d out of range\n", progname, level);
+          exit(1);
+        }
+        break;
+      case 'e':
+        method = atoi(optarg);
+        if (method < 0) {
+          fprintf(stderr, "%s: wavelet filtering method %d out of range\n", progname, method);
+          exit(1);
+        }
+        break;
+      case 'f':
+        filter = atoi(optarg);
+        if (filter <= 0) {
+          fprintf(stderr, "%s: filter number %d out of range\n", progname, filter);
+          exit(1);
+        }
+        break;
+      case 'F':
+        strcpy(filter_name, optarg);
+        break;
+      case 'h':
+      case '?':
+        usage();
+        break;
+      case 'o':
+        if ((out = fopen(optarg, "wb")) == NULL) {
+          fprintf(stderr, "%s: unable to open output file %s\n", progname, optarg);
+          exit(1);
+        }
+        strcpy(output_name, optarg);
+        break;
+      case 's':
+        if ((sig = fopen(optarg, "r")) == NULL) {
+          fprintf(stderr, "%s: unable to open signature file %s\n", progname, optarg);
+          exit(1);
+        }
+        strcpy(signature_name, optarg);
+        break;
+      case 'v':
+        verbose = atoi(optarg);
+        if (verbose < 0) {
+          fprintf(stderr, "%s: verbosity level %d out of range\n", progname, verbose);
+          exit(1);
+        }
+        break;
+    }
+  }
+
+  argc -= optind;
+  argv += optind;
+
+  if (argc > 1) {
+    usage();
+    exit(1);
+  }
+
+  if (argc == 1 && *argv[0] != '-')
+    if ((in = fopen(argv[0], "rb")) == NULL) {
+      fprintf(stderr, "%s: unable to open input file %s\n", progname, argv[0]);
+      exit(1);
+    }
+    else
+      strcpy(input_name, argv[0]);
+
+  if (sig) {
+    char line[32];
+    fgets(line, sizeof(line), sig);
+    if (strspn(line, "XASG") >= 4) {
+      fscanf(sig, "%d\n", &n);
+      if (alpha == 0.0)
+        fscanf(sig, "%lf\n", &alpha);
+      else
+        fscanf(sig, "%*lf\n");
+      if (level == 0)
+        fscanf(sig, "%d\n", &level);
+      else
+        fscanf(sig, "%*d\n");
+      if (method < 0)
+        fscanf(sig, "%d\n", &method);
+      else
+        fscanf(sig, "%*d\n");
+      if (filter == 0)
+        fscanf(sig, "%d\n", &filter);
+      else
+        fscanf(sig, "%*d\n");
+      if (!strcmp(filter_name, ""))
+        fscanf(sig, "%[^\n\r]\n", &filter_name);
+      else
+        fscanf(sig, "%*[^\n\r]\n");
+    }
+    else {
+      fprintf(stderr, "%s: invalid signature file %s\n", progname, signature_name);
+      exit(1);
+    }
+  }
+  else {
+    fprintf(stderr, "%s: signature file not specified, use -s file option\n", progname);
+    exit(1);
+  }
+
+  watermark = malloc(n * sizeof(double));
+  for (i = 0; i < n; i++) 
+    fscanf(sig, "%lf\n", &watermark[i]);
+  fclose(sig);
+
+  pgm_readpgminit(in, &cols, &rows, &maxval, &format);
+  image = pgm_allocarray(cols, rows);
+  for (row = 0; row < rows; row++)
+    pgm_readpgmrow(in, image[row], cols, maxval, format);
+  fclose(in);
+
+  // complete decomposition
+  levels = find_deepest_level(cols, rows) - 1;
+  if (level > levels) {
+    fprintf(stderr, "%s: decomposition level %d not possible (max. %d), image size is %d x %d\n", progname, level, levels, cols, rows);
+    exit(1);
+  }
+
+  // wavelet transform
+  init_dwt(cols, rows, filter_name, filter, level, method);
+#ifdef POLLEN_STUFF
+#include "pollen_stuff.xxx"
+#endif
+#ifdef PARAM_STUFF
+#include "param_stuff.xxx"
+#endif
+
+  dwts = fdwt(image);
+
+  p = dwts;
+  while (p->coarse) {
+
+    mark_subband(p->horizontal, HORIZONTAL, alpha, watermark, n, verbose);
+    mark_subband(p->vertical, VERTICAL, alpha, watermark, n, verbose);
+    mark_subband(p->diagonal, DIAGONAL, alpha, watermark, n, verbose);
+
+    p = p->coarse;
+  }
+
+  free(watermark);
+  idwt(dwts, image);
+
+  pgm_writepgminit(out, cols, rows, maxval, 0);
+  for (row = 0; row < rows; row++)
+    pgm_writepgmrow(out, image[row], cols, maxval, 0);
+  fclose(out);
+
+  pgm_freearray(image, rows);
+
+  exit(0);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Meerwald/wm_xie_d.c	Sun Aug 12 13:14:34 2007 +0200
@@ -0,0 +1,257 @@
+#include "wm.h"
+#include "signature.h"
+#include "dwt.h"
+#include "pgm.h"
+
+char *progname;
+
+// inverse watermarking transformation, extract embedded bit, check quantization boundaries
+double wm_transform(double alpha, double f1, double f2, double f3) {
+  double s = alpha * (fabs(f3) - fabs(f1)) / 2.0;
+  double l = f1;
+  int x;
+  
+  x = 0;
+  while (l  < f2) {
+    l += s;
+    x++;
+  }
+
+  if (fabs(l - s - f2) < fabs(l-f2))
+    return (x+1) % 2;
+  else 
+    return (x) % 2;
+}
+
+void usage(void) {
+  fprintf(stderr, "usage: %s [-a n] [-e n] [-f n] [-F n] [-h] [-l n] [-o file] [-v n] -s file file\n\n", progname);
+  fprintf(stderr, "\t-a n\t\tembedding strength (default 0.05)\n");
+  fprintf(stderr, "\t-e n\t\twavelet filtering method\n");
+  fprintf(stderr, "\t-f n\t\tfilter number\n");
+  fprintf(stderr, "\t-F file\t\tfilter definition file\n");
+  fprintf(stderr, "\t-l n\t\tembedding level\n");
+  fprintf(stderr, "\t-h\t\tprint usage\n");
+  fprintf(stderr, "\t-o file\t\textracted signature file\n");
+  fprintf(stderr, "\t-s file\t\tsignature to embed in input image\n");
+  fprintf(stderr, "\t-v n\t\tverbosity level\n");
+  exit(0);
+}
+
+int main(int argc, char *argv[]) {
+
+  FILE *in = stdin;
+  FILE *out = stdout;
+  FILE *sig = NULL;
+
+  char output_name[MAXPATHLEN] = "(stdout)";
+  char input_name[MAXPATHLEN] = "(stdin)";
+  char signature_name[MAXPATHLEN];
+
+  int c, n;
+  int row, col;
+
+  double alpha = 0.0;
+  int filter = 0;
+  int method = -1;
+  int level = 0;
+  char filter_name[MAXPATHLEN] = "";
+
+  int seed;
+  int verbose = 0;
+
+  gray **image;
+  Image_tree dwts, p;
+
+  gray maxval;
+  int rows, cols, colors, format;
+
+  progname = argv[0];
+
+  pgm_init(&argc, argv); wm_init2();
+
+  while ((c = getopt(argc, argv, "a:e:f:F:h?l:o:s:v:")) != EOF) {
+    switch (c) {
+      case 'e':
+        method = atoi(optarg);
+        if (method < 0) {
+          fprintf(stderr, "%s: wavelet filtering method %d out of range\n", progname, method);
+          exit(1);
+        }
+        break;
+      case 'f':
+        filter = atoi(optarg);
+        if (filter <= 0) {
+          fprintf(stderr, "%s: filter number %d out of range\n", progname, filter);
+          exit(1);
+        }
+        break;
+      case 'F':
+        strcpy(filter_name, optarg);
+        break;
+      case 'h':
+      case '?':
+        usage();
+        break;
+      case 'l':
+        level = atoi(optarg);
+        if (level < 1) {
+          fprintf(stderr, "%s: embedding level out of range\n", progname);
+          exit(1);
+        }
+        break;       
+      case 'o':
+        if ((out = fopen(optarg, "wb")) == NULL) {
+          fprintf(stderr, "%s: unable to open output file %s\n", progname, optarg);
+          exit(1);
+        }
+        strcpy(output_name, optarg);
+        break;
+      case 'a':
+        alpha = atof(optarg);
+        if (alpha <= 0.0) {
+          fprintf(stderr, "%s: embedding strength factor %f out of range\n", progname, alpha);
+          exit(1);
+        }
+        break;
+      case 's':
+        if ((sig = fopen(optarg, "r")) == NULL) {
+          fprintf(stderr, "%s: unable to open signature file %s\n", progname, optarg);
+          exit(1);
+        }
+        strcpy(signature_name, optarg);
+        break;
+      case 'v':
+        verbose = atoi(optarg);
+        if (verbose < 0) {
+          fprintf(stderr, "%s: verbosity level %d out of range\n", progname, verbose);
+          exit(1);
+        }
+        break;
+    }
+  }
+
+  argc -= optind;
+  argv += optind;
+
+  if (argc > 1) {
+    usage();
+    exit(1);
+  }
+
+  if (argc == 1 && *argv[0] != '-')
+    if ((in = fopen(argv[0], "rb")) == NULL) {
+      fprintf(stderr, "%s: unable to open input file %s\n", progname, argv[0]);
+      exit(1);
+    }
+    else
+      strcpy(input_name, argv[0]);
+
+  if (sig) {
+    char line[32];
+    fgets(line, sizeof(line), sig);
+    if (strspn(line, "XESG") >= 4) {
+      fscanf(sig, "%d\n", &nbit_signature);
+      if (alpha == 0.0)
+        fscanf(sig, "%lf\n", &alpha);
+      else
+        fscanf(sig, "%*lf\n");
+      if (method < 0)
+        fscanf(sig, "%d\n", &method);
+      else
+        fscanf(sig, "%*d\n");
+      if (filter == 0)
+        fscanf(sig, "%d\n", &filter);
+      else
+        fscanf(sig, "%*d\n");
+      if (!strcmp(filter_name, ""))
+        fscanf(sig, "%[^\n\r]\n", &filter_name);
+      else
+        fscanf(sig, "%*[^\n\r]\n");
+      if (level == 0)
+        fscanf(sig, "%d\n", &level);
+      else
+        fscanf(sig, "%*d\n");
+      fscanf(sig, "%d\n", &seed);
+      srandom(seed);
+      n_signature = NBITSTOBYTES(nbit_signature);
+      fread(signature, sizeof(char), n_signature, sig);
+      fscanf(sig, "\n");
+    }
+    else {
+      fprintf(stderr, "%s: invalid signature file %s\n", progname, signature_name);
+      exit(1);
+    }
+    fclose(sig);
+  }
+  else {
+    fprintf(stderr, "%s: signature file not specified, use -s file option\n", progname);
+    exit(1);
+  }
+
+  pgm_readpgminit(in, &cols, &rows, &maxval, &format);
+  if (verbose > 0) 
+    fprintf(stderr, "%s: embedding %d bits with strength %f in\n"
+                    "  %d x %d host image, decomposition level %d\n",
+                    progname, nbit_signature, alpha, cols, rows, level);
+
+  image = pgm_allocarray(cols, rows);
+  for (row = 0; row < rows; row++)
+    pgm_readpgmrow(in, image[row], cols, maxval, format);
+  fclose(in);
+
+  // decomposition of image
+  init_dwt(cols, rows, filter_name, filter, level, method);
+#ifdef POLLEN_STUFF
+#include "pollen_stuff.xxx"
+#endif
+#ifdef PARAM_STUFF
+#include "param_stuff.xxx"
+#endif
+
+  dwts = fdwt(image);
+
+  p = dwts;
+
+  // consider each resolution level
+  while (p->level < level) 
+    // descend one level
+    p = p->coarse;
+
+  // repeat binary watermark by sliding a 3-pixel window of approximation image
+  n = 0;
+  for (row = 0; row < p->image->height; row++) {
+    for (col = 0; col < p->image->width - 3; col += 3) {
+      double b1, b2, b3;
+      double *f1 = &b1, *f2 = &b2, *f3 = &b3;
+
+      // get all three approximation pixels in window
+      b1 = get_pixel(p->image, col + 0, row);
+      b2 = get_pixel(p->image, col + 1, row);
+      b3 = get_pixel(p->image, col + 2, row);
+
+      // bring selected pixels in ascending order
+#define SWAP(A, B) {double *t = A; A = B; B = t;}
+      if (*f1 > *f2) SWAP(f1, f2);
+      if (*f2 > *f3) SWAP(f2, f3);
+      if (*f1 > *f2) SWAP(f1, f2);
+
+      set_signature_bit(n, wm_transform(alpha, *f1, *f2, *f3));
+
+      if (verbose > 1)
+        fprintf(stderr, "%s: extracting #%d (= %d) at (%d/%d); %f < %f < %f\n",
+          progname, n, get_signature_bit(n % nbit_signature), col, row, *f1, *f2, *f3);
+
+      n++;
+    }
+  }
+
+  fprintf(out, "XEWM\n");  
+  fprintf(out, "%d\n", n);
+  fwrite(signature, sizeof(char), NBITSTOBYTES(n), out);
+  fprintf(out, "\n");
+  fclose(out);
+
+  pgm_freearray(image, rows);
+
+  exit(0);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Meerwald/wm_xie_e.c	Sun Aug 12 13:14:34 2007 +0200
@@ -0,0 +1,269 @@
+#include "wm.h"
+#include "signature.h"
+#include "dwt.h"
+#include "pgm.h"
+
+char *progname;
+
+// watermarking transformation, set median pixel to quantization boundary
+double wm_transform(double alpha, double f1, double f2, double f3, int x) {
+  double s = alpha * (fabs(f3) - fabs(f1)) / 2.0;
+  double l = x ? (f1 + s) : f1;
+  double f2new;
+  
+  while ((l + 2 * s) < f2) l += 2 * s;
+  f2new = ((f2 - l) < (l + 2 * s - f2)) ? l : (l + 2 * s);
+
+  return f2new;
+}
+
+void usage(void) {
+  fprintf(stderr, "usage: %s [-a n] [-e n] [-f n] [-F n] [-h] [-l n] [-o file] [-v n] -s file file\n\n", progname);
+  fprintf(stderr, "\t-a n\t\tembedding strength (default 0.05)\n");
+  fprintf(stderr, "\t-e n\t\twavelet filtering method\n");
+  fprintf(stderr, "\t-f n\t\tfilter number\n");
+  fprintf(stderr, "\t-F file\t\tfilter definition file\n");
+  fprintf(stderr, "\t-l n\t\tembedding level\n");
+  fprintf(stderr, "\t-h\t\tprint usage\n");
+  fprintf(stderr, "\t-o file\t\toutput (watermarked) file\n");
+  fprintf(stderr, "\t-s file\t\tsignature to embed in input image\n");
+  fprintf(stderr, "\t-v n\t\tverbosity level\n");
+  exit(0);
+}
+
+int main(int argc, char *argv[]) {
+
+  FILE *in = stdin;
+  FILE *out = stdout;
+  FILE *sig = NULL;
+
+  char output_name[MAXPATHLEN] = "(stdout)";
+  char input_name[MAXPATHLEN] = "(stdin)";
+  char signature_name[MAXPATHLEN];
+
+  int c, n;
+  int row, col;
+
+  double alpha = 0.0;
+  int filter = 0;
+  int method = -1;
+  int level = 0;
+  char filter_name[MAXPATHLEN] = "";
+
+  int seed;
+  int verbose = 0;
+
+  gray **image;
+  Image_tree dwts, p;
+
+  gray maxval;
+  int rows, cols, colors, format;
+
+  progname = argv[0];
+
+  pgm_init(&argc, argv); wm_init();
+
+  while ((c = getopt(argc, argv, "a:e:f:F:h?l:o:s:v:")) != EOF) {
+    switch (c) {
+      case 'e':
+        method = atoi(optarg);
+        if (method < 0) {
+          fprintf(stderr, "%s: wavelet filtering method %d out of range\n", progname, method);
+          exit(1);
+        }
+        break;
+      case 'f':
+        filter = atoi(optarg);
+        if (filter <= 0) {
+          fprintf(stderr, "%s: filter number %d out of range\n", progname, filter);
+          exit(1);
+        }
+        break;
+      case 'F':
+        strcpy(filter_name, optarg);
+        break;
+      case 'h':
+      case '?':
+        usage();
+        break;
+      case 'l':
+        level = atoi(optarg);
+        if (level < 1) {
+          fprintf(stderr, "%s: embedding level out of range\n", progname);
+          exit(1);
+        }
+        break;       
+      case 'o':
+        if ((out = fopen(optarg, "wb")) == NULL) {
+          fprintf(stderr, "%s: unable to open output file %s\n", progname, optarg);
+          exit(1);
+        }
+        strcpy(output_name, optarg);
+        break;
+      case 'a':
+        alpha = atof(optarg);
+        if (alpha <= 0.0) {
+          fprintf(stderr, "%s: embedding strength factor %f out of range\n", progname, alpha);
+          exit(1);
+        }
+        break;
+      case 's':
+        if ((sig = fopen(optarg, "r")) == NULL) {
+          fprintf(stderr, "%s: unable to open signature file %s\n", progname, optarg);
+          exit(1);
+        }
+        strcpy(signature_name, optarg);
+        break;
+      case 'v':
+        verbose = atoi(optarg);
+        if (verbose < 0) {
+          fprintf(stderr, "%s: verbosity level %d out of range\n", progname, verbose);
+          exit(1);
+        }
+        break;
+    }
+  }
+
+  argc -= optind;
+  argv += optind;
+
+  if (argc > 1) {
+    usage();
+    exit(1);
+  }
+
+  if (argc == 1 && *argv[0] != '-')
+    if ((in = fopen(argv[0], "rb")) == NULL) {
+      fprintf(stderr, "%s: unable to open input file %s\n", progname, argv[0]);
+      exit(1);
+    }
+    else
+      strcpy(input_name, argv[0]);
+
+  if (sig) {
+    char line[32];
+    fgets(line, sizeof(line), sig);
+    if (strspn(line, "XESG") >= 4) {
+      fscanf(sig, "%d\n", &nbit_signature);
+      if (alpha == 0.0)
+        fscanf(sig, "%lf\n", &alpha);
+      else
+        fscanf(sig, "%*lf\n");
+      if (method < 0)
+        fscanf(sig, "%d\n", &method);
+      else
+        fscanf(sig, "%*d\n");
+      if (filter == 0)
+        fscanf(sig, "%d\n", &filter);
+      else
+        fscanf(sig, "%*d\n");
+      if (!strcmp(filter_name, ""))
+        fscanf(sig, "%[^\n\r]\n", &filter_name);
+      else
+        fscanf(sig, "%*[^\n\r]\n");
+      if (level == 0)
+        fscanf(sig, "%d\n", &level);
+      else
+        fscanf(sig, "%*d\n");
+      fscanf(sig, "%d\n", &seed);
+      srandom(seed);
+      n_signature = NBITSTOBYTES(nbit_signature);
+      fread(signature, sizeof(char), n_signature, sig);
+      fscanf(sig, "\n");
+    }
+    else {
+      fprintf(stderr, "%s: invalid signature file %s\n", progname, signature_name);
+      exit(1);
+    }
+    fclose(sig);
+  }
+  else {
+    fprintf(stderr, "%s: signature file not specified, use -s file option\n", progname);
+    exit(1);
+  }
+
+  pgm_readpgminit(in, &cols, &rows, &maxval, &format);
+
+  if (verbose > 0) 
+    fprintf(stderr, "%s: embedding %d bits with strength %f in\n"
+                    "  %d x %d host image, decomposition level %d\n",
+                    progname, nbit_signature, alpha, cols, rows, level);
+
+  image = pgm_allocarray(cols, rows);
+
+  for (row = 0; row < rows; row++)
+    pgm_readpgmrow(in, image[row], cols, maxval, format);
+
+  fclose(in);
+
+  // decomposition of image
+  init_dwt(cols, rows, filter_name, filter, level, method);
+#ifdef POLLEN_STUFF
+#include "pollen_stuff.xxx"
+#endif
+#ifdef PARAM_STUFF
+#include "param_stuff.xxx"
+#endif
+
+  dwts = fdwt(image);
+
+  p = dwts;
+
+  // consider each resolution level
+  while (p->level < level) 
+    // descend one level
+    p = p->coarse;
+
+  // repeat binary watermark by sliding a 3-pixel window of approximation image
+  n = 0;
+  for (row = 0; row < p->image->height; row++) {
+    for (col = 0; col < p->image->width - 3; col += 3) {
+      double b1, b2, b3;
+      double *f1 = &b1, *f2 = &b2, *f3 = &b3;
+      double f2new;
+
+      // get all three approximation pixels in window
+      b1 = get_pixel(p->image, col + 0, row);
+      b2 = get_pixel(p->image, col + 1, row);
+      b3 = get_pixel(p->image, col + 2, row);
+
+      // bring selected pixels in ascending order
+#define SWAP(A, B) {double *t = A; A = B; B = t;}
+      if (*f1 > *f2) SWAP(f1, f2);
+      if (*f2 > *f3) SWAP(f2, f3);
+      if (*f1 > *f2) SWAP(f1, f2);
+
+      // apply watermarking transformation (modify median pixel)
+      f2new = wm_transform(alpha, *f1, *f2, *f3, get_signature_bit(n % nbit_signature));
+
+      if (verbose > 1)
+        fprintf(stderr, "%s: embedding #%d (= %d) at (%d/%d); %f < %f -> %f < %f\n",
+          progname, n, get_signature_bit(n % nbit_signature), col, row, *f1, *f2, f2new, *f3);
+
+      *f2 = f2new;
+
+      // write modified pixel     
+      set_pixel(p->image, col + 0, row, b1);
+      set_pixel(p->image, col + 1, row, b2);
+      set_pixel(p->image, col + 2, row, b3);
+      
+      n++;
+    }
+  }
+
+    
+  // skip over some pixels
+
+  idwt(dwts, image);
+
+  pgm_writepgminit(out, cols, rows, maxval, 0);
+
+  for (row = 0; row < rows; row++)
+    pgm_writepgmrow(out, image[row], cols, maxval, 0);
+
+  fclose(out);
+
+  pgm_freearray(image, rows);
+
+  exit(0);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Meerwald/wm_zhu_d.c	Sun Aug 12 13:14:34 2007 +0200
@@ -0,0 +1,304 @@
+#include "wm.h"
+#include "dwt.h"
+#include "pgm.h"
+
+char *progname;
+
+void usage(void) {
+  fprintf(stderr, "usage: %s [-a n] [-e n] [-f n] [-F file] [-h] [-l n] [-o file] [-v n] -s file -i file file\n\n", progname);
+  fprintf(stderr, "\t-a n\t\talpha factor\n");
+  fprintf(stderr, "\t-b n\t\tbeta factor\n");
+  fprintf(stderr, "\t-e n\t\twavelet filtering method\n");
+  fprintf(stderr, "\t-f n\t\tfilter number\n");
+  fprintf(stderr, "\t-F file\t\tfilter definition file\n");
+  fprintf(stderr, "\t-h\t\tprint usage\n");
+  fprintf(stderr, "\t-i file\t\toriginal image file\n");
+  fprintf(stderr, "\t-l n\t\tdecomposition level\n");
+  fprintf(stderr, "\t-o file\t\tfile for extracted watermark\n");
+  fprintf(stderr, "\t-s file\t\toriginal signature file\n");
+  fprintf(stderr, "\t-v n\t\tverbosity level\n");
+  exit(0);
+}
+
+void write_mark(FILE *out, double watermark[], int n) {
+  int i;
+
+  fprintf(out, "%d\n", n);
+  for (i = 0; i < n; i++) 
+    fprintf(out, "%f\n", watermark[i]);
+}
+
+int main(int argc, char *argv[]) {
+
+  FILE *in = stdin;
+  FILE *out = stdout;
+  FILE *orig = NULL;
+  FILE *sig = NULL;
+
+  gray **input_image;
+  gray **orig_image;
+
+  char signature_name[MAXPATHLEN];
+  char output_name[MAXPATHLEN] = "(stdout)";
+  char input_name[MAXPATHLEN] = "(stdin)";
+  char orig_name[MAXPATHLEN];
+
+  int c, w;
+  int i;
+  int n = 0;
+  int method = -1;
+  int filter = 0;
+  char filter_name[MAXPATHLEN] = "";
+
+  int level = 0, levels;
+  double alpha = 0.0;
+
+  int in_rows, in_cols, in_format;
+  gray in_maxval;
+  int orig_rows, orig_cols, orig_format;
+  gray orig_maxval;
+  int rows, cols;
+  int row, col;
+
+  double *watermark;
+
+  Image_tree input_dwts, orig_dwts, p, q;
+
+  int verbose = 0;
+
+  progname = argv[0];
+
+  pgm_init(&argc, argv); wm_init2();
+
+  while ((c = getopt(argc, argv, "a:e:f:F:h?i:l:o:s:v:")) != EOF) {
+    switch (c) {
+      case 'a':
+        alpha = atof(optarg);
+        if (alpha <= 0.0) {
+          fprintf(stderr, "%s: alpha factor %f out of range\n", progname, alpha);
+          exit(1);
+        }
+        break;
+      case 'e':
+        method = atoi(optarg);
+        if (method < 0) {
+          fprintf(stderr, "%s: wavelet filtering method %d out of range\n", progname, method);
+          exit(1);
+        }
+        break;
+      case 'f':
+        filter = atoi(optarg);
+        if (filter <= 0) {
+          fprintf(stderr, "%s: filter number %d out of range\n", progname, filter);
+          exit(1);
+        }
+        break;
+      case 'F':
+        strcpy(filter_name, optarg);
+        break;
+      case 'h':
+      case '?':
+        usage();
+        break;
+      case 'i':
+        if ((orig = fopen(optarg, "rb")) == NULL) {
+          fprintf(stderr, "%s: unable to open original image file %s\n", progname, optarg);
+          exit(1);
+        }
+        strcpy(orig_name, optarg);
+        break;
+      case 'l':
+        level = atoi(optarg);  
+        if (level <= 0) { 
+          fprintf(stderr, "%s: decomposition level %d out of range\n", progname, level);
+          exit(1);
+        }
+        break;
+      case 'o':
+        if ((out = fopen(optarg, "w")) == NULL) {
+          fprintf(stderr, "%s: unable to open output file %s\n", progname, optarg);
+          exit(1);
+        }
+        strcpy(output_name, optarg);
+        break;
+      case 's':
+        if ((sig = fopen(optarg, "r")) == NULL) {
+          fprintf(stderr, "%s: unable to open signature file %s\n", progname, optarg);
+          exit(1);
+        }
+        strcpy(signature_name, optarg);
+        break;
+      case 'v':
+        verbose = atoi(optarg);
+        if (verbose < 0) {
+          fprintf(stderr, "%s: verbosity level %d out of range\n", progname, verbose);
+          exit(1);
+        }
+        break;
+    }
+  }
+
+  argc -= optind;
+  argv += optind;
+
+  if (argc > 1) {
+    usage();
+    exit(1);
+  }
+
+  if (argc == 1 && *argv[0] != '-')
+    if ((in = fopen(argv[0], "rb")) == NULL) {
+      fprintf(stderr, "%s: unable to open input file %s\n", progname, argv[0]);
+      exit(1);
+    }
+    else
+      strcpy(input_name, argv[0]);
+
+  if (!orig) {
+    fprintf(stderr, "%s: original image file not specified, use -i file option\n", progname);
+    exit(1);
+  }
+
+  if (sig) {
+    char line[32];
+    fgets(line, sizeof(line), sig);
+    if (strspn(line, "ZHSG") >= 4) {
+      fscanf(sig, "%d\n", &n);
+      if (alpha == 0.0)
+        fscanf(sig, "%lf\n", &alpha);
+      else
+        fscanf(sig, "%*lf\n");
+      if (level == 0)
+        fscanf(sig, "%d\n", &level);
+      else
+        fscanf(sig, "%*d\n");
+      if (method < 0)
+        fscanf(sig, "%d\n", &method);
+      else
+        fscanf(sig, "%*d\n");
+      if (filter == 0)
+        fscanf(sig, "%d\n", &filter);
+      else
+        fscanf(sig, "%*d\n");
+      if (!strcmp(filter_name, ""))
+        fscanf(sig, "%[^\n\r]\n", &filter_name);
+      else
+        fscanf(sig, "%*[^\n\r]\n");
+    }
+    else {
+      fprintf(stderr, "%s: invalid signature file %s\n", progname, signature_name);
+      exit(1);
+    }
+    fclose(sig);
+  }
+  else {
+    fprintf(stderr, "%s: signature file not specified, use -s file option\n", progname);
+    exit(1);
+  }
+
+  pgm_readpgminit(in, &in_cols, &in_rows, &in_maxval, &in_format);
+  pgm_readpgminit(orig, &orig_cols, &orig_rows, &orig_maxval, &orig_format);
+
+  if (in_cols != orig_cols || in_rows != orig_rows) {
+    fprintf(stderr, "%s: input image %s does not match dimensions of original image %s\n", progname, input_name, orig_name);
+    exit(1);
+  }
+
+  cols = in_cols;
+  rows = in_rows;
+
+  input_image = pgm_allocarray(in_cols, in_rows);
+  orig_image = pgm_allocarray(orig_cols, orig_rows);
+
+  for (row = 0; row < in_rows; row++) {
+    pgm_readpgmrow(in, input_image[row], in_cols, in_maxval, in_format);
+    pgm_readpgmrow(orig, orig_image[row], orig_cols, orig_maxval, orig_format);
+  }
+
+  fclose(in);
+  fclose(orig);
+
+  // complete decomposition
+  levels = find_deepest_level(cols, rows) - 1;
+  if (level > levels) {
+    fprintf(stderr, "%s: decomposition level %d not possible (max. %d), image size is %d x %d\n", progname, level, levels, cols, rows);
+    exit(1);
+  }
+
+  init_dwt(cols, rows, filter_name, filter, levels, method);
+#ifdef POLLEN_STUFF
+#include "pollen_stuff.xxx"
+#endif
+#ifdef PARAM_STUFF
+#include "param_stuff.xxx"
+#endif
+
+  input_dwts = fdwt(input_image);
+  orig_dwts = fdwt(orig_image);
+
+  watermark = malloc(n * sizeof(double));
+  if (!watermark) {
+    fprintf(stderr, "%s: malloc() failed\n\n", progname);
+    exit(1);
+  }
+
+  fprintf(out, "ZHWM\n");
+  fprintf(out, "%d\n", n);
+  fprintf(out, "%d\n", level);
+
+  p = input_dwts;
+  q = orig_dwts;
+  while (p->coarse && q->coarse) { 
+    double *collected_coeffs, *largest;
+    int subband_size = q->horizontal->image->size;
+    int maxselect = MIN(3 * subband_size, n + 1);
+    double threshold;
+
+    collected_coeffs = malloc(3 * subband_size * sizeof(double));
+    if (!collected_coeffs) {
+      fprintf(stderr, "%s: malloc() failed\n", progname);
+      exit(1);
+    }
+
+    for (i = 0; i < subband_size; i++) {
+      collected_coeffs[3 * i + 0] = q->horizontal->image->data[i];
+      collected_coeffs[3 * i + 1] = q->vertical->image->data[i];
+      collected_coeffs[3 * i + 2] = q->diagonal->image->data[i];
+    }
+
+    largest = malloc(maxselect * sizeof(double));
+    if (!largest) {
+      fprintf(stderr, "%s: malloc() failed\n", progname);
+      exit(1);
+    }
+
+    select_largest_coeffs(collected_coeffs, 3 * subband_size, maxselect, largest);
+    threshold = largest[0];
+    free(largest);
+    free(collected_coeffs);
+
+    w = 0;
+    for (i = 0; i < subband_size && w < n; i++) {
+      if (q->horizontal->image->data[i] > threshold)
+        watermark[w++] = (p->horizontal->image->data[i] / q->horizontal->image->data[i] - 1.0) / alpha;
+      if (q->vertical->image->data[i] > threshold)
+        watermark[w++] = (p->vertical->image->data[i] / q->vertical->image->data[i] - 1.0) / alpha;
+      if (q->diagonal->image->data[i] > threshold)
+        watermark[w++] = (p->diagonal->image->data[i] / q->diagonal->image->data[i] - 1.0) / alpha;
+    }
+
+    write_mark(out, watermark, w);
+        
+    p = p->coarse;
+    q = q->coarse;
+  }
+
+  fclose(out);
+
+  free(watermark);
+
+  pgm_freearray(input_image, rows);
+  pgm_freearray(orig_image, rows);
+
+  exit(0);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Meerwald/wm_zhu_e.c	Sun Aug 12 13:14:34 2007 +0200
@@ -0,0 +1,260 @@
+#include "wm.h"
+#include "dwt.h"
+#include "pgm.h"
+#include "sort.h"
+
+char *progname;
+
+void usage(void) {
+  fprintf(stderr, "usage: %s [-a n] [-e n] [-f n] [-F n] [-h] [-l n] [-o file] [-v n] -s file file\n\n", progname);
+  fprintf(stderr, "\t-a n\t\talpha factor/embedding strength\n");
+  fprintf(stderr, "\t-e n\t\twavelet filtering method\n");
+  fprintf(stderr, "\t-f n\t\tfilter number\n");
+  fprintf(stderr, "\t-F file\t\tfilter definition file\n");
+  fprintf(stderr, "\t-h\t\tprint usage\n");
+  fprintf(stderr, "\t-l n\t\tdecomposition level\n");
+  fprintf(stderr, "\t-o file\t\toutput (watermarked) file\n");
+  fprintf(stderr, "\t-s file\t\tsignature to embed in input image\n");
+  fprintf(stderr, "\t-v n\t\tverbosity level\n");
+  exit(0);
+}
+
+int main(int argc, char *argv[]) {
+
+  FILE *in = stdin;
+  FILE *out = stdout;
+  FILE *sig = NULL;
+
+  char output_name[MAXPATHLEN] = "(stdout)";
+  char input_name[MAXPATHLEN] = "(stdin)";
+  char signature_name[MAXPATHLEN];
+
+  int i, c, w;
+  int row, col;
+
+  int n;
+
+  double alpha = 0.0;
+  int level = 0;
+
+  int filter = 0;
+  int method = -1;
+  int levels;
+  char filter_name[MAXPATHLEN] = "";
+
+  int verbose = 0;
+
+  gray **image;
+  Image_tree p, dwts;
+
+  gray maxval;
+  int rows, cols, colors, format;
+
+  double *watermark;
+
+  progname = argv[0];
+
+  pgm_init(&argc, argv); wm_init();
+
+  while ((c = getopt(argc, argv, "a:e:f:F:h?o:l:s:v:")) != EOF) {
+    switch (c) {
+      case 'a':
+        alpha = atof(optarg);
+        if (alpha <= 0.0) {
+          fprintf(stderr, "%s: alpha factor %f out of range\n", progname, alpha);
+          exit(1);
+        }
+        break;
+      case 'l':
+        level = atoi(optarg);
+        if (level <= 0) {
+          fprintf(stderr, "%s: decomposition level %d out of range\n", progname, level);
+          exit(1);
+        }
+        break;
+      case 'e':
+        method = atoi(optarg);
+        if (method < 0) {
+          fprintf(stderr, "%s: wavelet filtering method %d out of range\n", progname, method);
+          exit(1);
+        }
+        break;
+      case 'f':
+        filter = atoi(optarg);
+        if (filter <= 0) {
+          fprintf(stderr, "%s: filter number %d out of range\n", progname, filter);
+          exit(1);
+        }
+        break;
+      case 'F':
+        strcpy(filter_name, optarg);
+        break;
+      case 'h':
+      case '?':
+        usage();
+        break;
+      case 'o':
+        if ((out = fopen(optarg, "wb")) == NULL) {
+          fprintf(stderr, "%s: unable to open output file %s\n", progname, optarg);
+          exit(1);
+        }
+        strcpy(output_name, optarg);
+        break;
+      case 's':
+        if ((sig = fopen(optarg, "r")) == NULL) {
+          fprintf(stderr, "%s: unable to open signature file %s\n", progname, optarg);
+          exit(1);
+        }
+        strcpy(signature_name, optarg);
+        break;
+      case 'v':
+        verbose = atoi(optarg);
+        if (verbose < 0) {
+          fprintf(stderr, "%s: verbosity level %d out of range\n", progname, verbose);
+          exit(1);
+        }
+        break;
+    }
+  }
+
+  argc -= optind;
+  argv += optind;
+
+  if (argc > 1) {
+    usage();
+    exit(1);
+  }
+
+  if (argc == 1 && *argv[0] != '-')
+    if ((in = fopen(argv[0], "rb")) == NULL) {
+      fprintf(stderr, "%s: unable to open input file %s\n", progname, argv[0]);
+      exit(1);
+    }
+    else
+      strcpy(input_name, argv[0]);
+
+  if (sig) {
+    char line[32];
+    fgets(line, sizeof(line), sig);
+    if (strspn(line, "ZHSG") >= 4) {
+      fscanf(sig, "%d\n", &n);
+      if (alpha == 0.0)
+        fscanf(sig, "%lf\n", &alpha);
+      else
+        fscanf(sig, "%*lf\n");
+      if (level == 0)
+        fscanf(sig, "%d\n", &level);
+      else
+        fscanf(sig, "%*d\n");
+      if (method < 0)
+        fscanf(sig, "%d\n", &method);
+      else
+        fscanf(sig, "%*d\n");
+      if (filter == 0)
+        fscanf(sig, "%d\n", &filter);
+      else
+        fscanf(sig, "%*d\n");
+      if (!strcmp(filter_name, ""))
+        fscanf(sig, "%[^\n\r]\n", &filter_name);
+      else
+        fscanf(sig, "%*[^\n\r]\n");
+    }
+    else {
+      fprintf(stderr, "%s: invalid signature file %s\n", progname, signature_name);
+      exit(1);
+    }
+  }
+  else {
+    fprintf(stderr, "%s: signature file not specified, use -s file option\n", progname);
+    exit(1);
+  }
+
+  watermark = malloc(n * sizeof(double));
+  for (i = 0; i < n; i++) 
+    fscanf(sig, "%lf\n", &watermark[i]);
+  fclose(sig);
+
+  pgm_readpgminit(in, &cols, &rows, &maxval, &format);
+  image = pgm_allocarray(cols, rows);
+  for (row = 0; row < rows; row++)
+    pgm_readpgmrow(in, image[row], cols, maxval, format);
+  fclose(in);
+
+  // complete decomposition
+  levels = find_deepest_level(cols, rows) - 1;
+  if (level > levels) {
+    fprintf(stderr, "%s: decomposition level %d not possible (max. %d), image size is %d x %d\n", progname, level, levels, cols, rows);
+    exit(1);
+  }
+
+  // wavelet transform
+  init_dwt(cols, rows, filter_name, filter, level, method);
+#ifdef POLLEN_STUFF
+#include "pollen_stuff.xxx"
+#endif
+#ifdef PARAM_STUFF
+#include "param_stuff.xxx"
+#endif
+
+  dwts = fdwt(image);
+
+  p = dwts;
+  while (p->coarse) {
+    double *collected_coeffs, *largest;
+    int subband_size = p->horizontal->image->size;
+    int maxselect = MIN(3 * subband_size, n + 1);
+    double threshold;
+
+    // allocate memory for coefficient vector
+    collected_coeffs = malloc(3 * subband_size * sizeof(double));
+    if (!collected_coeffs) {
+      fprintf(stderr, "%s: malloc() failed\n", progname);
+      exit(1);
+    }
+
+    // collect coefficients from all subbands of one level into one vector
+    for (i = 0; i < subband_size; i++) {
+      collected_coeffs[3 * i + 0] = p->horizontal->image->data[i];
+      collected_coeffs[3 * i + 1] = p->vertical->image->data[i];
+      collected_coeffs[3 * i + 2] = p->diagonal->image->data[i];
+    }
+
+    // allocate memory for largest coefficients
+    largest = malloc(maxselect * sizeof(double));
+    if (!largest) {
+      fprintf(stderr, "%s: malloc() failed\n", progname);
+      exit(1);
+    }
+
+    // select largest coefficients (involves sorting)
+    select_largest_coeffs(collected_coeffs, 3 * subband_size, maxselect, largest);
+    // threshold is the smallest of the largest coefficients 
+    threshold = largest[0];
+    free(largest);
+    free(collected_coeffs);
+
+    w = 0;
+    for (i = 0; i < subband_size && w < n; i++) {
+      if (p->horizontal->image->data[i] > threshold)
+        p->horizontal->image->data[i] *= (1.0 + alpha * watermark[w++]);
+      if (p->vertical->image->data[i] > threshold)
+        p->vertical->image->data[i] *= (1.0 + alpha * watermark[w++]);
+      if (p->diagonal->image->data[i] > threshold)
+        p->diagonal->image->data[i] *= (1.0 + alpha * watermark[w++]);
+    }
+
+    p = p->coarse;
+  }
+
+  free(watermark);
+  idwt(dwts, image);
+
+  pgm_writepgminit(out, cols, rows, maxval, 0);
+  for (row = 0; row < rows; row++)
+    pgm_writepgmrow(out, image[row], cols, maxval, 0);
+  fclose(out);
+
+  pgm_freearray(image, rows);
+
+  exit(0);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/README	Sun Aug 12 13:14:34 2007 +0200
@@ -0,0 +1,29 @@
+Watermarking source
+
+version 0.4
+  * bug fixes
+      - wm_xia_{e|d}.c variable level uninitialized
+      - wm_zhu_{e|d}.c variable level uninitialized
+      - issue with random() vs. rand() and RAND_MAX in frid2_common.c
+  * added option to bruyn algorithm to disable block skipping
+  * added algorithm kim
+
+version 0.3
+  * added nice manual/documentation
+  * added algorithms by Dugad, Wang, Zhu, Fridrich
+  * added Makefiles for Win32 plattform (mingw32)
+
+version 0.2 
+ * added contribution by Vassilis Fotopoulos (Piva's algorithm,
+   DCT, Hartley and subband domain) - see Fotopoulos/ subdirectory
+ * stuff moved to Meerwald/ subdirectory
+ * added Bruyndonckx, Corvi, Koch, Xia, Xie algorithms
+
+version 0.1
+ * initial release
+
+Peter Meerwald  
+Dept. of Scientific Computing, University of Salzburg
+
+pmeerw@cosy.sbg.ac.at
+http://www.cosy.sbg.ac.at/~pmeerw/Watermarking
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/images/lena.pgm	Sun Aug 12 13:14:34 2007 +0200
@@ -0,0 +1,4 @@
+P5
+512 512
+255
+�������������������������������������������������������������wvjaa^\Xag`heiiiihnnlkihmmmljjlnmkmmnnlhjjlmovoqvywpzyz}zy|{��{z������������������~�~���������������������������������������������������������������������~���������������������������������������������������������~����~���~�����}��~��~�y||ywzywuroqsifghptvz��������������������������������������������������������������������������������������������������zkjeghoiqtuwuwvy{ywux}yv{z}�yw{vy|{xzyy{z|�v|~|~~{{|}vv�z~~~�|~~z�|~w{rytwvsx|���������������������������������������������������������������������wvjaa^\Xag`heiiiihnnlkihmmmljjlnmkmmnnlhjjlmovoqvywpzyz}zy|{��{z������������������~�~���������������������������������������������������������������������~���������������������������������������������������������~����~���~�����}��~��~�y||ywzywuroqsifghptvz��������������������������������������������������������������������������������������������������zkjeghoiqtuwuwvy{ywux}yv{z}�yw{vy|{xzyy{z|�v|~|~~{{|}vv�z~~~�|~~z�|~w{rytwvsx|���������������������������������������������������������������������wvjaa^\Xag`heiiiihnnlkihmmmljjlnmkmmnnlhjjlmovoqvywpzyz}zy|{��{z������������������~�~���������������������������������������������������������������������~���������������������������������������������������������~����~���~�����}��~��~�y||ywzywuroqsifghptvz��������������������������������������������������������������������������������������������������zkjeghoiqtuwuwvy{ywux}yv{z}�yw{vy|{xzyy{z|�v|~|~~{{|}vv�z~~~�|~~z�|~w{rytwvsx|���������������������������������������������������������������������wvjaa^\Xag`heiiiihnnlkihmmmljjlnmkmmnnlhjjlmovoqvywpzyz}zy|{��{z������������������~�~���������������������������������������������������������������������~���������������������������������������������������������~����~���~�����}��~��~�y||ywzywuroqsifghptvz��������������������������������������������������������������������������������������������������zkjeghoiqtuwuwvy{ywux}yv{z}�yw{vy|{xzyy{z|�v|~|~~{{|}vv�z~~~�|~~z�|~w{rytwvsx|���������������������������������������������������������������������wvjaa^\Xag`heiiiihnnlkihmmmljjlnmkmmnnlhjjlmovoqvywpzyz}zy|{��{z������������������~�~���������������������������������������������������������������������~���������������������������������������������������������~����~���~�����}��~��~�y||ywzywuroqsifghptvz��������������������������������������������������������������������������������������������������zkjeghoiqtuwuwvy{ywux}yv{z}�yw{vy|{xzyy{z|�v|~|~~{{|}vv�z~~~�|~~z�|~w{rytwvsx|��������������������������������������������������������������������{wonf`\_Y_`afecdlhjjiklidjhljdihjliflhogikohloorwsvxxzwy|zz�}z}~||}|����������������}�������������������������������������~������������������������������~�������~����{�������������������������������}����~�����������{z|����~����~���~}{xz{||wtrrvloijhenmxz�����������������������������������������������������������������������������������������������Ⱥ��pgahfipooxtwuvxyx|zzuzz|z|{zy|vwt}yuzx{~{}|zx}{z�|{vvzy|�|�~�~|}y{wsr{zz~~�����|gM������������������������������������������������������������z~kkabY^[c\ca``hhmohfcjgjejfbfhlllekhjkhffsglkoqxxswuxx{�y|{{}w}|z��������}�~������{�~�����}��~���������������������������������������������������������}���~���������������~��������������������������~�}�~~���{����~~����}����~�~�����{}{{z|z{~wttpnongghffrvz~}����������������������������������������������������������������������������������������������ò��ljdfgmiqutsw|vsxzyvyzzz|}~xxvy}y|z~vz�}|{x}zzzv~}z}zz{~{}yz{}}~}~~|wxv~~��~yp\O@:������������������������������������������������������������|yrn^^ZSVVX]]daeinjmjhgecijlegfcjgikggkjjikimpppqsswyz}}~�|�}{z�x{���������~������������������������������������������������������������������������������������������~}��������������}���������������������}���~�|�����������}���}�~}�|~zxuvyxtwpqsojjmceqtz{~����������������������������������������������������������������������������������������������ɻ��zfagholrqurvwrtwtwvyt{wvy|{~y~|{|w{z|||}}z�}x|{w~{y}yywz~~���z����}}{|x��~|r^SFC27/������������������������������������������������������������|xnra^ZWX\]_^gchighfinkghellffkikglgfmsgjkgrnqnrnrwuwxy|wxz~}�|}}��z~~��}�������������������������������������������������~�����������������������{��������}�|�������������������������~���������������{����}|�|~��{~�{�~�����~����}~|�x~�z~zwztqpploqojfgkjsuy�����������������������������������������������������������������������������������������������ij��pgfmljposqtv{wv}wyuy}vwzwwv|||xvyzx|}|~}{v{~{y|~{{x|}{~||}��}�|����}��}��{l^I@02./1������������������������������������������������������������yyqja^[\Z[Y[a]fgbcefleigchipigkjihgfckgcdnimmmjsrttrut}wv|x|~|x~|~�~���}��������������������������������������������������������������|�������}�����}�����|����������~||��~�������������������������������~��}���}|}{|�z|�}���{~��x{}�}}||}twxxrspooqgoigflouv|����������������������������������������������������������������������������������������������̽��|nihhlnqpsuuuvwztxwyzw|ww�~xzxwx{y}z{|~z{{}{uz~|y~~�zz|~�}|}~}~}��|�~}wiaR;5.1/.,�������������������������������������������������������������|qhaZZYZ[_ciabdddihgegihhcgfknjdggegifejnloplmmquxsw{|}y}y{{z{{}��}��~���������������}�|������������������������������������������������������������~�~�}�}������������������������������������������~�~�}���~�~~��|�|�����������~}xw{pvvzvpstqknjnjgdmqx|�����������������������������������������������������������������������������������������������Ʒ��ojddjilmosnuu{zswvuz|yuyyvwxwxuyywwyxy||}z{v~z{zy{}~|z|||}��{~}|������~rk[M=/04/.33������������������������������������������������������������~tjk`\Y[VWW^d^cf`dhfefiigilkkffhggjhhngdehhkqorrortttwwy~{|z}|�|�~�~�}��~���~�������������~��������������������������~������������������������������������������������������������������|��}��������~������������~���~����}����������|�}�}}zwwzytqqulmmnhlhlijrw����������������������������������������������������������������������������������������������������khjhhjqprosuxyww{uzyxz}xuzxz{ywxuwx}xx{|x|{{|{|y|yz|}{|}}~}�~�������|wiWH85,,+0.-0������������������������������������������������������������}ulfd_TZYWa_Yaadegkiggijimklkhkdfaigefigfcilrrmtpsrvwxuxzy{z{�z��y}~|�|�������������������~����^�������������������������������������������������������~}��������������~������������������������������������~������|���|�~{W}}��{{����}y�}xxyzystpqqqookojgfinyy�����������������������������������������������������������������������������������������������ɺ��tigjgjknqpvsru{xxvxy{yy|zxuztvzv|wz�y{yy{wwx{yy~zyz|��}|x{|�z�������|n_I<22(.+0/02������������������������������������������������������������{smig[W[`\\Y`cdgfckiiionjjmkqleiggkifdggjfioqpnrsrwzyttx{ywwyzz~~|}}�z�}���������������������������|�����������������������������~����~���������������������������������|�����������������������������~�����~�~���~��~�}��~|X~���~�����|�x|}z|uqxoinmqrppkgdgku|������������������������������������������������������������������������������������������������Ŵ��kgkintsltspt|qwvv{wt|vzx{x}}wyz||vz}vzx{{{}|{|}vz|}��~|�~}~�����|tm_G9<B1*(-,212������������������������������������������������������������}qkc[^YX``]_ddifahhglklglnjgsifechjmffbfdijniqrrsrxuwvx{|z}{yyy|�|}|��~|�����~�����������~��������������������������������������������������~��������~����������~����~��������������~������������������������~�~}�~}�}����{����}����~�}{xyz�|zywuuukspotimkkghmqvw��������������������������������������������������������������������������������������������������zgkkljjmpppvvpruqxuzyuz|zxz{vxxsx|{|wuxz~}yy~}�}z}~{z}z}~��������|qgYB6/2H400/6413������������������������������������������������������������ytnpe\]Y\\[[[bigidhgkkohlkjicjjghgiglkfdehjmononoqvqtuwxy|}~~|�}��~~�~���~����������������~����������������������������������������������������������������������������~����������������������������������~~���~~�~~�|�����|��~����|��������z{yzxtutlst~kophihjiory������������������������������������������������������������������������������������������������ƻ��piimhnmlkpytvrsvz{ttxw~~yywy{~z{x{}xz{yy~yz~}|{}y~�}��������{pdT@53*+2..-+5.70�������������������������������������������������������������zmhc]ZTZX][\^fhge_bjpojmgombieejfneehhhddihkpporrqqsyy|y}|v�|�}}���������~~����������������������������������������������������������������������������������|~�������������������������������������������~}������|��{z����������������~~{~tvz}txwprs{wninljegkswz������������������������������������������������������������������������������������������������ij�|qiidkqllrzttqrsvyzyxw{zuxs}yzvxwy}w|}}{xw|{��~�������������zp_R>/10*(0+000-*15������������������������������������������������������������zplh_X\ZTX^_W`idoedemhehigknkhjicjniegfdfhgfmoqpqtqyuuuxw}y~|z|xy�~}��~���������������������}��������������������������~�������������������������������������{�}����������~������������������������������������{��~����~~|~�}������������~����|~}~{tqrqqruxoomtiliifpsy������������������������������������������������������������������������������������������������ʻ��wdgpkhjnqtutswyywxv{w{y}wzz~~{yzyz~|~~�{y~~~~}����}�������|q`P=/-2+-.(02//,(-5������������������������������������������������������������}tmd^d^W^X]a_cgkbdegejdhnigjgglfgigibbheehmnkntrrxryvvvvxz}yx{{x|������~�~������}����������������������������������������������������������������������������~�����������}��������������������������������~{���������z}�~}}������~���|}���}}}|{ytsuoqvtmplqhejfgnux�������������������������������������������������������������������������������������������������Ʊ��ifghmlkopuozrxytwxy}}x}�}�zw{{z{�y||y|~w}|�~~������������{n]S92+(.4..+2.1.01.2�������������������������������������������������������������~q_cXVWY___c`bkcdcilnkirlkjfghhmgjmfnifejkorupusss{{}zxyxv}~zz{���}����������������������������������������������������������������������������������������������������������������������������������������������}�|��}�������~~����~y�{z~zvxvxsqtrlomqkleehnru{������������������������������������������������������������������������������������������������˿��uggfhjjmpprtprwuxy~x}wyy||z|z|{zx~{{y||�||��~}�����������~nbLA0&-22-2/1;13+*,-4�������������������������������������������������������������tg^bUWZY_`_ebfjigjkmihnljegfeigeejldhggdilrpqrroszuuwwxvz~z|t{|�}|~������������~��������������������������������~��������������������~������������������������������~�~���������������������}�~���~��|����������{{}~������~~~�}�~y}z�{x�yxwtosslnjimidfmqu{�������������������������������������������������������������������������������������������������ƹ��qcppmkqurqmuxuwszyyyx{{{zx~uv~ztxzyy�~~~}������������~pdR?43++7C52-/92.2.5.4������������������������������������������������������������~yoid]cWV^]bc\gcgigfwkjjegimfini_dgbgmcgeghkpqqqsptqxrvzzx~zy�}~|�{yy��~��������~�������������������������������������~�����������������������������~��������������������������������~�������~����|���{�|}~~��||{~��|{����~�����~}~z{{{{{�|ypoprpojnjpkkgmoos��������������������������������������������������������������������������������������������������į�xhimqjiqrqnuwtxtwzsx{~u|s{{||x||~|���}���������������p_I<4.--))1151,(+0/1/72�������������������������������������������������������������yyib[]WZa_``fbdcgah�jggihdceglfadhdkfhhfhinonvsoouysw|uuxxwt�}|zz{~~}������������������~��������������������������������~���������������|������~������~�������~���������������������������������~�~���|}|}z�~~|����}�~���}~~���~}~y{y|{xxxyrrupolqukjjfginnr~�������������������������������������������������������������������������������������������������̻��ljfijlourmyqxwtvvrsry|~~|xwzwuzyu|��}���������������t[G615)*-,-65>/34+.11846�������������������������������������������������������������~tec`VYWX^_bchbckkhjgefghkgegggknmgcekihjkgkjmloqqsqt}xu|yvy}w|~|��������������������~~�~����������������������������|~��|������~�����~�����|}��~�}�|�����}����������������������~~������������~�����{~~|~}{}�|~�~|��|}���~~{|x}wxxuzrsqqllppikmimppry��������������������������������������������������������������������������������������������������³�~qlelskloqtrtxruysxvzw{{xyy{t{y{xy||~�����������}qaI83::.6?32063//././//0=�������������������������������������������������������������xqjc]YYYV\^b^_cfefknfjgihgceojkgdgijcehhkkolkmtlopsxxw}y{|xxzt{�}�����}x�|���~����~~�����~~�������}��������������������������������}���������~��~�||~~~{���}�����~��}���������������������������~�������{~�}|z}}�}�}�|�||�~|���||yxy{xvvsunonolknjjklovuu}������������������������������������������������������������������������������������������������������tfjhnkoqovv{|vz}ytwzv{�xyyxzwvxw{yw��~|}�����������q^J;L?/0+-0,2(,4,-,6147766������������������������������������������������������������}xrg`_XURX[e_^aa`eikingmjjhdhilfhghechjbhhnkqqpoqpsqxw{yy{xvx}w}~}�}���|{�������������{��~��~��������~��������~�����|���������������~��}}}y}{�~~}��{}~�}��z�|~~��z�|~�~��������������������~���~�~{|�����z�}{�}����}~|}|����}~{~}{y�yutpoklnmjiihnqpxz�~��������������������������������������������������������������������������������������������������Ǻ��jedjjlkrwrvyzwzzv~|{|y}}zzxyztv}|~yx}����������o^H9>KJ10(/+.0('..,).01476:������������������������������������������������������������ztmc\VWVNSTa]`aedhgeidlekghgiiegfdeilgfeihljoollqrqrwzzwxw~vzyz|{{}~~����|�|~������}��}��}����������������}���~�������~������������~������z~z~|��~{}~�{�~�����|}}}~��}y~�y�~�������������������~�~|~}�~�~�|�}{���}��{�������|}{yy|||~wvrmqqlkjhjjmltrww���������������������������������������������������������������������������������������������������²�ydhjklnorrts|}z{~~y|{x|}vxwxzx�|}}w{z~�������~o`R52)0<4.&'%)/**.-.-.74;</0������������������������������������������������������������zrnbaW[\TUTU`_cgfdkghijhkjukgkkkdhgeicfghklmmkklptuuuy|ywt|~z~|{{�����~|�|�}����~�����������������|~����������}�|�����������������~{~|~}�wy}|}{~|����}~~~�{|}��}}��{|��|~~�����������������}���~��}�z~}�}z�|���~{~~���~|}~{y}vxz|yzswknpnqjmgiinsw{z�������������������������������������������������������������������������������������������������������mghhonrtslo~~|y|{xy~}|zzw�st{~{wy{}}�������~r^F7+0,.70.(,(,...-33.+184401������������������������������������������������������������|vof`VXSUTV__caeefdigcjgjlhgimicikchggcjiglmlloosuruty}x{wu|zzy}}~�}}x�|���|�����~���������|������������������������������������������~}}}�}}|}xy|x}{{|����|{|}{|~z}��}~�}�����~~��������������������{~��~�~�~{~~~|}~}}�|||���}}}|{{{|}ux}zqzvtnsonmjklkrpz|������������������������������������������������������������������������������������������������������ŵ�}egjklmnutsuyywwv{y{{xzxy{yy{w|}~|�{�������spYJ5+'))20/0+,+/-/.0./15:7/69M�������������������������������������������������������������spfhZYXSV]]`iabbijjgflhhjiijkdhihekjjgdhkjmkpiosqsusuww|xy}{x|}{~�}~}�y�~}�|��}~~���}������}������������������{���|}��~z�������������~|�}�}{yzxz{{}}zw{~���~}}~{{�||{z}}��|{���������~�������������{|���~~���������|~�}}{}}|}|{����}}|}�xqwv{r{wolqqqoplllpsux~�����������������������������������������������������������������������������������������������������«�ngijkpqruursuz}yz}}yy~{{xw{vx{x||�}{�������lYG310((,/.+036*++:21635.53/33?�������������������������������������������������������������tre_Y][WUZ]]cdfahfjlkhhqhdgikffhgfehjfdfkfokokjmpqutvvxyy{{y}�zy{�}}~���~�|~}������~�����������������������~}��}����������������}w{|{xz{{}w{~zz������}~�}�{~y~�}}�{�������~�������������}�~~��~�������~|x��y�{{~~~�|��}�������zz{suxtwwuusqlqmmmlhktvy|������������������������������������������������������������������������������������������������������˺�fajqnqqwvqtuutu}|v~t}xz{yxx�x|�}�������zq_J/+(,-.21/2.)./6)./053251-58:9������������������������������������������������������������~rqfa^[WVW_`bcagbdeinlpnmoheikmcfeglhmghiljkjlnpotsvuzw}||{zzzw|{}|}{�|����~|�~�}��}|~~���}��������������������������|����������������}~zyt|{{{z~y}}~y~~z~~|~}~�yz~||��|������|�}���������~~��~~��}{y}���|�}~|~�}�{�|��}�����~�~zzzpvxtvvvwrplppqmklso|}�������������������������������������������������������������������������������������������������������Ʈ�vjjkiinortuvzvwy}}~vyyww|y}|}z}~�~����{l[H6)+'*22+/-2/-.5-1452213-1,5683�������������������������������������������������������������ymid\ZWV\\db__cefegghoilmmkklncdefchhbdghhjkloquqqquuuz{wxxx}xvx~||~~~~��{z���~��z�{|}~{�}����~��������}�����������������~|�����������}�~���}{|�wx}z|{y}}xl}}�||w||~~�}}|}{|{��������~~��������~�}~~~x����~}}~�~z~~~|{~}}}z��~��}}y}w|yxyvtshtpnnomikikksz�z����������������������������������������������������������������������������������������ǿ�������������̼��soskvqrsvzuvtwwu{|y{yx}}�w}|}�����~xoWC314(),85.)0/++0214863314/23=99������������������������������������������������������������}wpf`X]Y^Y``]`bjcaehjiighlijiodegffdcjfjimjilopmporvuuvw{{y�|}wx|~}~���{��|��~�}~�����~��������������������~�������������������~~�~�||{y~{|z{uvx{{xz{~}}�~~~�}}}{~�y|{}w}}|���~���~�}������������|���~}���~��~�z����~|}�}|�~~��|y~~~}zwzyxqvnqnlnrlhilnotv{|��������������������������������������������������������������������������������������������������������ɸ�~mjihmlpusruttxu{y}~}}y~{|||������yk^F84'%02((665474+.:;64522/11/32;78������������������������������������������������������������|smg_`RV\\aZ\hdc`ciggkkjiilhbhgdhhgde`ifffhgoooslsusqvsv{s{y||zzv~�z|}|����������}~�~~�}{����������~������}��~�������}���������������}~~}||z{}y~x{wv{yx|x}}}{|���{zy}y{~{}~}z|�����������������������|~�����~|���}�{z�~|��z{}}}��~��{~}~~�||||{wuqysqprktnogmpqwvw}|�����������������������������������������������������������������������������������������������������������qjigiknitqptwuvxzyz{xzy{��~}������zqcK:.+(&*,++-39>244096.14;115126;538������������������������������������������������������������~rmc_]WZYXY]ccdgcgiohhgihiiigfiglhgggge_cjhhlkorotruvwuwz{zu{{v{}�y||{{{���~�~���~���||}}y}��������||����������~�����|������~�}��~~|z|{|z|yyzzyz|{}�z|�~�zw{xx{|wxzx�|}}�����{�������������~���������|��}}�}z}|�~~|��~x�{�}�}����}{~|yxvt{vrwronrrlyphnnpsvzx}��������������������������������������������������������������������������������������������������������ɽ��jglcokpqrqtsuw{y|~|wzw|y�������|uaG4.,,(,,&+/2.6;16D4354283322067520.�������������������������������������������������������������vklaYZVU^X]eadheccfclhdgfggfeehhecheikikhkfnnpotontwxuvvzywwwuz|~y}xw}|~��}�~���}~|}|�{y~��|�{�|~�����~}{�~�|}��������~}�~����~�}y}��}~z�}|�|zzz}}~x}��|~}~~}zx|}yzxwy}~{vz�����������������~��||�~��}�|�~�}�}||~{|z|��~�}~�|~}�~��{y~u~xuyuqvyrpsvqpmgjmnqvyz|���������������������������������������������������������������������������������������������������������ɱ�zicjiekrrurqqwyyw||}�}y��}���}yi[K<*+*())/-/6549<98853/17130.40765/2,������������������������������������������������������������~xkf^YRTSS\YfZ[dciggihedgbgedjfhffchafikhjjkoklrrpprxuqu||syzqyy{�{xyz~��{�|�}|��||}�~z}xz{~}|����~~��}{�}|������������������~�������}}�~~�|{}x{{|xv~y�vy~||}~~{vv{u|{|vyx||{}�����}�}������������������������}~~}~yy}z|���}}}��}}�~{�{{zx~zwvtr}w{sqsooplniplxt|�������������������������������������������������������������������������������������������������������������r``hgolpowsvqu~~|y|z�|�������vi[A8,')-+,*.,./31-1236556.;4:322/432,,,������������������������������������������������������������|vpd]TPRXSW[[_^ecichmifhdcgddidfgffhgighddigjonpoussrwvs{yxxwvtxx}}�z�{}||}{{|��}}{}y|}}�{�~���~���}}��|���~������}�|�����}��~}~~~}y{~|{xuz|yux{}~}�z{vzwxxyuxw{ywz|}}}}~�|�~��~����������~�|���~������}}~|~�|~~{|}~}���y|~��}~~zwyytw{~vxusnoilhhkkqt|���������������������������������������������������������������������������������������������������������ʹ�}fcbckionopssrwxwuy|~y~�����vk\J6-+02,()*+(.5254777>:8=6854285.,3//44������������������������������������������������������������~vm`W[WRSSV\cdecfdfeehmoefjfeecfcjigdjjfbehhiprnqpvutuvux{vuyur{wv||}{}||�}|{}��z�|zyx}�z�~��������~���~|{����}�������~��~������|~���~{~~{�zzzxy|�xz|yvzzz|zutu|uxxzux{w|z~zz~}|��}|y��������~~��z�}���~�}~����|}~{|{{���|�}~}z{|zxwsvstsussupoqjmnntww|~�����������������������������������������������������������������������������������������������������������ů�ubbcqoplmprrvyyqwy}}������xl\I4,'-(.1,11-(/;ACLF???@9>3451342-0--..:�����������������������������������������������������������zthd`YSOQU\d\[ebjjggidgcdigkfffefddmechfkfjijmtpssvrrxxuyu{zxz|xxyzy~�wyy{�~�{{}~}�~~|�y}z|{w��|�����|�~���|�~�~��������������}~��~�}�~}��v�yyy�{{~wvsywzyzy{yy{uwxx{xxv{zw|}�}}���������~��{�}�|z~}���}�}~xy��~���}}�z�||��}~||~{zxuyrstuwvsnurqstmmors{||�����������������������������������������������������������������������������������������������������������ɿ��kdehhrhkponsuswxz{y�����yp[K80+&-2,)*.4-)-02375181435101//040,-/,/2�����������������������������������������������������������ysfd_XTQSXZYdWYlffqifleccdefdffbdkefcibgffchgikoporrv{xyuxxzvw~zx�vwz|xz{w{���}{}{�z}y||~}~z||��|���|�����~�������|���}����}|�����|�����{���}~||z�}}~}~yzzzxutvxyuuyvx{yzyvxs{xyyx|��|�����~����~�|~���}�~{�����~}{}�}��}}{��~z���~{�~}x|zyxwsuptrusnxunommsoptz|������������������������������������������������������������������������������������������������������������Ʈ�xdbimkmjpqurqoqtx|z}��~|qaQ46/*,,-*.)+/4/4:573:3<42.57711-.1.,-,/),�����������������������������������������������������������}|pie]VYQQSZ]Ybdkgfchfdkfhhfifhilackddaiehggjjjoqnpssrzxyyzuwwvz�{|y|�y}{y�{z}�|�~{}|�|��|����}��}�{}~��}|����|�����������|�������}~}�}}�~����}}{��{}{{x}zxxwtwvz{wzxttwwzurtvxwx}|~�}��~����������||~��}�x|�����|}}|���|~~�}}�}|~���}�|}|}z{zzxtqyusrswsqxsnqmlnruxx~|����������������������������������������������������������������������������������������������������������ʺ��lchgmhimkqormtryz|���vq^Q=.-+-))*+.+,40.667:<=64461:1341051+.---)1�������������������������������������������������������������ymb^WUOZWWa_\afcdgidfjgkmjieenjcfljfhcclifilomomqrqs||w{yxuutwy}{x~{�}z{y~x}}��v{z|z}y�������}�����}~|~���}��~�~��~���}}}�����|�}���~~������}�{~{~{vz~||zy|rzuvqxxrw|vvtzwytxu}zzz{|~z}�����~�|{�������|�������|~~���||���{}{��{�}�}�~uwwx~{xuu{urtrtqqoonmnjmmssxz�����������������������������������������������������������������������������������������������������������Ƴ�xdagjlmljomtrwwzz}��wr_I@,0+(*+*-./000975<9E>>:914642833/.,,,03.)-�����������������������������������������������������������|uja`]TOWV[^]adfhacmjcegkdejddjoidfgedifeefjnlknorrwutyuxzzxyz|{�z}��{~{{�|}}}}~|{||~~�~}~|��~��~}|{�������������������~~����~��{�{�����~|}x{}xuw|~y�������}y}}vuztustxwwxw}~yuxx{{�}�{~}|z�������{��������|~��}�~|���~�}}}~�}|�{{y{{||tuyqppstuuqsnkllprqrs{�~���������������������������������������������������������������������������������������������������������������kbjflkjnprtquxyy��{kaO92,+)(.0.)11133616<;5;95>7:542452-++-..1/+0������������������������������������������������������������~qja`XSNRT`\^babceddigkfjgcjbfcfkifelefgkhhlrmknouxvuwxxysvzvz|{z|yw{�|}||~�~�~y{{}z��{��������~�~}|}|�����~�����|���}|��|}}�����{~~z��|zz�z|~}|~{}�{�������������������vz|wtwyv{|{|vwzyz{yx|{~yzz��}�{��������}|~}���{���}}���}}��y}�}�|zztwvptvouvrpoogknlptrtz�~������������������������������������������������������������������������������������������������������������Ȳ�vedjfillpyqory�}xf^Q;/,100*-+,*/2,11562:9;?=:5433076<1/+,,/20.1-������������������������������������������������������������|tig\YWNUS^[YZ__ecjdhfmihmhmijeljkeffehffkhmtoqnvutssx}yvzy{xz}xz|{zz}z{y�}�~~{�|~y{��~����||��������~~z��������������y�}~��|������y{~�~|{�~���������������������������������||rwwvutvywv{zxy�}|}~}}}~z�~�~�������|��~y|}�|�}}{�}~�{|~|}{xvtwrpupovxqonqnkjpqvswy������������������������������������������������������������������������������������������������������������������lbgvijmuuwty}}|siXR@/-+,*200,*+1..0446<:7<8=4788>5*;2/6,-,/.4-,/�������������������������������������������������������������|kfa[ZQVT]Zccadagghglhelnqkfdgedfelfgidgjflrlooprqsvwyyxxz}u{z{zz|z~}~|}�}}��~|~z�~���|}}�����~�}}�|}����������~���}z}��||}����~~~~y���}�������������������������������������zxuqsvqwvquzy|{}z{|}~�}{}��|�������������y}~}}}||�{�z~}}||{||xxxyvvtvuquvrponljpglqsuwx��������������������������������������������������������������������������������������������������������������̽�~om}poopvqs|v}xjYB0-/,.++00/-*.214229678:@?;;88333-0++1+,0.+/00-�������������������������������������������������������������~mh\_YSRU\Z__\^_gdfglkhkijneeheldhffjfghiklportopqlpwvyz}zwy}{||�|z{}|}||�~���z}~�}}����~����|}~�����~��~�}������~�~�������}��~���~��|��������������������������������������ö�����|{xruvuttvy{y{z||{�y~}~�������������~���z~���}��}}}�~}y{zwyyyvtqppotorrplmknmpswy||��������������������������������������������������������������������������������������������������������������Ư�tilifnurr|~zsnbN<,'/(&**,-*)01233:=43<77=:<984341.**,..1.'.-005�������������������������������������������������������������yod_\[TRXW[\aaibcdedfeghfhjckegkgjgfbfeehkjpqtqrpppqxwxwzyuuyw{{�}|}�}z~�{�~|���~~~~|�|�����z}}����~{}�����������~��y|}{~�}���������������������������������������Ǻ���ú����û����zwxswystwsx�z{}z~}|{�����~������{~z��|�~�}~�}|~~||uxxyyvvunsqrorpmlkjnlqrzw}���������������������������������������������������������������������������������������������������������������˼��loglpxvx~}vj]L3+&*+-1+,*1--,126278546H<A998??84,.'+,**/4.161/-�������������������������������������������������������������zlcY^QTYY\[_Zeccdbkfjifikidfeechhkffdgghhnlqosprtntuyz|y|{{zzy}~~z|�|x|z}~z�{|~}�����������������}�{�~�}�������������}�|}~{y|~��������������������������������������������������������������vuqr{ptzzxy|{{|z{������������}���~{||~}}~{}�}~zzvuyuxw{wmqnspoppkjnmortw~}����������������������������������������������������������������������������������������������������������������ɶ��nklux~{�tg]H:0*%))**-+(,-.*/2592:678685;66379-1/)*,++,*/-1+/3�������������������������������������������������������������tjd]WVRSTYZ]`aY_ccdgmggfiehfbefhikhonggfmlpnorrpquvwuzzyux{wtxx|}{}�~�||�}}||��~~�{}����}���{��~����~||}��������|��~}�~{�~}~�������������������������������������������������������������������rrnoryxxz{yxyz~|}������}�|�{~�{|~���{��}�|{|wwuyuyyvsruvssnqponnkjhniprtt{��������������������������������������������������������������������������������������������������������������������xqpxrw|{f]K4-++)*,)*/,,++.0-/84173247444768330/',+-+/1,,.1(*/������������������������������������������������������������~xmeaUVSSQYY`^[Ygfeefihgiffidcljfeeghlfhcmhmlkouqtttwuxyw}}~tv{wzz}~���~�|z~zz�}{�}}�������~���������|�|�~��~������|�~~}{~���������������������������������������������������������������¾�����}vuswwtusw|vz}}|~�|~||���{}��}�~�{|}|}~|�|{uxv{xxtw{uwrosqopmmimhlnnpwv�����������������������������������������������������������������������������������������������������������������ξ��uptvxysdL:1**((*-.,)+..0*.,33;75249575215201/2,-00/3-,/+)1,-������������������������������������������������������������~vhf_UTQOZWW_]]`fbfcgmhkffjkbjkffiifejijlpoklnmurtwrvx{xz~y{wvxw�}}{�|�{}~~|||~~�}~���|��z���������~z���~���~{���~�~{�|������������������������������������������������������������������¿�������knstuwx|t�{{|}��|}~~}�~��|~�{zy�|w}||y|}�v{wwxywxuoprurprrqqsmjjhkosou|�������������������������������������������������������������������������������������������������������������������ɶ�~vzyxsiQ:/--)%&),/+-*-/1,.25:3<628-155444254-0,3421133)-*,,*������������������������������������������������������������zvma^VRTXXV[cb\bh`gcffkhhb_legihdhdiljfcihllmsquzvustyzzxwz{{{xx}}~z��~|z~~������~{������z���}{�~zz��}||���~|z|�~�����������������������������������������������������������������ľ�����������vrpussvu|vx}{|{�}|}|�|��|}~zw�}�{||{w|{zzwyxvtwlpsuoomorssnijfjpmtz{}�������������������������������������������������������������������������������������������������������������������ȱ�xy~obQ@1''-1*.)-.51//55088:768818.7825-3)).4635/51/0/.32+03�����������������������������������������������������������wpbZUJOSWXYYY\_`_^ceffhf`bgfecghfghphhgjfgpqppyyvutyw{vyuyv{z~y{}~�{~~|}�z}~�����z��~~~~}z��~�~}{��xz~~�������}��}���~���������������������������������������������������������������������ſ���ż��qosu|stvt{|~}~{z��~��|~|z�~��zv}~z{z}zvv|vvy|oqqustpqrkqkkljk|mtw|~�������������������������������������������������������������������������������������������������������������������п��zqc[=4/6%+)((67,1042311757868:244546-0++-0359;011,00)++,.3�������������������������}~��������������������������������xl_\UPPNRWUXY]bc__eheefkcdecekhhigejghijifookos{sssxxxw{wwyz{uw��y~~�~}z�{{�~z��}~�|��~|����|������y~|�z��}~~����������~}z���������������������������������������������������������������������������ſ���yrotswysuz|~~}z��z�{~zy}~~}{{}yx||{v{wxxuwujssrsoqtplnpkjer|ms{}��������������������������������������������������������������������������������������������������������������������̷�xhSC,)*.)-**$14)*..4553644475054634//,+0875220.-*)6()..70,������������������������{{z~�������������������������������~xk^ZVMPNRVXS_\^cca^_^_cdd_fhddceebefhhongfimmmrtsqqwtuwyx{yxzy|~zzzzy|z|}~}{�z{z�{�|||�~|�{|�}{{}|y~������������yz~�������������������������������������������������������������������������������ô��qqpmvpt~|}{z~�}~|z|y}��|y}y�}zw}{xzsrqouorrqtqpopvjmrnmkjoppzx���������������������������������������������������������������������������������������������������������������������ǦxXA3,*.'(,&,'.*/05899:8<25=69361357123,2077<:0//9-(*,-.2..����������������������}|yuxw}�������������������������������~ribXUNMNWUUX\b``c\bbebdecihc^faifcb_elnlmjjioorqswqttzvvx{{{yx~y}||~zt{|z�xw|�~|{}{��||}�~���~�|}~wxz|{wy�����������zvtxz���������������������������������������������������������������¹������¿ÿ�����þ��vrnmsu||z{z}|}��{vxwx�|~|{{z}|yzxxtvuussqmpplosmllmjigilioqsqs{�~��������������������������������������������������������������������������������������������������������������������͸�M0..***&.3'+)3.)+646811978116>3<=6439..06;34/.11+(,.,.2-3���������������������|yswurx���������������������������������rjcZUMNLMOWeg[dec_a^_ceecbhbbfbcdcccfjjfjjjlmmtqnuryvutwuuy{wwwyw{{z|z|wxwxx~}�}~�~~~�{�~�}}{~{y�������������~~usy{}�|�����������������������������������������������������������ž�����ý�������þ���DZ�nmmrwvyuvwvywx~{xzxxxz~vz{{|{{wxsrsqwvwsqtorqnnoniiggkhmqlsut}���������������������������������������������������������������������������������������������������������������������׻�C,,'++'),2+05+1*0-47567027644553,-.50/33.10-/1.:082++(/05���������������������xtpmgpw���������������������������������wj`YTPNRVV_d[^\`_dhjccaeeb_bffbbdedchmfknljkmoppprkxr}pttxqww{wyw{uxyw�yy~}y|x~z~{{|�~~�}|�|||}|~|y|���������������|z~}wx}x���������������������������������������������������������������¾������þ�������º��ponyyxqszwwwu}yvx}{tzzv|yz|y{x|zysvqtrprpvpqmoijmildfcillptuy����������������������������������������������������������������������������������������������������������������������ִp/$!*&($()-0.031).4:53230333543.0-.-0221M7425//,768.-.9328��������������������zynjjelu~��������������������������������{pa]VYSJKLTZQWU\^\dafnja]dddcbg`eakfifgcjihkooopoqq~svry{wux{{vxyzyzzy�}z|�yz{��}~|�}�|��}�|v|y�|w��������������~|�z{zwz{u������|z���������~��������������������������������������������������½������������Ʒ��jsttlusoqsqxzy}xyvxzzwzyuxzyzzvvwvsuusuqrppqplpnmkigggplppuu}���������������������������������������������������������������������������������������������������������������������׹p)&$-()*..-)03(-35379;66584==;1,/-/+-15236526,'*246*-+0721�������������������unecefs}��������������������������������xpdXWSJMORS]ZXU^Y\_`acac_[c`c_ed`ekhbcgfihjrkulnptussvzqq|uuxxyvysxyyyz{}{~}}}{|{}{�~}�{{}|�{y|~�~z�����������}v�}�yyuxxxyy~��������|y������~�������������������������������������������������������������������ø��yrruopppw{vxvxuvw|{yu{yxtytwwwuwuvssspnqpikllnmeiefchiorrxy����������������������������������������������������������������������������������������������������������������������Å8#(+)++)/)*/01325377553564565..,-*/+319<040,/0++-..-+48993�������������������zrhg[\hpz���������������������������������slb[TNJSNTUWUZX^Y]ab]_`ab_ce`b_faggcibghgidijojrpnsqypuuspwxxu�z{rz|xx�x}xxy|}|}}�}|}|zx|yz~���y{�|}~����~�{x�~}{|~}{~||�����������������������������������������������������������������ø���������������½��ǹ�lilnoopswvutuuxz|xzx|xxx}yzwyuuwttrqnsqoohmjkhilj`cnmkoux���������������������������������������������������������������������������������������������������������������������̦[$()()-,,*-2*'///6445793778561-/+-0--3487310+,-,0.-2.346<:4������������������zuiiZ\[cox�������������������������������}vja^QQHKNKPRVW[`\c^`_c_[`_hcdbacddbfggkjghjkjnmhlnnvyswwqqyqzw{w{ty}zyx|}{xwzz�{|{}{z{~{{||z}}��ƍoq}|{z�}�}~zvv}zzwy}y~�}���������������������������������������������������������������������������������Ŀ�����÷�pjnjlnpnqtttvzwrxxtzzwvuvwuvrsuusqplrmnlmpijmngidfjnqqtx��������������������������������������������������������������������������������������������������������������������ѷz4"'*($%'+,+32,44/485411/;=4583)..-.,.466380/-+).*/)14687421������������������yme]SQVcpx���������������������������������ul`YOJKJPUWPUVVXZ^`__^`^`bfa^ibcfg`hhgdihjikiqoiksqmusu}rszvxrttwvs{}|{|z}{y|x}~�|~�~y�~{y|zyz����ifm||{t{xx�uv{zx}|v�zzzzw��������uy��������������������������������������������������������¿��������������������¿��mhkkmoksutu�ruvvrwuwvwvvuwsxwrstptqurqqphljlejhifilonz������������������������������������������������������������������������������������������������������������������ѻ�D'&"*+,'))+.+2.127<=57644<5:2-,(+,))02.932/7//+-/).01/731-($������������������ui_VQPXhmx��������������������������������|tr_VONJGMQQVWZZ[_]]^\c\ba`a__bbbflaehbhnjhgengjiempnruqvssxzxrrqvxuz�y{zy||}y~y�y|�|~}�yzzyw}y���m[Wjmxx}vz|q{}ysy}zyzu{zq~}��������~}������������������������������������������������������ÿ��������ľ������������������}nihmhmjqos~rpspwsusu{wwurtwrospptkkmpkokjkicgdbelnpq}������������������������������������������������������������������������������������������������������������������ӿ�V1$,#'--+**)+.6-395;926=684<865--/+/-43772.)/,//.1./856;6-'" �����������������~pf]YHOZery���������������������������������wneZRSJGNKORVW]\a[]]_c__`bb`egacacc`gicdhbeogjjfjktrrqsvprqrqtrqvvw��|~{x{||�y}|y{}{}z~y{{ssz|�ϩgb[ns~yx{�yxy~zvs�zxx|wvt}�����wz�|����������������������������������������������������������������������ÿ������Ľ������veeajijomqorrmsprsotvstusutsponpjmlolmlljkhidfhltqyz{����������������������������������������������������������������������������������������������������������������ӿ�W3*)+%,++//.(-+420987;0639;74542('+-3336294/**.0*00876:86+'$�����������������vmZPJKOTdow��������������������������������~umcVUPHELVRSUZ_^\]d_ad_gab`bcdfh_befhgbdedhekmlmoopqotsrqslqxssvwtty}{wxt}wx|zz|w}y||}||~z|x~}z���i`fosuttw|}vy{v{|��yytysuz}�~����y{�~������{������������������������������������������ÿ�����½���������������¼������û��mdfgjpijgjnmuosunsustrrrqvtppjonqojhmjknleigjhktrv����������������������������������������������������������������������������������������������������������������Ͽ�b1,&&*-./),-+/,,152152/6:77648.,-/.-.12725-.,-)*0+-3:5<>:;($ ���������������{l^SOLJQYcqw��������������������������������}sk_SWGIFQNUYY\V\[Zb^_ceaead_cabbcecigecheenklkppmqmpuronsuqptusxxxuuwxyxxvx�}�~zz�|~}|}|}�x{��smqspsxxv{}vvuw�{�y|p{z~�}~���������������������������������������������������������������Ž�������ý�������¼��������Ƚ��qfgnljikiikjkprrrptsosrqqslplooplilohjjhiaghnoqsv��������������������������������������������������������������������������������������������������������������̸�Z6'++**--,.**)/,2-<3.272436789002-1432874;7/+,21,1//5;<@38+!���������������uveVQLIJRWgrx��������������������������������~tlcQUQEDKNQT_V[aX]dbikfillgbhegbib`dfdfimjgllkmgkqqvstxnorrttuuuuvt{uzvwvxw}z|�}���wx|�||{��smmlrumltvw{|ysyszxx�|uuxx~��������{��|��������������u��������������������������������������¾�����ý�����������������������ì�oaedabhlhhmknkjpqqprnstnomqlpmrjjlkknjfgb`iknqp{~���������������������������������������������������������������������������������������������������������������S1-'//+-00+./,-/627014500656352,,1-:1869@95753,/.1115=??F;1& #$���������������vj_RHKKQX]gpu��������������������������������~tn^QQGIJLQXWXXU\\^_ehjbadal^afhaddcideeajaglklmolmopwwwkmmoquupwuywxvwxxvzy~yxx|}x{�z|zy}||{��qlntrsnr{vxwwro}{{yr{}~~}yx}�������{�����������y{��������������������������������������������Ĺ����ļ��������������������������ƴ�la_bddehgfmlkorqqvvoqqprnriphmiilhnmkkmiadlgpqz{�������������������������������������������������������������������������������������������������������������S6.,+-3,*+*/+-3,,20(42102=<21430.-13@5864.5023)+341.24ECM@<.$#7��������������~sf[QKLHOX`enw��������������������������������ysi_RLPHGNPSWT_\X]_^fecc`cnrgbdc^a`egbdf^baifijopomoprrpr{ussvupr{qtzxuzqvyxy|wz}{{}~}w|{tx{~��|nsroquxtystrnklzxwwuz~{{���}yw��}�~y��}������zw������������������������������������������þ������������������������������������ʵ�sbX]^bc\efgelmiqspnqrrjnllijjlmprpjlhgedekjnpv��������������������������������������������������������������������������������������������������������������uJ22))-24-)),-.2351036120:771=932*()/3=>836.3+,1,+:6/9?EJHD62,  "4b�������������}xm`STKKHQXbdmx��������������������������������{yl^UMLHFHOQW^VZ]d`df_gdg]_faafdb^ag`cef`ehghmkljmllumqnqwtvptuusuyvw}vywyzyyy|xz}}z{~yy|u{���vjovpryvvqotlppvrrwsvy}|||�|u}��ys~�����������{~�������������������������������������������������ž��������������Ľ����������������õ�p]_\_^\^fbdfilktolinopnjhhdlollpnimfhfdghknvx|��������������������������������~���������������������������������������������������������������������������nP43,/02'+-/(/413*14564472561+02.,+(,/6;:722->3..006679@EAF<*&% $4^��������������yqdYPMMNNOYchty�������������������������������~yn[VHPJHNSRWXWZ]a[\]ca\ceffccjee]fegaccbekhlmjjompmtqsptpwtpspsrtxvw~xxxwy}|yy}}{y{~}|yyyz���|looqtvprlmqjomrqrvuyv�����zp~���yty���������zy�����~�����������������������������������������Ŀ������ü����������������������������ɘrnmkcZZb_eagheqlllppoomkjjlljejrghgggagejpmr�����������������������������~~�}z�}�����������������������������������������������������������������������qP;0./1.,'&0).()*135<=D:6133/11,,*'))07569899<1/7514674=DCD80&" &3Vz�������������|tl\UNNPKMVU[hww��������������������������������{qgbTMJGKLRSTZeX```ceefdaihfcchfgbehd`ebefddhkklolohsnqrtrspmrpsytv{yxvuyuxt{{~zw|~~|{|z{~�Ʃtprprtrrtoqjhqtrwzwwuv{x��{n}�|}xz��x���~����������������������������������������������������������ź������Ⱦ�����ý¿��������������һ�����iY[^]`igonpmmrljghnmihjfjikhedadc`ilptv|�����������������������������~x�wv{|~���������������������������������������������������������������������{VA/.-*)'/*,4)&)+,0137547556/4.,,..(*/0353966/0/-21264@>CCG<30%""/Sp�������������wmaVQMRXNPRU]kr{��������������������������������~sf]THMHINSQTWWUae]fef_^a`fad`ebececedggcejephdkiqkkkqrmsvuxnuvuvx~xzvxoxuwr~wy{v{{x{||zv����nrtuwnijnginmrnuyvxxrvz�xwt~�~z~}|�����{z��������������|�������������������������������������������ľ������ƿ������û����ƾ�������������������r^TX_`cglkjlodqlkfiffjghmlnhhegberoqtt~����������������������������xzwrwvwz��������������������������������������������������������������������iG----+,-(50),')0276372529=5740--,+0,6758D632--,320175=CGB8/('$#'/Ko��������������~we]PRoPONIPZbfqz��������������������������������}rh_VOJMJLSPVXXX^_^\ldbbe_b_b_ddbfedfccfbkdfjfmpimpplstpsxvwouqorrzytvzu{z|v{}{zvvz{��{z}{���tosqrrjmnpkhlqsqz}uuxqzw{r{����{v~x����}���y����������{����u������������������������������ú����������������ÿ����þ��������������������������ˢkVY[[eflnmjmkofgieakhllggeffge`bhkmtw�����������������������������ywurosvrv}�������������������������������������������������������������������pU6,/(*00(((,)+(,33:/3688861021*),-005<3:;313/502511468AMM@8*&&"#+Gc}��������������{m^RNPPUUUPQY\gvx��������������������������������ztp`ZPFJOPLV`ZUZ[_ahrdcfbciaj_afbidbbieeeelgkekponprnvvrtrrsooquryrwxzxuysxz{{|zzx{uz}y{|}��~ooyomklnkholmouvvxursswtj~�zs�~vy|u���y��~����������w�����������������������������������ò����»�������ƶ�����ǽ����Ľ������������������������˓]ZYYY]ejgfjlmhefcffhhhijeheja`kjipmw�����������������������������{vxjklpsou|~����������������������������������������������������������������wX;32)+/04-'*,9''+.421645453.2,,0+.+20;958876//-08224<99GOJ>7'%),1;Zv��������������yrhZQPXUWZTRJXagm|�������������������������������zth`WPJLJQTSYZXX^efbjb_g`ccfhb\efdbcggddfgffklhirnsoyru{~qortqsnyqsp||ww|xu}~yy{|wy|{}{���vvrqpnkmdgjupiq|w|yvusxqk{�{}{�zvy���z���xw������|���~��������������������������������������������������µ����ľ���Ž���������������������������ܽ{VRSSZaaeiiieeagcdcecighehda^cgilmlw}���������������������������|wsnfafighox{���������������������������������������������������������������|[?9.--+++--%&/2-.154354433413,*).)*+608?:1-28/11.1006:AHOVM;3)%%1>Vl��������������~un`_QMTSUVVXQW^js~�������������������������������}{rk]XVMKCLMTRSZ\_^_`\b`[cacggbbd^acffjefbffiilllhqonqlpsvwowxout|zwy{xww~y}w�{}vwwwz�~|���|zsmjojnnijpomosutrqswro|�{~}}x�yw��|z~~x��|�������x�������������������������������������������¿�������������������������������������������գcSMQV]adcihgbehgfdfghcehef_fdjhmrss�����������������������������xplg]aZcehry���������������������������������������������������������������mH.)-0,,-1)**/55.1-1:>.12<042538.-(*.3497:00-2//.,2136>EKZRI=4+,1CXp���������������yqkYSPRSSTPTVTYcjq~�������������������������������~xshZWPKKDKPUZW\]^Y^dabagf^\^aiciafhgajfcbhhhjknnqplnpnssrroorqyxzr|�}z{{wyw|zxzwv{w|~~��~utjmphmmrmnpnxruw�|rspow��zx{|x|rv~|t�����wz�����{����}���|����}������������������¾������ƶ�����ž������ƾ�������������������������������������޽�ZJSZ[\cadfhekfcchhffddaeg_^[agooqt�����������������������������zqea^\\UYbomw�������������������������������������������������������������oO6+*23(,9&,,%:+1.31;972264876/./.')05A6<<71-(120++318=DNQQOF=/'1<Xn���������������|si`OQSSQRUTXRWW^jn}�������������������������������{sh[WRMMKMPVYX[_^_a]]cfjq^bbhf]f`ccddcgchgkhjnhkolnooooqtuqvurvouvyxwwwuyz{|~sysy}|z}z{��{volrnjohtnsptwsx}vvysoy}}}uu~z}zxxvv�r}�}v|�y���w��|����y��������~��������������ƺ������������¼������������������������������������������������ϫuQKUYX^dcgcdiecjedbchgcgecaa`jilpq�����������������������������{wjZYRVRWY`lqx�����������������������������������������������������������sX7**(0('()/*,/*3./5163:30627422+.1+,04;89;3./7-5/./77=B<NGML@901<Tl���������������wqb`TOSPT\VRLTVU_iry�������������������������������{wnj]RQHKOIRUX[Y_a`````cjf`gec`^ggc_f_edhhggjgjmornxjursqpqrsoqrxvuzw}xwx|z{z}xyz}{|x�~�~ytojhjlqsmopotxxt}u~vul~}y|ot�yw|ss|yln|�{������~���{����������������������������������³�����·�����Ľ�������������������������������������������ͤgNPSVY[ce`debfeeeacdace`c]Y\ekrqs�����������������������������vl^UNPSORWfqt�����������������������������������������������������������hA4.1&(''#&(+))+02079658?4241./**,,(/295<21,'.2+1-105;BCEKALF;00DRm}���������������|uf`YOLVRXTUVUYX[bns}~������������������������������}vmqhSSIHJINUX\\\d___ddbbg]fchc`djjjec_chcchfdcgpoponqwuppsq|tpsv{qyxy|{w|syz}zy|yy{���}qpmnjdnnpompwv|zurwtrv{{xytqxzt{ztnz}vt|zv}��z������������{{�������������������������������������µ��¿������������������������������������������������ʒYSWQWV\]ac]debabe^dbabeba\aenoow~����������������������������~tjZUS@DCGS[kv{��������������������������������������������������������kR21*.$###(*07,-14714867.1900021-+.5,1151821.-/2.15347>FJHLBAB=?FRgx���������������~vi^VQPSWYVU[SXVV\_gpv}������������������������������|uqie]WSKOQSVTWY^]_c_]cdcfag^be]ejohhiehffajngimnnporpsvussouvsuysuv~swzz}wyzx~{|}~�{x��}wnelmmgqqimnmlt}sxyvm|~�|}tx|{}x|rx�sk�~���{������������}{���~��������������������������������Ļ������������������������������������������������������ٻwUOQWVW\`[\]fbadbefeca_cccbaikrq���������������������������yi_SG:@>>NZemw�������������������������������������������������������tU6+*$)*,())(,+..<84<6798267744..%*-3357;832),.+/.4443?=FORPC@8=K[jw����������������tneXOQUUVWY`WWTQ\\Yepv��������������������������������xsjaZUPLUKQW\X]]X\\[aaebafcaebcfmhgeegdbefgfililjjnqopqqtrrutrsusuvwyxzy}wy{{|y}�z{}��utiijfmlirkrp{qyuqpsry~ysz{u|yxux}uqoz�|������~�������������������������������������ĵ������������ø���������������������������������������������������ҨmWJPOVVaZ]c`b_^_bjf^ba]bY`dippr}�����������������������������wfaOA599;BV]rpz}������������������������������������������������������^8**$$&()&)'%.)/-425?3B6859753,)&&.246588.0.)58,3;BMI<?BES[=G<<IPgx����������������|riXTSRWZW[Y[^YVSZ^bkt{��������������������������������|tmb[SNLSQRS]ZZ\_\a^bbd`efdee_ckekgecdacfdegfmnmkolntottpqstwnryuvvy{xuxs{zv{|y}}{~~}rpkjielgkrspvuqzvkm|{|vzs}zwyzsku}tmvwyv�}����w����������������������������������������������������������������������������������������������������������ǡmMKQPTX[Z]`faabce_\ca^^[befmrt{�����������������������������{laQC<8/3:NYbouy�����������������������������������������������������mH5,1&&'+)())),2/7:<481/7823:42..((1836;47-0-.+,0.8<GEPCADVHBECLZiv����������������|rj_ZWPQWYW[[Y\SSOU[dim~��������������������������������|rj`YXNNHMNQTW^_Z_^a\`^aafdgghgihgbfhgbggfidkqlkloshkqotrstuusnwuwzzyuxzzv{xy�w}{~��|utnnmqliohhroqtnnxpmw�y|{sxstz�}urrxsouuv~�z{��}~���������~����}����������������������������������������������������������������������������������������������ƚhQLMTVQ[\[aaba_bd]eb`^\`filtu|����������������������������|qfXF<3.88ARWeut{���������������������������������������������������pP4(,'&+/3'-)+1.05<;<45:5:886241*1'.2;9>51/*,%(,.-5DA?=FGDKUKKCQZk|����������������{reYUOVXWX[U[XXSVXU\_jn{��������������������������������tqj_VTNKJMRXUX\\Yaaca`^f`aeme`gcmfgjdegagbgdlkoqjoniovpwypsuvvttwzxvzxx|{~}{wy{{{���wmlspfofgqlopsusvlpmztwyuwqsmq�{lstpqvwsz�}|��t��������|�����������������������������������������������������������������������������������������������������Ŕ\JRMOUXVW\b_^^]^]_^a_bg`hnqty���������������������������}{mkSI@4.05;GW`lrw���������������������������������������������������Z=25,'1)'&,.+1.5;=:3590=46822/-0.++5<>;:432,-3030>6:<<>AGCKPIJMXhs����������������}rc[YSSVWUZYWZZ[WVYUZajpy}�������������������������������tok`ZPOIIMTX^Z_]^`_aa^]dibghe`jjhghbff`gebfimmopjjkpnrqyrstuntvrzv~~}z{xys|yyvu||��{thokgjoiipjktoqtqkvy}zxquwrnv}woqsrmxz|vw{}��{r}��������������������������������������������������������������������������������������������������������������ذpTNOPTTY[ZYYZfdbd_aa^_b_fhps}�����������������������������|se]Q93)*-4CL[flqz�����������������������������������������������~fF0*'<=IF;),*+-4;6?756689;1746/-3..,879=35/3*,-0-)7?9;:<EMNKOQPZds������������������wob[RVSS]X^WY[ZWVXXRVaeps}�������������������������������ysna\OIHMNPVX]Z`]bebb`aej_eid^eefhg^edaggcgmikiljopjqsmqrytwsqsxzwyy{xy{us�|y~y}�{nkmskjkonosmmqquqitz|�vtr|tu{ryxyrfjxuy~�xy�~zsy����������������������������������������������������������������������������������������������������������������̞fPJQOQSQVTYW[]]X^]^[W\fhipw|�����������������������������}rf[O9,((1-=KUbkquz�����������������������������������������������kI3)01RV;>99.+,255375341668;71/,/-)1468:862+1-0840.8?8?BCKNJKER\dpy�����������������|tf^OTX\W[]\ZV^ZRSZVXZ]hq}}������������������������������}{pcb\PLNGKTXTWZ`a_a``^]cb]bhabbcdgcgc_dahcekjkilkjnnktltutsurtuvxvxy}v}|zvxy|y}z�~tjkopghonqqynqrtqlvxvzxtutuvzvlzxkdgtrs~��z}�}v����������������������������������������������������������������������������������������������������������������������YKLNIVRRUXZXZUXYZ[]`^digtw|�����������������������������|xg]N@0-)--:FTbcjsv����������������������������������������������vZ>+33+*1--.--).1/47238045499800+-,/3=8;30///-4/472155<=I?EPKUQXcmy����������������{{xjcXVUUS^\]a[VZ\[X[XTWYdo{�������������������������������wyoe_]TNHMQVXZ\]`b_adgc^[f^bea``efdZcecdcjfhmihelinuqqtnyttvtutuvzwsztw{zzvzxy}{�tmokjmmonsmtoowoplvvvztszv{wvsusvoimuup~~z���v����������������������������������������������������������������������������������������������������������������������ھ�MGKLNOKUTUTZUX_\[Y[abgirv����������������������������~xj]J61)%,189R`_hkw|��������������������������������������������dA*(0&*.'3-&*)0*6436474.38430./-/-125:=DB..025:25/13/4B=CHJPQTXdpz�����������������zznbVSQUVSYic[][\[WXSVTVcbpt������������������������������zljaWSOLUNQT\^^eacddfbfbf__haa`ghg^`kfcb`gjlmihknknmywmupstsrrytxvxwzy{{|}{z}|�yuwqjljjor|rrmmn{rrttyvrtttyrcpvsiopqnx}yv���}v���{�����������������������y��������������������������������������������������������������������������������������������֨`URJJHHQQVOXXW_ZZYW`_giqv�������������������������������q`XN</%%$,7=JPdgrxz�������������������������������������������qQ8((%'%,.+),*4014887215@<5622/,#),,56<=A9/+102172147289BBQMMQ_iqy������������������tti^TVQYXZ\_]\Y[XX]WQWVYabky�������������������������������~sqd`ZSLGMMNWUYc_da_aqccad`bfdbfeccgjefgdbghlgekijkkrnlttrxywuqttvvtrwurxy|~�|~�wrrrrnljmluvoorkmwoqvwvsvuyypkmtlcgmpqtxrw�|x���y}��������~��������������|~����������������������������������������������������������½���������������������������������ŅiYNLKFRQRNTTSVTXXY`bgirx~����������������������������yndVM>0&$,-15DOdafuy������������������������������������������d?+)*&#)0*,,00117;25:78396552&.)%(-08<7;21),)4//3301:5=7;@JJQ[irz�������������������kkfUPSS[XW[[ZX][Z[VZWPXT^dow�������������������������������~wrlwYRHGPWV^YY_``eY^bheh\cadcbf_dafkhcfhaejgdfejlnpotmquvzyyorrtuuwywzywzy||~��wuxssnkrzokuvqpvkpstuxzty|xqrsuooqrrsy|wv{�|s��|zx��������z��������������������������������������������������������������������������������������������������������������ָ�z_VPPLJQMMUXT]YSSV_akpu|�����������������������������~tcXK;/'/@5,*:O\`jjt������������������������������������������lK96-&#%%+0+,1/1;686??631942,--+&%1159<<3-++285450578@H;=7@FOUcuz��������������������cc[UTWWSWX[_][_[]]WVSR[\[ejz~�������������������������������|nkaYPOKOPLS_]X_baaecdagZhddcac]gh`cbddifjigjjilmjroqptr}zsswssyuwwwyw|x{wu~��|ssztovonzkioqnsojoystztpxoinrqn}zq{�ztt�y||y��{y���}����v����}����������������������������������������������������������������������������������������������������������θ�~jULGKJKLMTS[YV\a_km|}������������������������������tdVL;1-*#)9A>;T[]dnt�����������������������������������������vZ4),,$%)'&'(,.83:;8<<5-4461/,-30)*2;>;791,,-.5557;:;<?@B@:>FRdn���������������������aaWQUWXUXZ\b\`[\Z^[XVYUYggkv�������������������������������}{oiaZSNLKNMNXYa_`_aadh`jbfdgaacc`dcchgicnhigjiqkgmolttr{v}twstsq{u|y}zw|wyz��ypqrprtyvonnoqlopoootvor{tkp}qyr{xk}rm�}zw���{~���zx����~����~���������������������������������|z���������������������������ÿ�����������������������������������������������ʹ�aGDCHJLIWWSWUX_ceow}�����������������������������|rdYS73*-(-=;30;O]`hzy|���������������������������������������h=')%))%(('022.=D777656937291-./+2-17?994/0**38924943887:==FFXhx����������������������ZZTSTZTY[YW_]a[ZY`[ZUVSW\kjxz������������������������������}yqja`SJHKJNLU_W\`_e]b_bbd`cha_da^cccadeahblhlhelllqmlrqvusqrzprpyttvw~{yy~~��xxpjslmmrwuuqpmpmsputruwzuvrryx}z|z|vuwyxrz���x}��y|�������������������������z������������������{�������ž��������������������ȿ���ÿ��������������������������������������������_NRNDGLSMTNRXcainv|����������������������������|qdXS;3.-,.*"+03?VYblv{�������������������������������������lL8,.-%*%')',1-:29;>7::977750/*+&..12;><50+0,1014:37/77:@<D?DRcq�����������������������WWNYQ^^]WY\^XYZV[b^WVYTZ]bivz�������������������������������xsk_XQKLLONQWV\`]_cc`fkddicfbeffbcgccffjffgfflipmnolnortwrsrqv{xyuux�su{xz���yojlrlmnnutuknkkjnmrrp|tts|nm}ywz|{uq�zqzz��~{~���p������������������������~���������������������������������������������Ƽ����Ŀ��ƺ�����������������������������������������������nlS>EHMQRQVX^ahkr|~����������������������������ymfYT>0(*&',+(20>FP]erw}������������������������������������vY4+%+(%(&)/+++1=724;7D:8822497+,'028B::60-+1:/,:76;267<;?ACHPZm~�����������������������ZZUUUZYY][[[ZZ[\_YYVTXWZ`dqt������������������������������|yrlb]SPKMIMVZZU[b\`^Zegeabd``dddaceh_fhlpefdgjilmonnoqqsxrvtrvtvtuuy~tuv|x���tpjijninntyypnwspnmommostzqrpvtpz{ou|sqz���~��|x�������������������������������������������}�������ľ���ľ�����������������������ǹ����������������������������������������������ŜxUCFHIHORNUV_hntz|����������������������������xrjYOA5=22+)")+54=OWbht}�����������������������������������~a?.%#&')+%(-,.-//5<;9878857735--,..278663-.231./8445?;0;3:9>P]k{������������������������YY[QS\Y\`\YbZ^]Z^_\WVXXZ\for}������������������������������}~roc_WNJHMOSVW\]_`_afc_cc_^c_bffabddeghgachhegpmmlqpoqvvwuvyuwtxuyv{zwyxz���{ulotpfjopnrtrotmpqluqipsqmqsutwtqvy~wq|�������xy�����������������������������~�������������������������÷�����������������������Ļ��������������������������������������������������ŗaA@DCGIONWY_cks�����������������������������~xmf\PA4-+1*($(*.08FWZjhv�����������������������������������qH-3(#)%++'+)7/5/5B77935078:60/3.2.7<:@G;6.,.9=145343742688>M[qz�������������������������ZZWYW_]_[^]Y][b[VX]XUZ[\bgls�������������������������������~|nlbcWNIFLRQVR[][`[^cd^decifefdfhbfcdgch`dgdhkjknrnnpsuruuuswxtzytsstwxy��xwlkrojhdimnvvvrnqxpnpsuwriqqovvrmy|qvv������yz�������������������~���������||��������u���{����ÿ�����������ļ����¿������������������������������������������������������������������}L=B<DGKMVY^fkv{�����������������������������ypf]OB4,52*+&'.0+5?MZ\_o����������������������������������uV4+)*$.***+3,2,15;78217365:730,++70596351(.-29745238166195?PTi}��������������������������UU\X_^[]^]Z^`Za^YZ_]YVWbadmw�������������������������������zrl^dTMJMNQRYYY__a\`_``\^ajegeaeg`febdggb`keghhikqmhlqquurwtuvyzxtvuurt|��zsrpj_gddfjglu|tvworooqxruyvyouosr{xrnzx��|w~����������������������������������������}~����������������ż���������¾����������������������������������������������������������������ֵr>56?FGLTZYems|����������������������������vqeZOF3/,(++%&&-)/5:LX^i{y��������������������������������c@..,()-.0*)--5.2294;75/346H4400,3254<23-,**/0142?@74/3333;FUgz���������������������������UUVUP^[^_\`^Y\]Y^[VZWW^^_cu}��������������������������������ynh\^ZMLOHKRR]]^a[a_cae]c_hdkihdd`cbebbdldbgghrklomlsoosutwtyyvzwuoossr���|rfe^njfbklckpossusvljtoksprtxtlmwsxw}wvx~��~|�����������������������������������y�������������������������������¼�����ÿ���������������������������������������������������������������֧[;9<BFLPV_`mry����������������������������}vl_[C;--.),++%+'-17AK[er{{������������������������������sT/*,+-(+2+.4.151;54437944;76142.,-4=<=/1,-+)142302E62.24.;=Lgw����������������������������TTTSW[Z^^]_`\a__^^Z]V\Zafipt��������������������������������wrk_WWQKOJPSWTY]b^a`_\^ff`adefh`bc_cd`]eedfhgljilmppouonrpwxwsqw{muuqr}�č}medjfhlhdjiloqpqrqtmopkprjsqnkttrkz}}vx�vz|}����{��������������������������~���s|��y{�{w�����������������������ǽ�����������������������������������������������������������������������ʼnE<B@DHORXakpz�����������������������������~sj^UC80*-)03&,&*(,1@IU^_sw~����������������������������vW7'.,,)),,()7).46692547?@4?773.,,.+4?:838+.03-=4500160-47:;E\oz����������������������������XX\TYa\c[_U]Z\`_\^Y[Z\YYagrv��������������������������������wqjaYTMLMKKTYX`^[[`__a`^c]bjehceffe`badhefegehkimmkpumrqvsrxppsqroqkos����xgehiikmkepjosrjrtlslqtrrrvsnnqpmp{{|x��|py�����~���������uu��������������{��yu���~v~~�}���ý�������ȼ��ü���º��������������������������������������������������������������������������ױW?<ABCLRZ]cmv����������������������������~tk^RA;2/-1--/'0*(.,/BHTZmvv~���������������������������hC6)+0-,-.*1+(1.561;842;9361726.4.41567320*10664;73/.4-+.:<IUi|�����������������������������^^ZW]]\Ya[^^XZTXY_[ZYYZWderx��������������������������������zpod`YLPLOSPXX\\_\Y_a`gae``feebefcfbccd`gejejeikknmnvssvxsqtmostwqqnrs�ƪ�vdcccghmqehpstpmrpplqsmqyukovurrqxzz��}lu���������������vt�������������}���zv����{y|x�����ſ��������ý�Ƽ���ž���������������������������������ƺ�����������������������������������������qUZWGBGOWbimt|����������������������������zrk]TC<6++.,*-)$'$%*07BOYcov|}�������������������������sL2)/(,++*)+,;4/22;3875:8;162?2/)034=9:=52025464?=;606(',.6NWiv������������������������������YYXYXZ`eZ\``[[]ZY[YXVXVT_epyz������������������������������xpia^XNEFPVTSWZYY^[^dd`gfadbaeadjdeaeahdgbfelkiljlnqusvnvtssurvsooosm��Ǩ�ocZhjmjsmdltnrhlwqirnsotpmnrrvr}{zr{�~zy��|{{��������}z����}����������{��~{ty�txt}ox������������ù��¸��������ú��³���������������������������������������������������������������������ѥ{aQ8FKLSX^nv|����������������������������{qi]WA:2/.-.,./),&),..5GNYaitx|�����������������������y`8-)*+/+-1+1-51259710-155236:1/0-/6359:526,-5/76;8281.()/99Lfz�������������������������������\\Y_[Z\]aXZZY[`_Y[WVRZXT_eov�������������������������������~~ukeUWLNLMPXWSVX[a_[_`b`fabfeedbfcffccedh`gemnkqppnpsrqruptvswusqkjpp��ǩhbigdrubfikklkkqukkwltstppxwwzys{uw�{v����yz���������||�����t���������}~���|��{qgrpmx����������ƿ�����������¾��ƿ��������������������������������������������������������������������������ͥnI8?HKSUbmyy����������������������������}oi[TG:70.,02/(,(%()(*47DN\bkrw~��������������������hB1+,(),0(*.2024/3?<8134868:6/52+466:89:/*3/.678<;110-&!(.2E\s��������������������������������^^][[Y\]aZX]][Z^^]XYW[]V[ekq}�������������������������������{sjc\QNHJPQOY[RUVa_^abdb`acbgccdhiekefefejfmmonsmnllqooqrlsrtollkhjow�Ͽ�ubkabehghmmloknpmmrggntrsuqx�~z{wt�{xv|�wx���������}z�������������������zw��xolorn�������·������´���¼���½�������������û���������������������������������������������������������������͢a98EGPYbo|�����������������������������{pl_SLA150-0**3-,*)&)'(.<CP[_gn|�������Ƚ������������qJ0+*/1,*63,,.028;9<@6210;55:85618410:25:2-/5873;9942/)*##0;\h}��������������������������������XXd]W^]W]]`b^[`]\]W]RTXV\ciu~������������������������������}wsn_[PQIGQUQWXXYYe`_`^a^[adcbbckjgcefacbiihnpkhlmprolmtutsxopmqookoq��ζ�rdegjjgkkilngpkhqsqjntoqyppzvuvzzxotx��}{}~���������|���|���������������zu��{kkug{��������������Ŷ�������þ��µ��������������������������������������������˿���������������������������������lj>6>CKYanv�����������������������������}qlcRD>83-,)(/0*,&1*%(%(-5COVe�����������ê����ū���r\6,+''+/-+;453/7608:6721.7489=84/901;846-//775=4172251.&(-<Pf{���������������������������������aaZaZ]X^^Y[Z[^[\YVY\UOQWZcit�������������������������������ztneZQONJLPTWXV^`]]cZ\a]^aaee`dfmgbeidgmggnonknfpkmrmqovtturollkpfly��ȭ�xachrjkhcgjjisnljororsppmlxwnvuvu�}}�����������������|��������������||z�}}nhgl{�������������������������ĸ�������������������¾�������������������������������������������������������������ݲX6?CKS_ip~����������������������������~vg]R??2+//-0-'0+),&()#(..>Ni������������ɿ���������Y@/.-.**,102.)116828489678:@B;:71<9540.60,2/0398<920-./,,+7Lar����������������������������������ZZac[X[[^ZZ\VWYUWTVVSUSW[fkv��������������������������������~|mh^XSFPKRRS[]^Y``^^\[abf_hlbcdibeb^bejiixqpjnlkihokqnootrooqrlkjj���¦�sebdpojdhjjmnmsmgptosvmillldp}{usu�~w|��z������������������v������~}tn��~ytmkr����������¶��ô������������������ž�������������ž��������������������������������������������������������������h35CJ[^km}�����������������������������wc_UH953()-.-,+.-&"&#$#&2Iq���������������������ϰqF/*+,,3**8C7*33=;:65753485:>CB8422;85:3.1.-3626<7710,++.7;L[s�����������������������������������\\`VX^XX\ZWXTV[]TVSTUUTUZbjs�������������������������������|ypfZRPIJQRPPSW\\^]][_```cca`^_\b`ca_`aehfchggkqkmookppwjpppommlkdl��Ͽ�|j_aiiekhgekclirvqquroklpoifpyzqn|�y|}}�����������������������������ndl}xrpqlw���������¾���������ż���ŵ������»������������������������������������������������������������������������������ӔC:ANSYkw|����������������������������{si^RI460/1+-1),+'($%#"'2A|���������Ĺ������������ʔ?**(+,.*+*-.*/,4:;316663521538801664861,5.7165<8/.+(%'278NXl~�����������������������������������XXX\[^XX_U_XVYV[U_ZWSXXTYdioy������������������������������ztmb`THFGMOPOUX\U[X]Z_bXd]]]ab`_^c_affh`^egcehjnjlpmnrwqnqnrnmhelby��ʷ�uk]dgmejaljinhlqvsxuoqiyvlkpxvny{yur�������������������~~{��������}nqx|~xqqpo~�������������������������¾�����������¿�������ľ��������������������ž�������������������������������������������ڮT5?GQ[hq{���������������������������~olgRG:/2.-//-.'(*(&3&'-F���������Ļ��������������ҸP"#%(/+1.124*195>A=4:89>.17064/=59779<440053<6E>5.+'%*-->Xix������������������������������������VVXYXV]]Z[[ZY]\^\b]TTOVQV`kuy�������������������������������xsga\PFBCJPOSTX[ZUXX[`^]__^a[_a__a^_dbe_fimhghekgjjoikmlolppjgeadc���ɥ�{mf`gnifdgmmnnrlpx|qgoluqwtoiu{ztniz�|�~��������~~�����v|�������}xnoy{qrnsqv�������������������������Ǽ�������ö�������������Ĺ�������������������������������������������������������������������x@=ILYanv��������������������������ynkaVI;2*/).()'%%$'!%(.O��������ɷ������������������p&&*0,-(1//01247774703AAM73,3415646683520057D9<A96*1*,-4E]v�������������������������������������aa[YZW]][YTXUXZY[ZXVURZPTdhp~�������������������������������wplaSOFDKKPTWRVX\VX]a\`Zbb^a^bc^a^`_ebfaebifejgiiilhljopokmlmeddil��ӽ��ymj`fjcdkiigsnkjrsvpmuppsyupp~�vmzz}~|�����������y����~r�������qkpy|oaahl}������������ȸ�������������������������������ľ���Ŀ����Ŀ���������Ⱦ�������������������������������������������������ΞN9BKS]oz|���������������������������woecO@93.+)++%+$$&'#-5k�������˿�������������������ן0*((-,2,/.036<>465162=7>96:;2333074;5003/:7493750-')*.DWm��������������������������������������__WY\ZXVZWZ[Z\ZYXZYVUVUXV_hr}�������������������������������zth_TQEJENIQNZSUZT^[_^``faab_]`]b_^Zb^ededhlijnkljjhjjltjnoskhfgmy��̶��}ohd^akfjkirqhotkkmxtqrutuuyswsy�{s|�{����{��������xsy��������}y|��xnekip�������������������������������������������������������������������¼���������������������������������������������������ؿsBCNVbjq����������������������������wmb\NC:1.++)('""(&)+@x�������ī��������������������߾O"*-).',6/,/;7<=91415=739112.3483820.-:5=.87666<,1'++=Ljy��������������������������������������WWY^YU[ZZ_^_W\Z^\]^]WYPT[dnr|������������������������������xyrk]ONLFEIINLOSYZ\[[_^cc`bcc_bcde]`bgfbfe`lghgenkjmjoonooslkohfck���ij���ria`hikkfimqoohgstvqqzomt}{prw~zvs��|{������y���wnjv��������{x��~vkmkjp������������������������������������������������Ŀ�����ſ���Ǿ������������������������������������������������������������͠^?BXZmt{���������������������������yod]SC4-.&*'(3%"$(1M�������͹������������������������~*)/),2.+,10/499477:6483610...520820,3418;341>62-+*=CKgu���������������������������������������WWUYW][Y^]_^^_]b__ZXX[TYZbmsz�������������������������������~tj]XNDBIJLNTRTWW^Z][c`baab`aabaeabecaaah`dgmglfjijknmtqsnnlpjbcl���í���rfgibledkmrorkclvvtqlquuwruwxy}qq{��}~����zxw��~ser���������|x|�{qjomfv�������������������������������������������»��ƽ½��ÿ���ù��ľ�»��������������������������������������������������������پ�MIKTjr���������������������������wkh^UD03,+$) $$%(2a�������ƫ������������������������۠4(++()-/,210125;666:23.-*/2/9.63/2/,/.;4<?5:-5-0/32EWq����������������������������������������ZZUX[XU[[[[ZZ_^Z``_UZZZX]bhu~������������������������������|ueYVMJBDIGKQPPZZ]__[^^fbbhcbchbac`ccdhc_fefjemigiijiqsroophhheg{�������wjcjbee`iaiplegjow~smklwvnky|xkpn�~�����|un|��qk]u���������|���zronnkx��������������������������������������������������¹�������������������������������������������������������������������������ӲkMKVhp|���������������������������{oiZH8+''(!$"$$,Dl������ͻ��������������������������߶B'+*-,,)-5./16239<F.-0072+-35:=:00-9.045454617-052EXh�����������������������������������������ZZ_X][Xda[^a][fa_b\W[\YSZamty�������������������������������vmf[WREGJELJIMPWX^d_Z\b_ccb`cdfafedcbddceadjjjliekljprrmrrlxihcg����·��ujegebajkhjqiioloywlnlspts~tknw��|�����vot}�tcov��������{�~zqjprfi������������������������ì������������������»����������������������������������������������������������������������������������ɘZIVaq{�������������������������}yoZXD3++&$ ($*0H�������ɴ�����������������������������_,*-%',+/45<4;@3477.2:31,22<650)(,11422:569822/.9=Ghy�����������������������������������������ZZaV^``]\Z^`\\_``^[\Y[W[Zepox�����������������������������|xmiaUOSHHKJLEPWTS\a[^acadfc``achc_fdbehddcfffigfkoghnpqrsquxicfi����â��ug`cbdegihgfkmmktv{qqiipysshr}}������~wrz|znoz������zw|�ytkmokZf�������������������������������û�������¾���ƾ���¹��ƿ��������������Ž���������������������������������������������������������ӻ|LR\oz���������������������������vh`PF0+$"$"#&0R���������������������������������������s,,*,(0,.7/.2140;4;54814/2.3+-,*$+7-02999;:8838.8EXp������������������������������������������aa\YW_W[_Y_^`]ce`][]ZUO\\cimz�������������������������������xqf\QJQMJPQNNLWW][a``fhdamcddddci_ddcffdachgihjkkkkolpsrtytsjkgm���ɼ���uba^]iijleiikjovqiszl^fv}uikx��z����yvz��yphuz������}xz��~rjptqff�������������������������������������������Ļ�����������¿���ɿ�����������������ľ�������������������������������������������������ϬiNZqx��������������������������~pjbY?/-#$"#*9^������˻�������������������������������Ύ,)*-+.+0021378/81222/--23022.&+//9609=;8<2170..?Mj������������������������������������������ZZ][`[\`cY]]]a``c\c`_VVY_hkly~������������������������������|sl]SOILMKIOROXU\[_]b^dfacbc`hgeibfddbehifefgfhnkqrqssmtsrqzojip��ҿ����r_^\d`njegijfpswoureYcopkmz��~~~���yt|w|vrsv}������yurx��vqovoij�������������������������������������������������½��������ú������������������������������������������������������������������������ƉRXhx~�������������������������vmj`b;+&!'+Cq������ʴ��������������������������������ӓ/--*),/+.0018822<<;1/./+002,/&(124250=67375//38Fap�������������������������������������������__\]Y`Z\]]```b]_`a`^c_Y[]cls~�������������������������������uql`XMFEIGNOTPYX]\]abddaceacfbdhdedhiddcfffjgjhkolmpmkoslnollfh|��������k]Za_ccdfdmlpklqro`Yaktvotv{{��~x}}�tmhr}������uqu���squkgkt����������������������������������������������Ź�������������°��������������������Ľ�������������������������������������������������ѩl_nw|�������������������������rq\UF2-)%'/M������������������������������������������֒,('('+2023.2311685/0-.3005*/+.&0.4,1.38865-/,/?Vp��������������������������������������������]]_Yb^ba__cad\a^`c]`k^ccbamt|������������������������������~woh^TOMJMNQEQVZ[^`\``b__cbbc`eejeeccf`iclkgmohjjlpolpoqvpnjciah����í���ne\`hgdamjoqoclko\Wgqqyvyzuyy~�wqz�zoroy�~����{uy����{swngjz�������������������������������������������Ľ�������û��·����������������������������ļ����������������������Ǿ������������������������ęqkv~������������������������{qj[Q?4+(,?e�������������������������������������������֔(*&*),.-476?4960.4)++-/4/.,,'0+-1103=7833.**35Me|��������������������������������������������\\__dZ`b]_j`gb`aae_b`c]Y`ckw|������������������������������{pmc\UHLNLQQTSV[X[]_`babcbggeheddecebehegkhllgmnlljmoqrnrxlif_b���ϼ����qf^acjnhkgoiljmbT`juoqtsv}z}�~~{r{�{xtgv}~~~����}{�����{�rlmdq�����������������������������������������û������������������������������������Ǽ���������������������������������������������������������Ģ~xw������������������������tlc`WH/-:W�������Ⱥ������������������ɾ����������������Ԓ*'&*)38326992<+0+.)/()+631-316-/2;2638.,''+14BWp���������������������������������������������__`]^^aad^cagdba`f_bb_b__fmpw������������������������������{ricTTNOJKNNVXX]Y_b_h`h`_cdd^jeecbjfgda`dkmjlnhnmkksmrsponknhcn���Թ���xok_ejjhacqijdeaRVmssqzxnr���yyuy~�xwzx|~ywr�����������yvofbjx������������������������������������������¾�����������������������þ������������¼������������������¾���¸����ƽ��������������������������Ǫ��������������������������xl_RG9=Is�������ij�������������������������������������ӎ&%%(+,..27;:B>342.2-0-*+,/)*62,8513038*+&"&97Jg����������������������������������������������___e^c`bcc_eecbe`ec_a^^]\cpp|�������������������������������zpkeXTVINPTTSXZ\a]`\bcfedghdg`_cnehagfeggfkkhhjnopnmoqqrqplkefp����ǫ��wuhcdgie_lkigjfZ`kuxzxtunw~�}vz~zvtq|�~|xm{������������~nabi���������������������������������������������������������������������ý��������������������������������������������������������������������������������������������������|xfZPDKa������������������������������������������������ӆ((%))/7763877:8)222*.+-,+)*,-152826310($"!%-GZw����������������������������������������������^^e`cca^dcgmcbbbcab\a``^_glq~�������������������������������zolcWTNJLPMSQZ[`a\\bbdfbaajgbfbfjgqghgdeefgmoklkpmlpqqourpigdcw����ɞ�}gn[ba_ddgejhc^ilqu}wqqvyrqtsz~|wigpzz|yw{������~�{�zm\[p}������������������������������������������������������������������ý���������������������������ý�����ǿ�����������������������������������������¡����������������������zqeYV[w������ʿ������������������������������������������|'0(-22-33346<870/5321.00.*),707>268>0) $!$)AUk�����������������������������������������������cce`cb]eeeccdc`eaa`^e]X\`eip~������������������������������ysk`XUOJOQQPWX[ba^]edhfbdfhlikcghemhjgafejfmonsqkmootvqttomjdc�����Ö��xrle]\bdabgda^lpnqryulq}snn~��vofq�}{yx}��{����}zu}{�ug\_d{���������������������������������������������������������������������ÿ��������������������������������ɺ����������������������������������������������������������������tq`dr������˿��������������������������������������������m',)*112354354F110330.-4.6-17978969;40.# %1Lc�����������������������������������������������ccacddecdddcgfbda`a`_ba^adjpy�������������������������������{rj`XONKOPRQ[UW[`^a_d_dbffehbfijfkikdfccddhhjtimlqltolwosqjjgg����α��wwofe]]c^dhhaennnproqnovri`kx�uqej{~�vw~��|v���{sqz��|mf_p}�������������������������������������������������������������������������������¾������Ŀ���������������Į������������������������������������������λ���������������������wpy�������Ⱦ���������������������������������������������Z-/*'&//20/..4>68B765013/.51312-74184,(#!",:]v������������������������������������������������bbaccdbj`fgddcdjcdj_]]`c\djq~������������������������������}tjb[VLJROTPWTUW`^_\ebdbdbbeafebikkbjeedcdehosknmoopqmsqqrmdfh����ȶ�{utstf`cX\c`dirnquskfjqyj_[g|vtuhiw|�}����|�wqmpxy{wibfo�����������������������������������������������������������������������������������ľ�������������������Ű���������������������������������������������˪����������������������������ķ��������������������������������������������ߺ?(1-*+,34-21364774882/,**--05<1675543(%%(4Sk~������������������������������������������������eebccccfddcecfccdja`cc__ebot}�������������������������������{woeYRIJNQMPXZWW^^]ahfebahehedchgdcjgcac[helmlijmmlnpotplof`]i���ϼ��vlwtgc^\gg^hllhmyqdcpvocbivzvvrv{{ywy|�����|sqxzywtlfks������������������������������������������������������������������������������������Ŀ����½������������õ�����þ���������������������������������������Ҿ���������������������������Ƹ����������������������������������������������ޮ5*/+1.563,/2.6538630.0.).-*/531567973(#&,<_t�������������������������������������������������ffi`ba_ikibccefcc`cada[cchntz�������������������������������yvqgYOPJIORSWYU^^[cfdilfhfdgdefja_jkeh_e`fedhlhmohqopmpnlihb^i���ɺ���y{wnje\cffjlhlpki``nnf^dmrwuutyxwxu{{{}��~}ypr|�}utmlkr��������������������������������������������������������������������������������������������������������Ƕ������Ŀ����������������������������������������˨������������������������ǹ��÷��������������������������������������������ٔ+'*)/6/;=301/4103056/'*),*,-32/84/4(+-''.@Qo�������������������������������������������������cchbgdfdfbacadbahabcccaccgnv}�������������������������������|spcZMPMORNVVZY][^]a`deffageefgcabgeid`gbhhjbggmokjmumlihfc^_p�������~��vtpbiiaclgioifbeig_Zeuvrxuxzvpmw�|~��|zvomr|~uyqqijt����������������������������������������������������������������������������������������������ý�������Ž��������������������������������������������������ι����������������������˾���«���������������������������������������������ր/*.*+-640110-.0706:312-1-/%-23763104-*.48Lbz��������������������������������������������������dd`aihgggdeicdcchf_dbcahinqy�������������������������������|vmaYNMPKQQUUV[c[b`\cc]`celedhhdf_ghcdbe`dcfelmjikmlnmonkjc^a����Ɯ����xxxndmdcliejhf[ethZYknsnoszvocfmy�}����~ujktzwvsuswjw��������������������vz������������������������������Ľ������������������������������������������ÿ�����Ź�����������������������¼���������������������������Ě��������������������´��Ȼ������������������������������������������������i(*,&*164/9;./22.28.22(-*/+,,15.6.60220/:Jas���������������������������������������������������aagc_gafdgf`fagcgb_]`f\dklow���������������������������������vlc_PJNMMMSVZ[cZ\]_d_hbcbgkccccgcfebecbcfehckjhlmljikkonbaac����ě����vjkkimhfngc^fgi`\irg^gsuph[er{ywwx�}{snlv�{srtqtr|���������������������������������������������������������������������������������������������������������������Ž���������½���������¾���������º�����������Ġ������������������ƺ������������������������������������������������������S-)033D675650519108,+5*()('-/25544716577GTj~���������������������������������������������������ggefcca^d`dbfbd_fia_ca`hcpru��������������������������������}tn`]KPLKIMZ]XZcV`bfbhcbccafhc`geihfig`kf_ehcjknjkmmhimgk_Yef����æ���z�uhfimofnlbdimaZZoqne`qqie`lv{ywtx|tqrhm|z{|xuvpm���������������������y~�������������������������������������������������������������������������¿ý������������������������¾������ż��������������������������ɱ����������������˾���Ǹ�������������������������������������������������޷B()0/304:3841372/1./+,)%*-52347639=58?@FN`w����������������������������������������������������cceahbdfadccg_bbfga^e_]ggmmw���������������������������������sh`YPQOOLOTW[YcY`]`eg_daadfhffcfdg_^afaecdhfilpjnknjjhjj`_Yh���ʷ�����{~{kakpkilkioppcfiiifhnuplcquzzv~}ykost�x~}zzyom}��������������������z���������������������������������������������������������������������������������������������������������������ƿ���ÿ���������������������ʽ��������������ÿ��������������������������������������������������������۞05002434476:2-76,00*+)'(-43,1350078;CCDIYj�����������������������������������������������������ggfce`adadcacddffkbda_agfmru�������������������������������~um_`MONPQWU[]aZ[aa^geaeaddf_bffdded``fadfhiehjngmkmhikeba^Zu���ʹ�����z�{magglhchooqlmpmcbkjropivwqpsw�zplrqz��~�}{vqn{�������������������ty���������������������������������������������������������������������������������������������������������þ��������������»�¿���������������Ʒ�����������˼����ž����������������������������������������������������֏4-0.,1071;555348222..'(2.44.3:4399:?:FGVes�����������������������������������������������������ddgaccbgjafaacbageded`_eehry}��������������������������������rgc]RRHOPQW\ng^X\_baceabeafbbfcdcgb`cgafjddiglhgkfiojjfaY^a�����ß������skndeke`gjhhonngglsiahqprrnpz{yqklsz}��~zpji}�������������������x�����������������������������������������������������������������������������¶���������������������������������¾�����������������������������è��������ɿ�������������������������������������������������������������,',183769@64,7<963.33-*//31.,-40/1?@AEJYo������������������������������������������������������ddgfefdcceidhfgcfebcagabemquz�������������������������������|spf[RJMRJNTVWb[[Y[]`degfedgcabbdccb\d_ccfbdjffhjjkggheca[Y\����ɷ������z�wvgeldciohkkhfgnvvddmyrlik|�zqom{}�z��~~skju�������������������ty�����������������������������������������������������������������������������¶����������������������������Ž¿���������������������������������ǻ�����������������������������������������������������������������������d!%*-1011.745040560,*.+*4+40/3569A9>@EK]k�������������������������������������������������������bbcagbejjica^]ceab`afbahfloz��������������������������������}unh[TPJGKNOTUT]Z]\b^cbab`ffgade`bbdbcagfbcdkgifigjihjefbWYd����ƴ�������ztjqedjniokle`clnkplqurtsps{xuolx}{�~ysmjw�������������������{{~�������������������������������������������������������������������������������������������������������Ļ���������������������������������������ƽ������ƹ���¹����������������������������������������������������������K%$,,)(2-'-127G7?8/23)()40-+-1728B?ENIXlx�������������������������������������������������������ddaedecghaeaaae_leccb_eghntu��������������������������������~uqbXRLMPLSOXY]Z]_aaY^ecgdgg``dadbd__deg_^fbaadjflsgkgea^^Zl�������������wpmndfjsrmhnbdhhlpipqrtu{ytrwsp{wz}�|zukjfv������������������ywv��������������������������������������������������������������������������ź�����������������������������������������������������������������������������¸��������������������������������������������������������������۩4(,%+0*,471,,29216/5.'.),73;3/;;=B<AJT\p~�������������������������������������������������������ccd_`cfbji^dg^e`geadcggdflvr�������������������������������xqtdVWNIOLOPSY\]\`___`^c`bikfhbdba^fb`bdbfd_ccbjkjgdfgeba\]t����ʶ�������r{{ojvolmficfifnmlpllot{}xwu|��~v}��~xnj`o������������������{wv�������������������������������������������������������������������������������������������������������¿�����������������������������������������������º���������������������������������������������ƽ�����������������Ռ'$$'***250---715/.0+)+++/402<166128>H\hv��������������������������������������������������������jjd`ecbdc_X_b_h_eadffgceiknuz�������������������������������{rs`[SRJGKSOTW[Z`b[]^c_^bebd^ddaa`ecdcab`j_hcgdkmkhieega[Z`v����Ǭ������~}�|o{�tknibhrccknjulpruqqls|z�wyz~�{znfs������������������{x{����������������������������������������������������������������������������������������������������¼������������������������������������������������ó�����������������������������������������������Ž�������������������i)(&$2+..50.,454/.,.*0'>10078>73:.6:PNiu���������������������������������������������������������jjg`_b`eadceaabaaaaac`cejeqq|~������������������������������uocYQJGMKNLW[\WZ_bc]ffd_^dd_ed^bcdebc__h`feaeempkgjefka]X^{���ͻ�ø�������xx��xslpokmghnkkhor{nhcjrzyttzz�zztip������������������z�������������������������������������������������������������������������������������������������������¾���������������������������������������������þ��������������������Ƚ���������������������������˺������������������ڶB)% &,/0)+1.2-13716-').-,,4:756+4(/<Q\n|���������������������������������������������������������ffb`b_biffaf^`ba`a^`af`cekrt|�������������������������������{sogZQNIJLRVTV^Yb[_a`df_ecd`]acaebg_bed_\dffgffjgnggcgie\[_~���Ȳ�����������{~zrtqsyghknpagokmmaTguvzqp}|�yrsskw������������}�����w{����������������������������������������������������������������������������������������������������������������������������������������������������̿��������������������������������������������������;�������������������֓6/#%+--)6..<5/78;624,1/,/+94=85.*'4;Kaw����������������������������������������������������������__b]^bbf`ed`a`ca`dafbfa[cirpw��������������������������������vrc\VONLQSTVX_\_[`_`abddcdaaacebg_g_ddhbbdciijfgfjjjdd`[Z\�����������������tu�~xpvthgmogeoomfc`gosu�qs{~wttnjs������������������xpr���������������������������������������������������������������������������������������������������������������������������������������������������������ü�������������������������������������������������������������������m3/#&,)(*(*003143?H8,*,1.36;0=28++%0@Wq�����������������������������������������������������������cc_`cc_g`mjcaa`bc`e`[aaaadir~��������������������������������xtcYPLNJLONUX\[c`ba_`cddaee`cbcgcac_d`facdbdgjfchfkeehc_[`�����±����������uy��{umjgdhhghxqhinqqjrw}swqljqohz������������������ulu��������������������������������������������������������������������������������������������������������������������������������������������������¹����������������������������������������������������ƶ�������������������غ>-**&**./-1-4421:A:2&+/7,2358=841*)6Hay�����������������������������������������������������������__ccgeac\c]`aa\fe_gc]_^fcfqsz�������������������������������~ysa\VLLMPSVY\Y]^^[^`aecdbehd```fecca`cc]ccagjigihkkgjd`_W_����ʲ�����������|����zijsdelihllekutlfq���se`efny�����������������zkqv�������������������������������������������������������������������������������������������������������������������������������������������������ľ�����������������������������������������������������ʸ��������������������ӕ*.-%)/,,-/1921,/61.53+..2-00205410->Rm������������������������������������������������������������__fech^b`adbcbbee_ibbb_adgrt{~������������������������������}vrd[VSROQTU`]\^^^_[d]ffgefdaf_`ebegaagecebbihigejiicecb^Z^��������������������~�vipninohdccdutrlow~slfbedq������������������sn|������������������������������������������������������������������������������������������������������������������������������������������������ɿ������������������������������������������������������ͽ�����������­���������](&)*4*1-,4.171-02/1++-1//.0+1038:2>Idv������������������������������������������������������������cc`aaaade_dj`a`ba^f_^cbbjhmt��������������������������������tlbUXNQLNQXZZa_abb_bdbchef`ge``c`fccc`cdaecdfbkcagghdcbYZY���˴Ķ��������������zuortnqnaSUimqhgmw~xvrijfgr�����������������psvu����������������������������������������������������������������������������������������������������������������������������������������������ѿ�����»�������������������������������������������������Ǵ��������������������Ӣ>(-*(<2767..61855:/-,*&+2-.-+/3:;IBEXr�������������������������������������������������������������``c`c]`e]b\\__bb]cbb^b_afhou|��������������������������������vn_WQPNMMRUYXa\`ac[abdbdkdec]_fdccdaace`cgebffigghfcgfdXZ]����ĸ����������������~qzvtobWS]rllaixywxuxng_s��������|��������rhmxx����������������������������������������������������������������������������������������������������������������������������������������������Ľ���������������������»���������������������������������л����������������������s-,'+,1@9//7/37@202+1))//40)()-3CLQOTiy�������������������������������������������������������������^^b^\`ega]`c_a^e`c\^\bfcgeiw~��������������������������������vkfZQUKOMTRYYb_^`_]bdcea_`acc_cd`ebfacabcjfdbfgfjdhhbf^`\^����¬õ���������������~}ypi[Xaia_gds|wtouse`x�����������������uooq��������������������������������������������������������������������������������������������������������������������������������������������������������������������������¾������������������������������Ʃ�������������������չ?.3-#'<8E-3/3/820.1(3))017-,2/2:@FOOgt��������������������������������������������������������������eece`a^j[^c_d`a^^`d``eh`bdkv~��������������������������������umaYYNQOOLPZU]_aaeahiidf_^edddaceccdabeaddffghcilc_edc^ZT\���Ʋ�İ����������������{xhfdem`WPapspnqpqhkt������������������nrw}��������������������������������������������������������������������������������������������������������������������������������������������ż������������������������¾�½������������������������������ѳ�����������~���������ґ/&&/'')/=42J<513,.++*-2/27+,0.:=LUV`q}��������������������������������������������������������������aa]db]a\\_a\[]a`ad_]beafahpv�������������������������������uldXWKLNNLUY[^`\[d`_bm`edcc_bccbcaeac^badcdeibddjiad`d_XV`��Ϲ�������������������~xpkhdia]T^ispjoqj_dw�����������������nvvqy�������������������������������������������������������������������������������������������������������������������������������������������ɹ���������������������Ž����ſ��������������������������������Ǥ����������||����������X%%(%&))*400I@;6-,*')3-263/,/328BJP[l|���������������������������������������������������������������bbb^[[`]__Xa\^aZX_b^\_bbceoy��������������������������������~wjg[YMKMRNQSX^[^_d_c`daafbdba_j`]beccb`b``ffgiffhf`da`]UXe����¹������������z����}vmclgd[]_qghjjlk\Zu�����������������zcw~{���������������������z���������������������������������������������������������������������������������������������������������������������dz���������������������ù�����ÿü�����������������������������б����������}����������۸=&*&)&,)+418G860..&++./7515-,,5??FTaq����������������������������������������������������������������]]dh`Y__a`_bb``a`a_``h_`ejsy���������������������������������umb^QINPNMSV^^]`^d`_adhdhdefb^]`bcc_fdf_bechhdfkb_ac__ZYVb���Ⱦ�������������������zikkgbdlknlgrlg^an���������|������vjvstv����������������������w������������������������������������������������������������������������������������������������������������������Ϳ���������������������������������������������������������������������������~�����������֛.$$')'&*.2253/705.),10;1/23,.0<CFIZm|����������������������������������������������������������������``mja_g_]_be`b][_]b_^[aeckrv��������������������������������vmfZUNNJQTTY\`b]`c`ecad^a_cd`]^`_dbab`bfddcjie]b_f`d\ZXUQi��������������������y���sjttdalimlmomgmgt����������yz����}mw�}v|�������������������v��������������������������������������������������������������������������������������������������������������������Ʒ����������������������������������������������������������������ϩ�����������������������m&'&+(/)*002/3510&-&*./5940.-148DPOb{�����������������������������������������������������������������aa`ed\\]\abba\^\`]`bf^aa`ntu��������������������������������vlf\XPLNQTSUV_^]ce\bcdccdbe_b``fe_`bacggkjcfhedj_ea_^\Y\Vt��ŵ���������������{{��|twqxmknfigrnd]t������������~�~��au��{��������������������}�������������������������������������������������������������������������������������������������������������������ſ������������������������þ���������������������������������������������������������������ܶ>&%.&+*0)205.146F*'+.+.365/-,65DGFap������������������������������������������������������������������^^^bc^]`_^^_Zf^^\Z[`\^addgnu���������������������������������ylcaXSMMUSU\]Y]]^`hbc]c_c^c_e^adadfdaadegh`cgecfed`_]]ZTS}�������������������y�����|svtoochggd_a~�����������������lj{�x������������������v�������������������������������������������������������������������������������������������������������������������õ��������������������¿��ļ����������������������������������������ͤ����������������������ד/').1,4,10//84/+=A**+/272/5502<BFK`y������������������������������������������������������������������``^hi\[^\^^cc`c^a\a_[aebinr{���������������������������������xmgZTRHLUQS[]\a[cdacdcdf`bce]`dgc`h__bcb`dbcaaedfff_[[URWz����Į�������������������zu�zsliokc_dw��}�������������xjnvwzy�����������������u�~�����������|������������������������������������������������������������������������������������������������������ȿ�������������������������ÿ����������������������������������������ϵ������������������������`++(&*18)32105+1+-059144;91,205G;FSm�������������������������������������������������������������������ccb`ec`cY[_^_\a`][_`\aicjnu~���������������������������������xog^OQHFOPWZZY\[^c`ag_db^``cacb_b`^_^\bbacbaf_acdg]aY]UQU����ȶ�������������������zx{�ommjkaYcn���{������������rmr|zv|�����������������~p~�����������������������������������������������������������������������������������������������������������������Ǿ���������������������������������������������������������������������Ğ����������������������߮7+(%+(+0.2360.3@6**2G57:474/34CCEPdz�������������������������������������������������������������������__a`gace`ba_h_``c^e_decdhpty���������������������������������|tmdSNLGUMTY\[[^\a`_`fa`a_`bh^^dbcbcbbcf_cecddejfe]^Z[URY���ɽ��ñ���������������}�|xjinjb\\y�����v~����}����zjszxvy�����������������lsz��������������������������������������������{�������������������������������������������������������������������Ƿ��������������ǿ�����������������ſ����������������������������������ϫ��������������yt~�������|'$()-+0.575433/::/54FE>65=-88.2;HUm��������������������������������������������������������������������^^]^b]cbgea]^]b^bba_ecgcflux~��������������������������������|rccUKJLQKSUUZ]a^_\]^fa`_ab\_]]```gefddbbb\^bcg]c`][]WSPV������˸��Ȯ����������������vlkkcZXj������zz���~����}ov�x{����������������y}xy�����������}�������������������������������}{u}qiYY]n���������������������������������������������������������¾���������½�����������������������ÿ�ž����������������������������������Ǚ������������mglqx�������Q%$%)*,2,197834>6</673CD9;102560>Har��������������������������������������������������������������������__`ab^cbc`e_a^_^bbbbhhllmmzx���������������������������������k][RKILINMSU]^c\b\a[`dbaac_b[^faeccdaahbcb`bb`eb_]__TPOS�����ͽ��κ�����������������x�mc[Udy�������{z������qhu��zx����������������yx�����������zu������������������������������{�����tkaJF���������������������������������������������������������̿���������Ż�����Ļ������������������������������������������������������Ы����������xoeU`lv�����۪6"')#%-.166<>1.29/2/.9IB5922.16??Xj��������������������������������������������������������������������bb`cb`dee`c``^_`bdgcdgkhhrsz���������������������������������wm]\RQKHHLXVZ[[\`de_a`ffc___[^^eadaa\^a`eaeceddab_a\WUPNX����θ���á�������������������qbZ]s��{������y|�����fo�w���������������{vy���������������������������tmfkinruw���������y������{kX;}��������������������������������������������������������ŭ������ü��������������������������������������������������������������������������x_^hd_^o��������y)* !%'..6/4,104/00-.0<><525AG8;@Da|���������������������������������������������������������������������ff_cbb^``_d_dd_adabdflkimnry���������������������������������xnb[UOIIHSMSWY[cYfdbb_`acb`^Z\\cbc`d_ac^bbbhieejb``\VTTOU����½�ʾ��������������������}gaegw�������|~���zhiw�t����������������no~�����������}z������������qb\dljoih[Z][iqv����rw�������{iNo�����������������������������������bz��������������������������ý��������¿������������������������������������������������������ɣ�������|fRQRW]]f������޻D&!! #%,,--,07*.5-0--47<8337454=LTm����������������������������������������������������������������������cc]bedbc\_cdedeb`ecdkjhhkmtz~��������������������������������xk]\SKEIKQRUT[YZZc`ed_]a__^__`df_`b_efdbb_bcbccc_^a]ZTMLP�������ů�û�����������������pcupqy��|}x�}������chz~y{����������������s{|z�����������������������|lTdxy~�}umlnaU^^el��`s��������~g\n������������������������������xkdS8?{�����������������������������������������������ý�����������������������������������������̯�������eWQRQUeddo�������ؘ)"""#%$.,/2264,)(002729:52.191<7I_w����������������������������������������������������������������������aaef`bef_cddc^ccbbecfhjkjpus~��������������������������������|ndZWRHEIINXZY^Zbcgad_aaea``e_da^gb^_bba`cceae^a\b]_^XQPQ������÷�о������������������{xw�yw~�x|�{z�����{^j�|t��������������~vy��{��������z������������v\[^w������vuvwnagYNcpdV����������~qfca`hp|�������������vlj��������v�~wV58N������������Ʊ��������������������������������������������������������������������������Ҵ������vWOJVS\Xblq}��������[&'$'%%).-54+/13+---4:177403227=@Ph����������������������������������������������������������������������ddeacbbc__`ecc`chcagejjhkquy���������������������������������yqcZOOEDHOPZZY[Zab]eaad`e`gbh`d_cfffdad^bdhcfeb`_a__\TNMT�����´��ɭ�������������������nr{}vp}zx��z���bllw~���������������pmq~�����������}z�����������x\Xn��������xxywrrmSKLPN������������~squrl`[ap�����������hh��wr���ep��lH.3Y���������Ƕ����������������Ŀ����������ÿ���������������������������������������������Ӻ�����z_NKPWWb[`hrz�������ԏ/" &")''0,7-/72-,4,01436>>=1789@M^s�����������������������������������������������������������������������ccbbaabgceba^aecha^bdddjlpu|���������������������������������{oe[PKDLOOVSTVXY]^babhaa]aee]d]d`fbdcgfbfccdcdaebd\XXTMOP����ȷ��˴�¼�����������������wvqw�vvzoy�}}���reyvvv��������������|�tn~�����������y�����������kgw������|�~|yximiog]SM9T�����������y��wor|v~sidXiy��������ngh\CQbZ?@p~q`3#/{�������Ŵ���������������������������������������������������������������������������̽�����mVLTYW[Zjaanw�������ݯB(!'&/=*-.1/-/32-++(/776=794/-59JVh{�����������������������������������������������������������������������ccda`acccgeb_cbbhdacciejtow{���������������������������������xqc[PMEEOKRQST]Zab__h_]_ccecfd_cfff_`hce`agfdcbe]`YZVVNQQ�������ƻ��Ƶ�����������������yxps}ytspt{{���ikm{xu��������������wpu}w�~�����������~�����������zr~������yqpojlh]^YWY[bK:F~���������q���������tiTFBES]ohbrgVaa_WX317AF14T^F+"-Y�����Ǿ���������ƿ��������������������Ŀ�������������������������������������������������iXYPMT[cW\__fz���������i)-+#$*.0/04.-/7.**+*,5363/4-0026Fdw������������������������������������������������������������������������ccdbgabab`fl]cdklffighhjqs|���������������������������������tnbWTKHJJPNTVW]b\[\_^`cc_kefid^_filccfbccabfbdcgcb^XYVRRU}�����ʶ��˼���������x��������omqgi|utry���r_ft~|���������������lrz�������������{������������ws�������rgdefkbRJE>;?ID2@y���������x��|��{{una`[TQXv`QEHRRQYCHCP</+565).@3&$+H{���ų����������������������������������¾���������������������������������������Ǵ����qbSQWRUWX\X`efn��������Ϙ2&%!%%%130.45)-7+))**..67760/,/5NWi~������������������������������������������������������������������������bbgddcgaa_fhba`cfaighjmqpv|~���������������������������������|ogaTKOFELOVTT[_[f^`^[d_agdfcd^`d`e_bbccfaeccgd`a]][`VOPO~����ͺ��κ��Ŷ����{����~����utfmrnw�}xx�nYkpwqy�������������xptx}����������{������������m\x�����zk\ZglcmXPOTPKF:?HHy�����������}qeWSaeT@<QQ_uoSABLA>?=F7:E5,)2--/+'&'+*I���Ȱ�������������������þ������������ÿ���������������������������������������Ʋ����k\\XTPWUXVZ_Xbnr��������׹P((*$,(0-26.30,17*,0200:4?21*),32Lcv�������������������������������������������������������������������������ffgccdfdgbfb`gaedbjimhjjiyw}���������������������������������}of[SJKFKOPVQR^b^[_eb^_bbaeccg``ggd``c\d_bcbhbcc_]b_][VSLo���ѿ��ι��ʿ�����|��{q����vimjjotq}�w~�wo]`tzxw�������������wr~�}�~�������{z}�����������vdx�����qh\bdhnebXW_imbTIXZ`}�|��������~oME?JCHE>9Mbz�d8:BZ@A835167,)-.)*.'&$#+Rw������������������������������������½���������������������������������������ǭ��~le\Y[ZXUWXXZ^Y^Zcu���������Ѓ,,(,&(.1*/2121--3',6;74559-,,*(17Ln~�������������������������������������������������������������������������cc_bblhgeebacc`bgcehkmmrmtt}���������������������������������zsfTSQOBKLRTPU_a^]`__d_eb`lg`c]ahfjb`acddabeebfd_db`_XVRNc������̾���Ű�������|l����|vjenqmqtt{}�l\ajwxx�������������xw������~������wt����������yjf{������~qX`rvwxdY]quwzng`h^g�hpu{���}gYWNLH<36<HRk�}g?<;:_NA6-/,).(&).3+)(-08^��±��������������������ÿ����������������������������������ɿ��������������ȿ��|rc\S[T\_[]SZXS[acfbr���������ԦE&f&.&.,17.74833308++/.99820./$'.?\x��������������������������������������������������������������������������cccgcifhbgcdcgj\`jdcknlqnrw}���������������������������������zseYQKGCJPRTSX[[af[]bgefea_a^ff`dcab`fagff`edcglc`_a^WYUQ]����������̶�ŭ�����m�����ywutoqpnnpx��p\gnnsv�������������ku�������~�������y����������pZl}�����|rijt���upgu���{{lOJGVdj]X^t��u[RKRgH8D86Alx�`D;>?:DZVH,,0($%#%)GH(%3c^m������������������������Ŀ�����������ſ����������������������þ������������ɹ��naY[VWV[^]YX^TX[Vcfoqw���������մY-&1.0%*+2/66-945.-0+).1;65.++7&-8L^|��������������������������������������������������������������������������__fddeihlfcc`c`beidehlonntv|���������������������������������~vdUPGHJLQQTXW^]\\c[_acc__a\bbacgej`cfcabe_ihhecda`[bZWQNY�����½��˹�ξ����uvqx{t{�rvxsrwlqrx�j`qysr{������������vnqz������������}~�����������tatx|����~wehw��iaik��wxtU@SSJe`OK_t}p\PSHUU00FBHm�mB0<JONQ<FV@90)*0& #&(%#%J������������������������¾��¿����������Ŀ����������������������������������Ƴ�v_ZYVZUSYXY[eW[]_^]dhp|����������ǟX-%*+(&+327383-//36<6/+43=891/+%&-9Tj���������������������������������������������������������������������������cccdffinmgecbba^bgmjiihoksz{���������������������������������}q]]OSLIMUSTR^[\ae^aa`ccbae_d_ehdadc_addeddjcaadb_[c^[TQRNk�������ʼ��˴����v}plg{����stxp|qm{xwpgkqxvx�������������nkyz~��������|~}�����������rdn������|}kfr�|gklln��v[dVCEM[NPPDSorp`bkeIPF;MVUlxU=@J_^PLDIJ`27H,)&%$$ !!$.U��������������������������������������������¿����������������������������ˬjaZUYWTYXVXWaa]W\]_aact����������ėc?1%(')&)1038.420428+354392<;5.))&*/@cw���������������������������������������������������������������������������eefggecchagdg`b]adkjomoltty����������������������������������{m`ZQOIEKSMUW]]_`ae`__bedhabh`_cffekaaafebfgb`a_eaa\[[VQORj������˻��ʷ������{qju�����~rxx�ztvtj`itvr~������������rm|x}}|����������vt}�����������kg������qk_r~�zv}�zofeSIANC=696AAEFRbpgZxYb`^^dio?AT\fR984/O]d0/06/&( &0_��Ĵ����������������������ÿ���������������������������������������������ͻ�e\X\^RYZXUWSUW[\`[\`iipr����������€<10-)(&0&-3/13213.+0*.-8/34=5:24,+))2Ur����������������������������������������������������������������������������bbddmfeghghfe\d]`ddoemjnmsy����������������������������������{pf[PNIFOQRSU\d[_^`^^a^b`^f`g_`dfagj`bdjh^geh^fb__c`Y]YQSO`���������ͺ�î����xii�������|o|��omf\dovtv������������|qt|~������������|z����������zcm~������|rii~��|vxxeRO;G:<9>97:9<BEJ_ic\}�bYuphg�lG[o�o8/7>.+8dw:0*-%7,  %;h�����ss����Ļ���������������������������������ÿ�������������������������ɭtg]WZ[cZY^[ZWWVYe`ecrjlx�����������Ɓ7),*'(+*/2/464022-,+06**88379=791-+03C[r����������������������������������������������������������������������������ggeiagjhggbgb``]`felhjkmtrt����������������������������������}ka^OJKKMSQLTY_\d\a]acfgg`beb`^hcfhad_`_fcdbbc_d`^]\\^WSOOV��������˸��ģ����ykv��������q|{qqk]o{p}����������wq{~�{��������||z{���������usnao�������zlct�wunahbRD::A82=98<799:J]mf\|�hOimXLfzgE[v�|>78OD<@Jg~6&"$*$+0=w�����tk�����Ľ����������Ŀ���ÿ��������������������¿���������������������a]]\_^b]\Z\ZVR]Z\cks{�������������џ5&*+**.3+-.0416/4,-/011',.-328<770.-38Qk�����������������������������������������������������������������������������iijkjgkgigedbcdbbcbmijmmotv����������������������������������na[UPJLPKMTSV]^`\_\Zccedbcb`dbccbmc`a^bfddcdb]^^`[bc`]TRSRx��ɺ��Ͼ��ӹ����y�{������x��}~rjefhmxs������������vmr|�{}���������|zy����������wbc|}�����~}f`ntc_PMNLFGONF@269@@B:@DWml[z�mSdaO7Llf[Cv�vf3FIOU:-3px9%!$!"$,GWv�¹��qnw�������������������������¼������û�¿�������������������������ź��}yoZ^]\^]\ZZ\XX\[[gux��������������ӴU,$))2/*,,,.66/578.+010+/1231;B9:;754<C^s�����������������������������������������������������������������������������lljffhfffgbda^`cc_bignolhpw~���������������������������������q^^SSRJISOVV^Z^^Z`af\`_`ab]bc`bdaffd\`b`bjdi`ec_d^ca\_ePRQp�����Ϳ����º������������z����zh]_qpsn{�����������~pq~��w}��������{y����������mW{��~�����sde`^H=><K]OMNOB=;7;=:4:EWj�c^�sRZX>85?[`Q\�^[KK^caO1&-y{(%"! %@Y�����}ts}�����Ľ�������������������������������������������������������Ĺ�h~���~daa^f`VXXW[^afn|���������������кc.*02101.5113544033/.-))*.2:=?>A@M4-/14Jiz�����������������������������������������������������������������������������kkikkpfeghc_fbe_ddegckilln|���������������������������������zndXYJEHGLUQVfY\]aab^_db^cb]`d`fjfedcb^`fdjea^_aeebfb`_]SKO^��������ͺ�̺�����������������wb^fquow������������tq{�~~}�����~x}|u����������~jH������~�xcaPLV?:<IGdaRSZE46/.39/3?Jj�t[sz]eL5.3<4HYglPKOP^kOA6"//tj$##!)]������qs������ý����������������������������������¿���������������������y[Uw���vhcbc`V]Y_hru|����������������Ϋ`3()+/-4-/-/62464;021*+1*+++.3133.;HO/3DTt������������������������������������������������������������������������������ggijgogihld_ddefgebgeelilny���������������������������������|qd^VTGENIOZR[\\`_^cZ_d`_bc`e`cdfeagafca`]fbecdbb`ccd_YXVMMS�������˶��ħ����|y���������{q^mvqsl|��������}}you�|}�{�����}yuty������������gN{�����vhW^TM;1AJUbjh\E>7;313564,:J`��^j�f`K1-)2//ZqvB8NZldY=6;#).~G+(#3[�����}xy�������·����������������������������������������������������ü�nigb^s���}nc^`gaemv�������������������ͮT20('*2.2,8.4:>;53:=.*/)./,,-5=CH<4<:2<<Rh�������������������������������������������������������������������������������jjkhkljgighejdibibfdfgkiorw}���������������������������������~pkZVNMLKOVSSV\U^Z`a]\aad`eh_Xd^de`ja^_hcbblecccddadba^ZYQMMp�����ͺ��а�ñ���qv��������tmaZnvxw}����������uaowz���x�~�����}xsu�������������lW����}ocYRR<548J`oq\BAB5759,.9;3)9d}�tr�ueL*+*,2-Bx�U9>Qiz^;*&,##I}@U/#:h�����|{����Ž�¿����������������������������������������������������ɽ��YKblnbx������onq{y}��������������������ϨR--(+--,0.-.7/852178;0140+')-049<CK871639Xp�������������������������������������������������������������������������������nniejljidhgjkji^ebh`bigjprx}���������������������������������~thYVNGLJMPSVTZZa[^\_]a]dg]_cZgbfaaaefadd`fgffcigfbgbc]\ZVOKc����ɼ��ʺ��������q����z���tkjcjvt�����������vop~y~��}{���|w{{�������������oK{��}db]PD795:JpsbM311074580.7<2.Muv|sye^Q.09*&-@q�\?FY_f_M,+#'$+`{^h,'Cr�����z�����������������������������������������������������������������iRHNfnmhu�������������������������������ͯV++(-1()4.235B95871672.-6/1)**+4@:5520731Bf|�������������������������������������������������������������������������������nnjecifeljihiee^dfebfkfiorw��������������������������������{me\TNFJIKOTURUX^]acdab`ai``geacbaaaaecda`a`aadbdddegdb][TTNP���Ͻ��̶��˴������{����y��ziokrt{����������qdk{|�w������vu~�}qx���������������tSu��pZTG=859GfnpQ830/.+2:<6*136+.]xkzkVM.018.*Ao�jQ=KVX]P1#!00&'mkAk3Hy�����xu���������������������������������������������������������������TCi_QN\pllkz�����������������������������Եa/&')-&-/323;78B66<4120+24027.337<1..(,465Zm|�������������������������������������������������������������������������������mmlgdphekfahgfg_ce`fdehjppoz����������������������������������riZWOHILJTRVX\^`[`__`ba]ddj^cgbdfdhd^edb^d]^`a`fefchbcaYQPOUl�����ȷ��ͻ��������y���w~xkfqupq|��������sgasu�|�~z�����zuzxwhm��������������y_k�yVC;;=8=KhoR99011.3,7?.*,000/<dT`d]443766Ai�yYH=Na_G/%!*1,$2�T,IZ}�����}z�������ļ��������������������������������������������������Ⱥ�`73B[hdYXcme]q������������������������������s4$&)%-//1-685=68243,160,07*2515/5:6.)+.21Edw��������������������������������������������������������������������������������oojliihfiekkjfbceiemhdjjlms{}��������������������������������}ofYRNDFNLWXXV[^^aca[a_`bbeadccbgecgdae]b`b`de^acdhchchaYVRQPa����˺��Ѿ��ɿ����������td_iqz{}��������{vgccvu~�~�}~���~~yrot�z~taXZky�������sYVr_D?A:>9ShfO4373*)-6:D6,%&4904ct�d?PVC.,,2:Fl��g[JMZi@%&$0J, -5�H0c�����yt��������ž����������������������������������������������������\\D./:izup``xk`h���������������������������Ҽv8.(+,%*),-413718=7.27<71-0.,151236412(/>12Ph��������������������������������������������������������������������������������kkkojihhjhleil_feaageejmktr���������������������������������~rm[ZTEFMLRYXX[_W[`]ad\[_^dedbeehdbfbebcgchdac_hfeadedd^\^TSRY���м��Ӿ���Ū����������h]glz~�����������j`crx}y}z��xyzz��|xwu����}upbZNSu�����oZVX?4GSB@RbUD96AA1-..=EF1+#,4:/Gv}zM3LI220.8Jn�th[^hfX'"$0bR G�M_������v������������������������������������������������¾�����������zA7Pa>3Ab�~vdeqyib��������������������������ѻq.)%'('%,/246/55289=78<790)-*.-).4;89>62-948Xp���������������������������������������������������������������������������������jjikngjghlkeidbhdifibegjipy���������������������������������|riZ[KFHQKSYTY^\\^`Yb^]e^ea_f^`_fa_e^_c\aefc`edgdfeeccjc]Y\RNU�������Ŷ��ð�����������n_fu�}���������xfqxvz{~����xxu~�~|ws{�������xndQKXxy��vZU@:=@OWVSMAA=A77:.0>ON/&#$(.7Hflt];;=7,2418c{qNM\zwp\3"&)`wI!]�r�����zy|��������ǿ��������������������������������������������������Z02>Xg\?AW���tftywdw��������������������������}-'((%**-0,0020790297245631-,..02118304,4/55Jew���������������������������������������������������������������������������������lljmjikhffhheddhaiajgcegkmsz����������������������������������wiZWMGJJJQYYZ__\_`^b^fb\ac`aaadeh__^_]_d`bfeacfidjlkgfae][XQUh�����Ⱦ��Ƴ�����������gbfo�~zy}������|km{��}|�}~�yvwy{�}xsx���������{kkWUPdolP;:B@BEKVIDO>99<;39=QP7.(*''46_eOmF+0;7E94>exdJ?^x~teC*+,V�v" 1z�����{wuy����Ŀ�������������������������������������������������þ���E-#*G_ro[=Gx��yijw~ej�����������������������ͼ�;&%+9(,/3/1406554;565017335-++.8,437:02:4<6>Xj����������������������������������������������������������������������������������ggihgkikhihhhddegceedclbempt���������������������������������td]QHAKBOQST]V[X^[^^`_a_]]\_]_eiic`^b`_\d^aa^gjijklkgcgda^_WYWw�������̹�����������ibYat}��}xw}���yvf`{|�~z��txzqp{}zv}{���������oih_ro[ONHRNJIGC@JU^SPM?>?702=\cJ,'$&'+<=eHas=.6;69<6M�bJBSow^SE,&2L}�Q!)G�����znwz�������þ���������������������������������»������¼��������X70..9_lrgL<`���pi{�to���������������������Ϳ�a9-%&(*)*/.104533255843:4>6,/,.-+4*654232..73Hap����������������������������������������������������������������������������������jjkjjhihmhhfdcdbjddcclfjilqz����������������������������������ukYUNGCGGOQSX]ZZ][^ac_^\cabf_a`dbbe^aacbebc_bcddffmgekff`c[UYT_������μľ����������lYXg�����yz��}tick~�z��z{�zxzxsyzsx����������oV=7J]]GEDP[WTEDMbhQG>E?>-*39]xb-+&$&'(HNn<bY-.+-,++4@`SJCTU`^R>'&M��}*.p����tt�������Ŀ����������������������������������������������¶��qVMGF927HjlrlRFc���jt�zoj|������������������ɸ~;2**5#%'**,.046864446;;;=4830451-,.23307/1399<Udx����������������������������������������������������������������������������������kknjilqlmfihhcedjacdhef_bpsx����������������������������������wf\SJADKIXUWWYYYX]_][Z`bb[_ba^]ba_`dh`__`dabbegkiggmklekfd^[WTY�������н����������t_bi�����{|�|tlou��{~�{~{|zxx|{|~x���������xrcN824=C<NSTS@FMWWbWHB>B>+$(-TrkA))((,*/RXm5^E*)&/-7;<W\PE2>Idh;1'.d��l" *H���q{yw�������������������������������������������������������������qZRHP\V>ESgotf_Pt��{m}�}ct�����������������̬f4&*-'% $*0-,.324458@<64EC65A51/51,003717:4212AEWl|����������������������������������������������������������������������������������uuknionemjkknhcdabbcdcfebnsv�~��������������������������������wg\NNKDILOWUT]__d``^\haa`c^ba``_Z^bcjd_badibbgekdhfgmhhdegb\XUW_��������¶���������kdm{�������}xunkqzx~�����{yzyvy~s|����yvmj\fdi[UNG??CVHJFAAaZNHD==>5.*,2<`s6*%%-&+3T`a0e8+//4>PK>?B2.-7Wi\*(%6|��9#*Fj��z_nx����ž���������������������������������������������������������w]LI\h_Q>GiegecK��oo�wlg����������������Ƙ^3()*)/6)(,-.2411//24;7>98E520.+5*-),)034722/2ABLXp�����������������������������������������������������������������������������������ggmmnmphtjomijgc`bccedfbdjtv���������������������������������}ucWWMKKFMPSRTY\Z]`\]^beedg_accbaa^a^i\a]dccd`gfffkilniffebbb^UTVl������ʿ����������tg�������|}xkkuv�����~�}y}�{yw}|����yfhhijvukioZXTSTMC<>BVcZI;A//4-,)-@_q�k*""%+**9Qbf0^/-+>;:85;35-/'=dtN'##A��m%A[e�}utag������������¿���������������������������������������������¿����fQKJXnlRLY_\_aX[��|ruwhd{�������������ο�J4*++6)1&,'--./36314.:965@6904*,/7.*,/+5262915CECRgw����������������������������������������������������������������������������������kkjihlmpjjiekchedabba^\cainw���������������������������������|ufVQJJIKOUUYOUW[[]]^`_^cbbccf^_aacfbbb`_^cebeggljhhkiflniffdc[YSW������Ȼ�ĺ�������kx�~||�����~urnpz{~������}~yv~zps����zww|w|ywrrdfieY\UB:@FQ[ZO<5/+)&'#/DAXn�i-**$*0.3Wd^2g/).8<902;;6502=mwB-",K��ZCp|�Rcqbo��Ľ�������¾�����������������������������������������������¾���x_TLEJpucJSdaYeYp��{u}lf~������������÷�@+,(*+.+*/%+11458;6722:67:?5812--()01/,/9;7>239HGDYty�����������������������������������������������������������������������������������nnmjljfnhdjgifffcedd\c_ccfns{��������������������������������wiYQIFIHMOTUWU[[\]ZXecb_caa`c_a`dddc`_^`beg`gidihgjlihihhef`]_[TTc�����ɽ��ȹ�����i]���uu|������tvt{|������}ztztmp����~�}�zuyu^_dcZNK?JFXb^^U>;,-'&)(,ECgr�N*&/*00)0WL[<X8'+-<;2+0:5*(&>opC*%5p�}en���|BXor��Ĺ������������������������������������������������������ÿÿ�����o]\P<Dl|j[hgZ`xf��}x}zsy����������ʽ�qD/-.'%-+-0)+25/787<;5423=3776;322//,6.,,419:1:4;EIQdt����~|xz����������������������������������������������������������������������������nnnmmllmigfhghgehecg`c_c`ekqy���������������������������������uiXQJKDJLPMPWWX\\_Z^cbb^cbbb^a`cebddgebcd\iefjihjknlijhokkieaa`ZPYs���������ķ���wXh���ttxy��{youv|z{���|z����~����|yyo{����{iQGJMVXNFLIJSSg]ifB:32.++(&)1Gj{|@'$&%69ABH@=@L;3/FL=;227=...MpXJ1+M�iy����lGh~������¿���¾��������������������������������������������������¹���zf\_YGEo�vpimfok}��z�{y���������Ǭ|Y6--,1.*++/.+,1359957323/493;83790-,/00+-28699/-8<;J\mx�����|{�����������������������������������������������������������������������������llkknkiljfijigfcabdeb^_b_inry��������������������������������|qj[SLGGJLSSS\TWX[[[`cbd]]\^_`Za`dfa`eddigfdddghejjllkkpnkomcgf]VWU\�������Ľ��ǽ�ph���}tpu~~z|xjv��}���~zy��zsx�|}~�rqf^s���wpfWE>D]YIAQXS_Za`hQE631.2,*$.8Rxlr6"$(+2\b+;5;:679?<NW[RTQXN80\xUGF2`|x\z�~��kTx������������¿��������������������������������������������������������o`YY]KI~�skkb]\\������{����������h;24)1.,./-++)).74=3:;948/28443:711+0*+/2//2367626;>BIau������w{�����������������������������������������������������������������������������lljllmkmdiigefddbbhc`b__\giny���������������������������������xeYYLKGGFOOTRU]V^b]\g`baae`c_cdaa``^badfbadffjjhejknkqponjlifd][XYRt�������ý����mv���zqvpvzrolnx�������v{zuomovx���yzxunpkedZ\QH>GOKGS[XNZdcdZ@C96:96*'11<Yn`n@'.0B6V[*/21146?=?O\Xb^^bZRN`zZPNLE|tU`i{�|kv�����������������������������������������������������½����������ź����|g[YZRBKx�kM\ES?i�����~���������YA41,())+/..4/+)-44988B9976@:96:955:.)'*+4-.73=4/16CICRlx����|~w������������������������������������������������������������������������������kkklkpmhhifdkhjfegd]`^^_]afo|���������������������������������sdYPLEBEKOMUT]XWZ]^_^a^a_^ba^abdaecb``cdbaackilhlikunlrljlmgl`e_ZYVb�������¿��Ù~���~|xstuvpcemq|�}����upxskfp{|��������~ommZB?;BPTLDJX]HM`jaeHBE7?4B61**7BQUIfG*.79BkF*-3575.30B8;?IB;5E9<Ui:JM@>okTVc��zl�������������������������������������������������������������������������qcXWXO;?f�ZSUSG@��������������mR6)+,,&*.+)032320/1994:2877:7=9:<90,**+/1.225246++2>@MZm~���|}�~�����������������������������������������������������������������������������mmmnpkmlghhhfififeacba]]^^js|��������������������������������tiaRMAFKGQVUTUZ]X[Z\c^_\db_a\``]_bdbceb^dbebgihfnjllkprpnokklhf`]YU[����������������}yzzxtvrockux|��zwnllrkq����|��sx���|qhVD@@FM?><GRPDI]dU]GFI=97403.-=CIURcP3?GGFH-+/.00213290,18:=*-+.C_7LK@DldE_{��w|�������������������������������������������������������������������������zh^SRRD/6~USSZA[�����������{rqY9))%)).4,)/,+/1514487;><57==686894/-'*41052;10627==IQdy����||~������������������������������������������������������������������������������llkjllfjhklgeedhc``bb\\^\cjmw���������������������������������wm[UNFEHIMPQLSX\ZX`b]`c_c]a__d__]a^bbgebbddehfhhnlhommtmpjkcjbcd__VZ���������������||u~�xwgeips{�}��~rrlks|�����~yy]\|���tkXOHATG<:5;GH@BY[bZIJE86/0-1-:AEAF@_`BXNC1+*/6.1..../1151/0,(%$+:V<AL[L]Z7Rztxu����������������������������������������������������ÿ���������������������pb[KAP>+<yzVbWE@{����������}vk[:'$**---%,,/+36/767;9:<:57478=683/*/&(,02::6810/9BALan�����{xw�������������������������������������������������������������������������������iiqpojkghjlifg`fhf`fa\[`Z]fqx���������������������������������wlaRICAIIROYXS\ZVW]_e`aeb``a^ae__\^b_ab`cbeedeigjkilrkssyjwkojgc_VX]����������˽����x{~||r`^gts{�|�{uvt}sp~�������}q]Ny��}xrX@?B>HF<897:8@XaOTPDC=E2/654?DOB4?_f]X_K225..-000.15173.1)12&*)3OFQilSSY8Lgkuy���������������������������������������������������������������������������tfb]JJH8)>nZ]TQ6_����������~riT82)$(,,)(,+0-57;78485:==?886;530.5/.*%)014923200>BCObx�����zwv�������������������������������������������������������������������������������jjjlhijilhekjddfdfdea][ZUbhnt}��������������������������������vm]PLDFKOTJPTT]`^_\bafdfbcgffcf````aadb^cdiefgjjghmnttololpkohhd`VVZ���������ɿ���v{�}z�ykknz{y~ywyqju�|������~��vc[xvtlccUCOG@>;68>..6=WdESEDHMRA7>53:GU;'4fkofXJ('(-/4/2/30/-5<3+-/,-**?^YgxfVV^@\�������������������������������������������������������������������������������yd^fV?<=,%=iV\NCAr����������uhJ431*')('(/0.38=>98656;<B<9?9D@6406*3#(.,./7220-86>GZn����{v�������������������������������������������������������������������������������lljgnigjjghkfefb`fd`b\[XWddn}}��������������������������������viZNMECIMPMOTUY]ZXZ\cdbb`de[bbde`gfaecb_cbeibhjjcgnspsqrommkmmlb`[[V����������»��wqvv}w|wurxu}�zztqtqtx���������~|vo\[|qjYUSIJQML=>;20)*8:HMHNCAEEUQG>;'6LQ8&6q[yx_X2(,+/:/,-00610:/)*,)'),A_l�kXUYaOr�������������������������������������������������������������������������Ƚ�����j\bNQ?80(0WjbJOMg���������v`;.-.&,(&(+,-/-1:8978658<79I;A:41-/3--*+*&..812.575HIbtx���~z}�������������������������������������������������������������������������������nnnhljgkeekigib_db`d`ZY\\dhn|~��������������������������������wj^NJGENKPPXUY]`YX``a\`db^e`bfc_bc`ce]^_^cdgfeimgjlqpsnqqnrmiiefa`ZY|���������û�rnjty�z|rqy|�|~zuhfluz}���������~wjfXOgb]NF;DWZOB34./-.+15=JUQFUDHU`L=8%8KO?(,^Y{�l^5)-/2-12240,*13+/!',&5<So�vVIT]le|�������������������������������������������������������������������������Ǿ�����rbYPLF80-'5lbUHWL����������|]=3,3&,*)*.,3.2.0>967;;:9;3:B897224E./(-(*02931-0/:KWm|�����|w�~�������������������������������������������������������������������������������jjdjfghlkinilfabdbc_]\XY\\iru��������������������������������wm^QNHGAOORXW]^\[]ccbddcbbfdbicgbdacedb`c^addhfjjptmqpqovpmkhkggc]XY|��������̼�viejv|�}ttysv|{uqggfx����������}ym^VCJSD312IfYIA.34**0+/43FaK;EDXU[YE)-7HP6"/;Zv�|oK*+,0.3:1+))),-(*#$$'6\inzkOO_o��}��������������������������������������������������������������������������������ye_QI<7.0+2N_UKTGp��������qQ54,.-+/,.00/1/335<75E268:<<:4;=1-2.+0+*-05836++1.8Sat�������~}��������������������������������������������������������������������������������kklghdmlnjlpdhfeg_ed`[_[X]em}�������������������������������}uk[ROHIKIJYWT_`\^]dcde`cgdficcbcbhafbdjcdcffihigljonttvvrqqnohhob^X[���������ʯ�tebovz|vtxxyz}z}nidqs���������vuv{�v]C55=9.+8N_J64+-31)1/239JbYJ>EGRTa;+/6HVA'(.Gvu~�b9**-/.014+/,.#""$&)7_v|lu\N[w���z�������������������������������������������������������������ſ�����������ƾ����th\SSC/020,6MSOHI]���������`G-:5-.602.40,/14436<>>9<<HBA>?>640+/'32(0-7311(-48:Yjx�����|}���������������������������������������������������������������������������������iiolhhjjgjhiigl``ec`aWY[X\cht��������������������������������}pm]RMHJLFMPVO`[a^\d]bcabb`]ha`aeah_de``dcfgbhkmfhlprttssuqrlrljlb`[[z��������Ѫxcdakqxxoqrwx}{}vnjpw~���������w{zx�vR.'+1;4+<TP=91,+-//5/.+/>X_XB:AUW`M+'/@WP%*,:\h}��\F?6/.*1)*&)#""$(&/_~�zfi`\w����w��������������������������������������������������������������������������������vkZVUA4).,)*DXTQAQ���������Y917;46-,*0,+31/:9:4:86<:=BF<:C963-40-,(/6.4//,+16:C[k�����y����������������������������������������������������������������������������������ggjkfhimfpkfnceaaa`d`[]ZWZbtx~��������������������������������wo`UMMDLOLRUVYZc_`^]dbeghd_hideacbafb`hfb^dekojlgnmootqoorrpqllkcb^]o��������ƌpehgipvssnsqtzusrppv�|�x���wr~wxr]4-&)/<3CXGA300+-1-128/14F\PS;?KNYK=,.:bS%#*71Sr��kh^_]H5%#&*$!%$%!2[���uZSfv�����x���������������������������������������������������������������������������ú����l^TSG2,)/(%6YQL<I���������W5/2,*)0,0./1022276=5A96:@???<><+4.*--,,..720.0//5?Qgv�����������������������������������������������������������������������������������������kkkiknhnfjcffcfeeedbaa^[\cjly��������������������������������~ugbVRJCLKMQSPX_e][cd_caec`dfehhgf`bd_bacjhmfflfjlonlnnpqtqqpmmnngd^_d�������ήymggkigipspuurwnggqz���{{|ne�}uns{�xhW0,&+6?[]6-/,+5***+.01+7CLTPN;?HVUE8(8gS$#-9+;b��cVQdocY3%!*"$"(.P����f]c|������z{��������������������������������������������������������������������������Ⱦ����me\[I3'$01,1PTLAEr�������xJ30../4,)+,3-4102317926:B>9??;47./7-0.(/)216.51:78HXq������������������������������������������������������������������������������������������ddljkngiig`ggcceffed\c[\[cir{~��������������������������������xfcOHHIFSSSSV[][[\a_a]gbfgddebikeb_fbcbcdghghhjhlnlnsmtvwvnplpnlj^gbc�������˙ljjhjkhijpwuqwxtnu|���~�kWx|rprryonuiG-'+->W_V,-)/&+/64-+20-148JVOE:?IKE@1EbX+-<<,2Q��X1>@KC>.)&$##!)V����qlhx��������{���������ü���������������������������������������������������������������������shWYK=.&*./.BIUK>e�������}M--/31*+/1-1+3371565:1@:=8@?EG:4/+,,1/3-/1=1*--16?N_v�����������������������������������������������������������������������������������������fffddjchijiceeiadgdgd`\YZaenv���������������������������������znjUQJFCOMOVRV[aZa\feda`f_adfagaegccffdfdejfjgggkmjjporxwxqpoopmkic_^w������ʊkhpoqnsiiqupmmuot���y~����tWesrpqofVWPV?/.23Q^`M2+*)'-273/1;325.38STHHEBEAC:@aV+.>@7<W��[(',-+*%$*!!%J����pjr�������������������������������������������������������������������������������������������zk__R>-)'+./6BLI?W�������vM1+2//+)170,.4448:@5;6868;BC?6/3/,.(,()-.72.,..79DOp~������������������������������������������������������������������������������������������hhigihkgmgijhfhgccef`e`[\cjow���������������������������������wlaQQCCGNPQPW[[_^[[ac_hac__dacfjdediddfdfcfihghdijp~|jotusprotqqpjea^k�����ػ�qnnosqqtnnvsjlbn~��|xw{���nXWc[`NLA9ACBD54..Uab>-*'-)-4;..8>31/613@QLJA=D9AMFYP)+K;5-Y��^')&$.(##!&As���qgt����������������������������������������������������������������������������������������¸��la\QF1&#&./0?EMF=v������M//216..0CE78?85894567;=BC:?A:503+0/,1222:7/(,+46M`u������}~������������������������������������������������������������������������������������cccmhelgkdjhigebb_ba`^[[ZXcmv���������������������������������zsaYQMIPQKPQTU_`]`bafhhckebhlhbhdcffhefdiefiffacgo��{lqurwnpvrnpmgdb`h�����ֶyrtkqu{xutqmoeaiz���}�zwlchPA@;HWORIKM\\ZC9.7ThZ2-)*-&-@C7.A:2,.4+0:<AL:;A54HT\O17a:,.@o�q,.)#'&#"! %6p���tgr�����������������������������������������������������������������������������������������Ĺ���xe`YG80&'&&,9FLP8V�������R08;7:/:*4314A6564;3;:7<AC>@<430-/0010567768,*-16Qiy������~�������������������������������������������������������������������������������������ddfnmifcogjmeggcebcbd^b[^`dmv��������������������������������wleXUHFKMONTUW[VX^bb_hjceifekjejkecdi`cedafbcfijm���rnmsvsvmqqlokkmebg~����֦turjtuxttrgedg������|_L[ZPR<I[YO978ORG3+,5fmI4-**,.6FF:;<9*+.//;514C>B964DZ`c;Cj7,/4P��7)-*'$!# !$4k���xkj}�����������������������������������������������������������������������������������������Ŀ���zkbXK71.-*'+*7FR?B�������e:3@?62+3:600;7789879;;?D<DD>784.*,*04276?6/).,-:Qq���������������������������������������������������������������������������������������������hhkgfhehhgedgcfcicad_^_\X`ihu�������������������������������vo`XOIGQHMOVQZ]Z]\_cbfhgbjgfgicjlchcbehacdebbgfp���xmosnxttqptpsopnglio����֤smuqrvxx}smcaru���z~y���sjzkg`KGQSC/.3?7.*,,<hmM.1,++0>G?23;525176D.+.;>@9227Ncng\z?7-3;��G%$($#(#)+b����tr{������������������������ƹ���������������������������������������������������������������������~oaQM:;2,&'(+07LF.x������lA3339.)/,15337;9<=9;D9=CC=<843.-//,2.094451**,/E_t��������������������������������������������������������������������������������������������jjikhkjlciggicgcdce_``][\bcrw���������������������������������wnfZSGLNFROVYY`]b]cgcegdgjjfjighibhebbedeebddfl���xqrnxyspstpqvutupnpep����֫ynurruyuyytdi~y~y��}}����ztooicWZD3.-/2+2&/58imA'*)/.ALG8,6=0-372B57).6A<8742?`rix~P@*56h�X) & $"$6]����{w}������������������������ÿ������������������������������������������������������������������ĺ���scRN<40)"#'*36KR1h������sJ7019</0163557887:<:<<?BFB=5733-**13-87<58(,**5Kbz���������������������������������������������������������������������������������������������gglqjhhkjgffefhecchda^\[X_equ���������������������������������pkdZSIEGSTUUV_`\^ieecggfghhjjkdihhdgbdceabhidin��rrpruqrqrqutsutsunmmmlt���ܾoquuoqpsttr|�||rw�������vihjla[U95556:')%.94[i?%''/0GQ>08@B+)-8486*+.:H;-983FIfloyYL;;-^�jA% %.Y����|s{��������������������������Ŀ�����������������������������¾����������������������������������Ƚ���sgVQF7.&!#*.1KY<N������hH6<26I:.38437;6<:==97><AD>=;0.4-+/-1042655)*05=Zj����������������������������������������������������������������������������������������������kkglkkgdggg_echaaabca[]ZYaiov���������������������������������leYULHLTSWXX\[]c_ghfheihdglddefebfdcbcacgjekmlwmrnrvrvxwtttvprvuvrnjfp}���ɍqwvrqngmrw}��}uvr~��}��}jhgdT>@95864C-)&'.(+Wn>'+.*8@?/57D4,/48=7121.D<1.1<KUHY[Ehe_RS>h��o6# )R����yr{���������������������������ʾ�����������������������������������������������������������������ƽ���tdUWG;-($#"(&2AZF@������cZ98324C86<;2478<99?=>C>CBB8>42-4+1//44660/+.38Q`v����������������������������������������������������������������������������������������������ffjhjfigfed`ddccddb^ZZ[\jeggu|��������������������������������pr`[QNORWUSTV[cebcegcecchddddefghdcdjaeefjhgijmtwqtrrvssuxruzyuvttttnqijt���ϙv{vurrjir��}{y��zy���~tkfbd_I.2103@O?+'%,))1MnI,368>3.-5=G0-373:B117;H=5&$.GiYNd<KYa]VVw��^' *Fv���x{x����������������������������ö����������������������������������������������������������������������zf]WM>4,&"))(1;TP9�����|bZA:6:*+,59;1<55B@5@><;B?DD:91-+-12-021581+*'.8Rr�����������������������������������������������������������������������������������������������kkjlhklkffbae_ij^beZ_^^]`_cks}��������������������������������zmaYUNROT[YYZ]]\a\cfaeffgei`edfgjahejdblcelkemppwururmqvvxuwxutxsvwttsnnn���Ҟwxtotmj{��w{}���|��xha^faM9<;01AS\/%')#-(/EhW3GKN5+,/:B11109856329HK:9&',8j[<gCBQG734O��Q*! Ax���ypw����������������������������ż�������������������������������������������������������������������ø��ha]P>5.("&(*(2G`7f�����cnN,/2.-348>6;4;9==>86=EE;?666.+-3530778;8.*-4Kez�����������������������������������������������������������������������������������������������hhhkhhieffbcfde`a`\]]\^VX]fmt�������������������������������~ulcWQJNNQSY_b]`c_[`bbdfdgeaifjfhjbfcidiegijffnlv�}moqpnx||uwxvywvxxurrrpq|��ت�vyrncv���yz�����wx�w]Y]VA/614:S]\M++(++)*+3ZlM?>=4/?AHK1/*29G21,0=R?88/(,8ha.JQLH/'"$.n�i.#6i���xzr{����������¼�������������������������������������������������������������������������������������ü���xjZNI8.*+)+//+;W:P�����]tQ/-41045578<87:6:>;9=;<K<<C422.10457961/-/43Rm~�����������������������������������������������������������������������������������������������hhijghkgebdfg_ea_^_a^^^ZVVckt}��������������������������������wmdYPKNQKSZ]W]^bb_gafcdddcffedglkjdghceggfejhgjp��ususrszvxxv||v{{vuqrwvwv��ҫ|{qigq�����������zoiQF/,1?3+Tq]h9'#().)**4Gk_;1+/03M\F6-,58:-,.3JT/4;(/.4QV*2MQA+(# +E�{K ,f���zw������������û�������}������������������������������������������þ���������������������������������ɻ���we]YN>1//(()*38VCH�����[q>.(14756;55::@8:74<78>B::3183/,.,2:8660)/,/:St������������������������������������������������������������������������������������������������ddmghgj`dkdhgaka^a\]X_XXXYam|}��������������������������������uh`XKKLNORW_[]]_]a^cccelffdhegfiidjhmdgkbiiiomimu|nov|uuzwztvyywvzwywtovyw}���x~yrio�������~�����n^]C3-1A9)&CPdg3,)&67()+,3HhK6%2.>WN54-<6/;*0*6YK2=N/171.B-4NS?## $3s�Z1V���}owz���������������������v�����¾���������������������������������������������������������������������������~e`XMD7,-/()$-1T]>~����^n<3.70&/686<5@>CA:;8<=?=3:776.31/-55432-'*(2Fau������������������������������������������������������������������������������������������������ggegigbgcffeccd_ccc^Z^^VX[inx���������������������������������ujdTKIKLKXW\^Yabb\hhbgcgebjgjfjmicefhhfihfhhlnintuwnuqrwuz{{uxwzzy~{yyuy~����qszwn|����������{|~uaTH2-7KD3'(-?nF2*)1E3'0,&)4Ia;.);UXJ9.+/819*,*<_A+E]3-7'+.=6Oe?$!  ,O}g_r���toz����������������������t}�����������������������������������������������������������������������������IJ���m\`WM>3/),+''1GcCj����iYB3D<2,;63;99::A;A=;==>;;7-02643/39763,+(.5E[s}�����������������������������������������������������������������������������������������������ddfjbicdcggdaec\be]d_^[ZY`dls~��������������������������������vj]TUQKLORZWY^``_]`cheeghdidfdjhmeeifcfegejmmklppstwtqpqpskqjsonopjefy}���qn��qmupz~�������|�z}l`YN90.EY8,!&'Ev@8*'JT21<*%%(4RH>9ZbS=2&()297,))@f;';Z142%&2E4OzS! # 1bg����}jt����������������������������ø������������������������������������������������������������������������ĸ���uecXP=2+-)()(1HePi����nXH1C8,).8=?9:<?:8@@B??H@850240198368:6,+*3FMlx�������������������������������������������������������������������������������������������������ddhjcffkjeccdfaadfiab\ZY[aakv���������������������������������sf`VQKQNQSTSY_^``_ff`ehhbejfhfiojijkfdffhikmnmjslrvvxtrolrlokmnelidegr���xW]W}yhis���~����{z~�zsb[NG/)-V[/)$&$O{E0,:b4)(9(%$',6>Mcib?67()09<.+,-Rd-&-J<>9)12-.c�a)!(>l���|qn������������������������������������������������������������������������������������������������������������sd\YQ@4*%%*),18]IX�����YV-9</.*/9934=88<D>@@B@;930*+3/2482923-),3:Sr{�������������������������������������������������������������������������������������������������ffekfcjifdcjde__a^_g_^[[T_ehyz��������������������������������wkeWOKLHOTWUTV^__bhcdcgfcgihiiheglidefcglgkljklnrqtywvzxwvstsvrqqnqwuz��qY[Uay{w`p��{�����|x{�xmfWF,+=bZ,'&"&P}R@/@O+$37=/2-.7BkheG6;*%"+;7.&)7Yd*%*GQX9@C/'<xqA0#  2Srv~lcj���������������������������������������������������������������������������������������������������������Ƴ��wf`bMD3+''*((.6^GW�����eX./903;7;5:94:>;=CF@<;?832.242025539.,)41CYv��������������������������������������������������������������������������������������������������ggfngdfhbdf^fe^ac``ie^W[Y\egv��������������������������������~sh`XTOHLQRW\TY`]^bddddghe`dlahihfgbhiifikfjjklnmmprwxwyvyywtv}uxxz|w}~�xLLar����gr�}|��z��~xvs�{ohU;/3]nM'&"#'VZ??64$(=,:?;;3GmqB9F64%'.,<7)('7kM'*,?]]:;;(*]u>(,(% )+Ix�uc\fy�����������������¼��������������������������������������������������������������������������������������ƴ��uc`[U@4+&***(.5QJOx����a[66A29:=I;=?>;<;:EDB@9<982.082//575/3,+,3Khz��������������������������������������������������������������������������������������������������eegggfgghbcbac]aaaa_aZZVY\cit~��������������������������������smeWOJHKOMRVZ[Yb^cdbgfggeaggfcfhjijfhheihglhkqqnqjqvrsuy{yztyyvvxyuvw���aow�����}nzt}�|���|qpz�ujV9/4BYzL+$ %,L�]QE')*47#4GKDNhxWIOH51'(/(8=1%+Dr3*(+?^r>6)+A}:)$-4.!">v��iVYr����������������������������������������������������������������������������������������������������������Ʊ��~haUN;2'&''.+48TOHw����lY78K36;AJ=5:C?;9C<=@A?6-023A4363583-3*+7@Rky������}�������������������������������������������������������������������������������������������ddfmcad^gaeae`a`\]a_]_]XY\dhw��������������������������������umdRTOGNPOSVX^_^^bffbg_adhakggjhdddghighegglllqnqsqswtqxvsxvxyywyrwvw�����������uutxw���yss~�m[;-/:@Zx@"&$,N�`d5&!%7%(/8HSfnVPVC>1,,--1>83-+Go/'(&8du=)%,\f*+082&$.d��s_Yi����������������������������������|������������������������������������������������������������������������ƶ��~i_RG<10'%'+-(5DD;y����uOGAH6?=QHDB03:;A@<D@>;5010440@37@881.*4<J^t~��������������������������������������������������������������������������������������������������__hhefbgf]bfhbcdbbg`_\^YZ[ihn���������������������������������vl`USJHLNOTSX^Y__ceecdgiegimfcgcfdcgdkbcbfghjkprsqqrtvprw}v{uxw|w}��}~���Zovy����|||~~���tqy��fA-.7TIjq,!)",1I�gZ*")/3)*2@Za_PCF::1+',)*,458+1ZX-#&&<ic=%$:jA,4@6./+X���`]a��¯�����������������������������ldh|{����������������������������������������������������������������������ŷ��|fU?:7,*())'*)/=Q3m����~PBLH62>>A::8>:8@F:E>68122/3;//7396/,*-3@Shv���������������������������������������������������������������������������������������������������iihencchdbcfaaade]a_]]]_U^dhr}��������������������������������ui]VSJFSSRWYRYX^```adgdilfgidgfhheedgeidjmikipppotovwztuywuxuxut}�������83>CCNYbv�|}����ypm�}q^4.2M^GwW"#)'/<Z�j:$&"0725HMF><2>C-(,(%*(-123:3/WG$$&,Tel<##JmAEP;'!*E}��t[e}�ƹ��������������������ƿ������mNJRfunyy�������������������������������������������½����������������������Ž���ybG=7302*(+(.%-HY,^�����_CCB86>A:DK@>@=ECOS>?7:/1,741648>90,114EWr~���������������������������������������������������������������������������������������������������ggdagcfef``cdddadbede]`YYY_js~��������������������������������wkcWQPDKSQYW[aaZ``cghihifd`f`Xgedehc_ebghhnjknkusvsvuvxyuvxxvvuz��ͽ���F$&%&&'+>n����}��ymirp^TE/>?bFZm?%#$,4Pu�r+##&=239?94///3@2(1)*+4,.5351,G7*))0eUl9)2[[72.)#;y��x_dr�ƺ����������������������������OEGUY]ejnhty}~}������������������������������������¿�����������������������¹����oRA<702+&%&"%,/A_.P�����^@85>@C8739==:;IIGFH=52540332015421/3+1H]s����������������������������������������������������������������������������������������������������bbgeebgafefcccgeeca``\`[[^cfu��������������������������������zkaXXHJRNUXYUZZY[``fefjhgjihkegdfjgbdagjefldgjlsnroxyrwvwwwuxvw���ʍosV8%!"%&*%I������|{piesiN905@YfAk_("(,(:_�j &+A,,.8439*45:0+/*,5:7.2895.JF/+,8`Il>02_B*% #+m���c]l������������������������������xUUWXaa`fc[`hddVfnsz|��������������������������������¼���ÿ�����������������dz����odL?;6-+&'(('**/Eb9>�����xR353;GMB15B89B>FDE;9.5/3/11275696/*14;Scv������~���������������������������������������������������������������������������������������������ccgdeddedhheiacdheeab]\\^[cgv~�������������������������������yl^WQJMINYSYRX\\c^ad_ahegifggggh`gicjeiiggkjnmmmquwxxutwzzw{yyx��߷l]455,''-'+8a����ּ{vjUPkWF214<\EX�I)(1+,Ha~�q""((6.'00/8784?J93)0/69-+'/HFOZR2==4W3iN&/\4'' *L���l\d�����������»�����������������vfhnvxywulf`ge[SMWU]ekr}������������������������������¼���������������������������s`_G=9514+(&'('&1C]85}����{Z:;-<<JC=:>:9@@L>B565./-4407:17441++3BUjy���������������������������������������������������������������������������������������������������ccfbfeddidegjdcadddc^^_[WZ`er}��������������������������������ti_SPJNPPOYYVYaea]cgfgdheieciehmljggfhhhe`gkiijnsystuyuy{{x|xy}��Ѯ�d364/-&(2<U{������oYIDSOA74?AaHx,(-')=Zex�r'!$+4#*45<VB2;4GF9/*,:7/2+00,B`hNF2<`.[S%-U1'%#>u��n[`{�����������ĵ����������������yvz�������yunkd[P??DGIKYjoz�����������������������������������������������ü�����zoh^TB>98/+')&(+),1<O72}�����_1:/3:EL6:D@:>?=;838;15,:8405<<411,2/F`k���������������������������������������������������������������������������������������������������ddiidhgbhfgbhdaecc`fa^^[U[]mt���������������������������������vl^SSKGJOUTVS\^a^^_^eepfbgcbcchhegdfjgfbfiijmgpnsvrsowvvr~�z{�������oJI;=-&')0V~������vlVA=VRC==6W][�H+(.%4W[\V�o)!!('&*<LBNL;5);OH50+<-''(*'*.Jm`3(Nc(K\+6N("/:n���eby�����������ǽ����������������{}�������������}th\KC;F==DLX^q������������������������������¾�����������¾����qfd_`[NGE>=D83((,(+*/1;E9-y�����a5<.869H?HC<;F@>;;847=42,-109=67561-7L]u����������������������������������������������������������������������������������������������������kkelfkhfih`dcdgjedf\b\^^V_`ht~��������������������������������{mcWMILLTPX]Y[Yc]^__fcngdlegbbeb_fehebgfddefjoomppruovvuzwz}���������^F61-%'-0P{���n\`m_@?I`W>68B[OlT.0.6-Gb_V;�."%(''3M?B:+=S*3JT4)6>*(#,) ()4PfY=ia%3]:->"('*P���rds������������ij�����������ý��vy����������������zm`]RFMCA?9FOYg�������������������������������¾���Ŀ������rjXOTBKUUY^XVVVG6/.1,,+009B;.u�����u@>484;O=CPEABGA=75+-613/1--39:82161:Nk������}�����������������������������������������������������������������������������������������������hhfifdfdhjgihbcbieec`_^^Y[_gn|��������������������������������~i]SQNTURSRXW^V\bcceahljehfgecacae]efclecffnomliporturysvu~����������HA80,$&)&R����hZX\bI=KZR85B`_QZ50**'E`]h@0~�? &$/3EaLF<7=cF?[\C'5;))(+'%)#-3O_fvT&-[Y.*$9u���nh��ì��������ǿ��������������|txz��������{��������~~saaVSHHD??AO[y������������������ż����������¾��������naXXVNXPUTmnuohjkaT?3.5*,&'-1HA/y�����vF>>434UB?DA=DC==641,72074/485C877/8<Vn������������������������������������������������������������������������������������������������������ggccejdcigmhfcbffacccc\[WZ`dsy��������������������������������{h]SNMOVSPWVV`[ea`d_dehljcfhbegfbf]chebehhkgjllqjmioqrwr{������������B11=<?,#*Q��|�eQSMqhOHI:;@Gf^_<1-125\r_Q)*n�^+$)1&4G;>7.*,39[]a<80$$$)()'*01YS`�R%+I\' 2b����q��÷���������Ļ�������������on{����������uz��������~[hZ^UTOKNHNN`v���������������������������¾��������vbTXSa_Wlfrf{��xnqe_U=:76)+'(*.CF1k�����sW;7385GS9<=<=EC=7;3,/30250:8989:925A[q������}�����������������������������������������������������������������������������������������������ccfcifhefmkmfihhfc`ce^SVZW_js~�������������������������������ypgXNNMPTTY\[^c```ceukggebgddedfdaZ^caabenbheeijjhmqqrpr�������������]K:_trC*&G���u_O8VY?2<34GPici;4747NzlS0$1T�}8(%,)4L@7+'&0(8WffL5*#",-,*1('*35ClnA+1/" !J{��{r�������������ſ����������ǽ�loqx~}{|������sO{�����q��v[lejd^W]ZQZ\bow����������������������������������o[VZ_gtlhryzm��zqbcb[K@6:8**)0)3EC)d�����s\813.6AJ29B<>I?E349/.B64=4144<567>=Jgx������������������������������������������������������������������������������������������������������cchceheikmdkfkcbebc`aXZWST^jr|��������������������������������zrbXQKHHUSXZ\[f^^bgiiegccegdcddfchcdfhahccdeiglomenmkqpz��������������yVl��hPGg�}|��vW;YR7/+29HSmxeGA?DKY{d8#%&?qD0/)*<SQ2&&(*01Ueh[-'(($**0/((*(1-8Rb=)"&!!5{��qmw��§���������Ż���������ȶ�dblqqrxuv}xu|�nX3Z����t`w}[Yqs|qidnc]dahmz����������������������������������pnkfkqw}ybeofstoj_NPSRG<=N9-6/+)3GJ+]�����pZP50248K59B<?G@:31801230342956-38>DRq}�����~}�����������������������������������������������������������������������������������������������ccdighfikjdmfhedffa\^ZU\XZagt���������������������������������yp_\PKLLNTTSX[Y]fbahdfidbhhffaihcea`kfecdgkfkhniimnkkts�������������³������xy�ziu��n<7;>(2:FLRZ{q=FCMHPesb-#"#7[kW,,1*0[W4.)%#$0Mglb4(+%(&+42.-&,*%(-;U&!,a��shk��������������ù��������̲uUd`hlke^_bffimkW>/Eo��|SDepIgn{|k_utomqpfmy���������������������������������|zz�zonvp_FWKEZ_U\MKMQJC>AM9*)'--:BL-d�����nc_.-/17^;>D?A?:;23,-/577758740.25=H^x�������������������������������������������������������������������������������������������������������__ebdcgmhkfmbee_dba^^[UWRZ_gs}��������������������������������xicUOPJMN\UTVX\e^\adceibffccc`aiabbhid^aceidbejghipqy�������������������������fVRU\H:,<A)(2APUex�H+JWRV>dxa%"#"1TRn10--<T^1/-&$)3>_`lW4%0++,.-4*.++*.''D?">���ji|�Ƶ��������������������ʭdTU_b`dgd`JKICRIQ;6/8Qi^K0.CE@Toy�We�wzusttwz���������������������ſ������������~�xZQXI76799AG?AC?ELFBDIA..*%'.6IL-\����tpgW0106;T<=CAC<85/4.4.4.8036;60+*4?Wl}�����~������������������������������������������������������������������������������������������������iijfjebmdfdedccdjb]]^]TXPX^ct���������������������������������niUMHIJMMSWXU\`_gccdcdfiicedaddgedaa]__c`ddhbihow�������������������������{O3C80/,.0;V\9JLP]r{a1,@IYWKhtP*"""5]@h@')-6Y]+'&&$).0C\v`:*),/2-(/-.3)0&$#(=!"'n��weo��������������Ǽ�������ͦ^OQO^WMEFWT@@C>9;962,25<78/+/008S{dax��|yz{|wz����������������ÿ����������������gnaG;9732414498<<A=FGB@FN3(+0($,-IT+V����pwrSD41.<\A8=E;87340120223.3145+'+5;So�������~������������������������������������������������������������������������������������������������bbgceeebecbgbabffd`^`UYTRS\iv~��������������������������������|peUPQTHJMOTXY[]\\bcdhcdhidgfdce`ad]_digc_f_bbdq����������������������{i{���{N,1,(!(%(<:LJPWVl�wH3;BQkPMktM+,(*9a8PX/,*/]e/(&"#&10:I}xeA/(%++,9//0(&$$'%#(O���nf���������������»������ɟZHNVMPHG<4;@86952812535521-+-+)(,5DKj�����z��}z�����������������¿������������sdaDF91275811301/:6<68?@IAG;.-1*$&'-HT.L����|soTPD/28RD=AAC8=10/3192/.1.795/)'.:_v��������������������������������������������������������������������������������������������������������ccihgehccedicddd[]eb\U\ZOTVfr}��������������������������������znaX[LIKKRUXWRY^\_cffjeggebddbdfbadae`_c`]_`b_j�����������������������x`cfy�^E+*- !*BVh^MP\\��iU==D^iGUsyS+)'*1d56JG-01cg.+&+$(&'+0\{|nO2-*.(+)/.,%$,39x���m}�˴�����������¾������ȝPAGFGDC?:536434412/10.2;0896A,.(&,)*8^������}~�������������������������ž����vW:>5363243310/.467:58777<FG4+)2))''.LO/I�����miVMB5-6NH;;:E7<-/,2/50-=:9874-&&/>dy��������������������������������������������������������������������������������������������������������ccigeb^bahdd`^`]^^b\]YVRQSPbn{��������������������������������yncYYPJGJUTUTZY^WWea^eijdh`eafc_cf``dc\_\]ZZ_ew����ξ}���������������}kRF;PlfE(&$$)?eti[NPYk�]XdPFLlPIa||U'&.'0_>)7V:/2Ys.&)'$'%% 05pyqr`@&&$'+/34* &*&Z��vg{��æ������������º����ƢXF@?K;67952544:3/24.0./,37?TG73.(.''0(7Xo������{~������������������������¼���[N;8<17:719>:10042377:@657@?32.40,-$,1FE/F�����of^GGJ12J>@<@A54/,0/142-:98285++',Jg���������������������������������������������������������������������������������������������������������]]abbc_^]e__`^\_]^Z[SPRNMUYcmt��������������������������������zodSMFEFOIQWUXSZUZc\^_ifdg`e_`c]_dbaa_c]\VY]b|�����ˤx���������������uiO30KTJ5'$#"(@ZvtgNC=e�c3AfUNNfEOm�uO#!/*6X=#*?U=-^�8,,*(&$$)%*AiyyrgH($)&'-/%)'"!#E���dd��Ư������������������ŧ^JAACC952/05535735-,*/./0OBbwo\F9.*'.)&.<Vs�����}�������������������������Ǻ�vK=85;534>34GV[K>;2/048A;9<9;650--.*%,,3FD.E�����ab^J@=?6SF;;=:41///34427.12>51.)+5Sm���������������������������������������������������������������������������������������������������������]]\]ba]X\^\a^Z[]^[_UYSPLLNT]ms�������������������������������{rbUNFLHKNSTWZXX[\`\`__bgc`]^aa`_aea__YVXWSUn������ňy���������������tW73FO</)!"!&4x�m[F2/S~^F79ZXN^ZEQ��pM*$&2<Q?*/:RV5\�G%-42,%+)+*0>nzpmfR;+''-)""&!!3j��q_~�ɽ�������������ľ���ŦYCKI>;B3004/00/7/30.,./,28FZ����hN8*))+&*.Cdu����~������������������������ʽ�e86:3/27629?3V|j[C1,+-323:89;2/.544+(,04NL,B�����`ZXG2A5<LJ?<;950-/,0/021879225//3A^z���������������������������������������������������������������������������������������������������������ccd\_c``a^cb\\\_[Z\S[RPMJNPai|�������������������������������yncUJJJBIOUUWZYd_[_c`_f_dc`b]cg^]]c\ZYaYVSUV��̸��ͮw|����������|h��{i[?XQ0**)*$!3b�|`5.)Cye2'-0EZWeWO`��b1($#01JE*108@3O�S(.,,/+()(%+4Hg`JZSm^/)*(#%" &S���ee��ƫ�����������������ȮaDHPKKF:)/101055/+612(.0L>E^������wb;*'&'*,3Qn���~}�~����������������������ŧpA123-.*1;:Qq\K���s_@.')+0686:77.)042.*$//P@-B�����`SfLB@;>TP=><:302-032413063022,26Lj~���������������������������������������������������������������������������������������������������������__baab^]^[``[[ZYZ\YUOVZKKOQ\is��������������������������������{pdXRIILLQUVZZ]\[``d`bbafcb`cfb]dc^`^ZXWXXUW��Ƴ�ζ�z�����������e\���oPMV7-%"1/,*Y�sa5'.7mvD%$*@Uirc]d}yI:/-',*?<),0-.0G�e*/-11.+2/+-02;;-3?PZU2*'"!!2r��k_y�Ȱ�����������������įiLPWULD<2*)*35=MC+/><-'$(XWAVy��̿���aE++;LJ?Om{�|yvy����������������������̵zQ621,+1,,78[��E����kP6++*+4768:5/30/2.%&,.PA+7�����_YcXE?@>XC<=E<51-,414579500/.,+0@]q���������������������������������������������������������������������������������������������������������``eii]]^c]_b]]aZ[XYRQPQMHIS\kx��������������������������������yqbSHJMINRXYZ\[bebfaadf^_d^df``cdc]]\\\ZWYVW�¯�ŝ�~�����������^m���iB?G4$&,833PucN=&&3_rM1%#+,H^|xc]Zvp7/+*)G/.0''8.',>z}?+5+,(*+)30/1./++-@HA8:%&'!%R��~`l�ƽ�����������������˷kQRXUND815,*,3ARZQ2<PO0&$'8ZA2H��������kH<>hlTKd{|xzwy������������������������\C225<40+-=9M��L����{^C8-)-0113831.22/.&'5?PI-6�����eeVl@>H:_B=?;86-.//0+6=4<2.00/1:Jax����������������������������������������������������������������������������������������������������������bbcb_f\`c_a`[^^[ZWUSQSQJHLQ^px��������������������������������{k_ZMILNQVXT`aa`c]^dcde`]ea\aafaf`a^^[\ZVXRI^����Ƶ�������������g����H-LQ+,&&CHUm\>.0&7MfG@/'#)2RV�wWZR�q545/+.,,%$(5+,,4f�I1=5)')(../,:22*+*4:4*)/IK9;t��g\��ɴ����������������ɽzP[^VQD8853*.48F\gZ29^]L0)+EpM8B���������bFD]�nT[tzutqs���������������������̞oVE82AC?6-(<<DcjF�����`L<5./E.03<54./5-2'')5^?+4�����rYWfO?DFT??;:631,/9=1.147-*+/25BPm{�����������������������������������������������������������������������������������������������������~���ffdb`c]d_a_e]c]\]VUXSSOJFKV^mv��������������������������������{qbTNGIJOUVW\[ce\dcdcgfedacccclffdcea]\\[TD:N������°����������yi���f1)+*$').Kpi]E*%/0NY<7D;-1+;HX�_Ba[�sB572/+.1)(5*0&'.R�T6D00#$&/&.78/+)'492+%(-5HJb��u`t�Ϳ�����������������]akeaVS@5301-/BG_skG4\bZHBBZlJ5W������ȿ��XFX|x^Zlwrpqsx{������������������Ծ�eNON3<TP?*.HUGSLE�����kRD7'/6*+/./4*/)3J@+2?`;+;�����{HUhWEDWV7;B66230210.31301+.078AXr���������������������������������������������������������������������������������������������������}�z����cccbbj]`ee]f_Z]\[VWYUTOOHJR]lv��������������������������������{pg\PHHJNVWT`c]icefbfegadkhddgkbbbff^``_WF43J���USl��ĵ��������]msVA%'(,'#/9ux[L7)'9NWI57LN/-2;Cf�cNQe�p91/0.*/01,8.+)+1EywF>,)*,*-,*0:.*&()++%'#%%.Ji�rVl��������������������Ǔibgtni\TRNB;.+-EJ]uycC:TbVV[SH9B~�������ȶ�lLFl~j\`ppmpvyz}�����������������˨|ZUga==^dYKCWiUK:W�����tN>;-+*'+-/1/2)-1*'+-<c;,3{�����OPf]MAXU4:E=0,-041324456350748Hbt����������������������������������������������������������������������������������������������~�����������ddacge``dcb]e`][\XY]QPNMDIO\hw��������������������������������{rbYOOQPPXQ[[ddc^djjhhkbijdfjifffdelhccXK<-1;u��VBUn���²�����hP.6452+'&**3CYocK/2-.KU9C5:JY5*3@Jy�kZV{�q:/+,/62/,&8(&'&-@eO5.1)5+)1-1=-(-&,+(#-'$&/ZxsQ\}�������������������˜gmesxzunda_VN7/3ESZlsX;<OWZPM7Aq��������ʶ�{]Tc~vfbkoourvz������������������Śn]ixx]:Uad]VXYWF@{�����pVE?.--*)(/0),6,*.+,1Fh5-2r�����SHa[KJTX::5>44/-3347<854.-.0-6Rh��������������������������������������������������������������������������������������������������������ii`dcc``b`ceh_\\\\XUQPNJCGNVgx��������������������������������{rd\UNITSWR[[ab]aefilkd`fkkl]gkhlirzkUGHA:1++@��qn�������ƴ��k9*(*)-1#$'/0>^bSE8730=CR>J8=DV98>HU��vaW�u@.'3+04//6@.,(,(:RtM*,405,-++540*0,'(+'.(%,@}�gQf�������������������Ølcprz~�}tuymd`J2+3D\ir}qY>96=:AMk�������������raf}}tforw|uq{�����������������ֿ�hil��vQAUgd`bREGo������mRE=.56(.,/-(/.(-(',5Re1-5j�����W?[WLHVN86572.?:0511><53,1-/15Yl����������������������������������������������������������������������������������������������|������������eedc_dbbcfa`_`ZV[^V\SMMIEJUYis�������������������������������}yqg^WQPMSUZ][aiedefjihiiggfmdcglft�kN928:2-41G�����þ�����ӻy@A*,*/)))&)14Ta]?88ED<8<UH<9>=GUNWPX�vhXQt�}H6&(-:0029<5(.*.4EO=*)1:2-,(--68(''$!%*025?n�|SV~������������������Ġmhquvv���|�|ulVA//Icqpuxq_R?BKX���������ü����xjt~zpps|}xv{z����������������ϵcor���oZMKYXVKLs�������jPA512.,0313(..++++-4P_:4:h�����\>V]YR\O;;886.0.7533?:51-,,+0<at�����������������������������������������������������������������������������������������������������������ddigb]bd`cdcd]^UZZZUSONKDDR[kv|������������������������������xsjZVKPTPW[[aafidhaklhoihkdmbgjkekl;84?7079KVv������������ϓ7:L0%(/(#&&.3SeRRHTSYH32@VUFFTQNa^[E`�ihJVn��N7*+75,.)?,+6,/+6=:6-(7@1'&),/05&%.-!#!*6<X��cXf�«�����������������ljswzrv~|�����|vcSCCRcsww|�xleft�����������ư�����qny�~tqyt|{|����������������ͮ~dak}���riXOOVd{�������{hQD:66/.003852')55-/4TX235[�����e=Q_VQ_IG44.343711+.8:;522+.2Sc|������������������������������������������������������������������������������������������������������������bbecehebccbca``V]][XSSMJIDRZdt|������������������������������yrf`VRXRY\Y^ccdeiggpjnjlnnmlhicPD=C/43^eVN`y��������������q;3EeC'(())'+2IfondZIF22*,7UPS[_XWTWGAf�it8Sq��ZI0=@2)'/?2,''$)0982.6C?..60,.17'$(%$! 9*M��|cf��Ŝ����������������fir|{z|~{�������rj_[]_^nw�����������������Ƕ������sp|��}yruy|������������������ʥ}fZYax����yqu����������xdSE1/7=63066350.48330\X719[�����gEKdM`RLH81-12-2-,058:;0-2/+3Mg������������������������������������������������������������������������������������������������������������cc`effbc`cfac[[]\WZ[VOIJJHSYk{�������������������������������rg]VRTURX]]Yceagjjmomiomkkq|j@8/**+69J~xx������������ڽ�S<+29nW*('-./A[y��skV/,/&#(Bd6>YaTL@WMJh�vx1Ot��i\GK3-.%.9,'$')14,1-0<@:6.,02D;/4+#'%",);n��_`|�ο������������Ŀ��`bwy{{���~��������|tkciSKq}�����������������������|uv���~}xwy{������������������ʥ~tf`\lw��������������|f\M5.4B@>885:810262336[W988\�����oSU]TeF>>35-.)/,-,1/758/+(0/CYu�������������������������������������������������������������������������������������������������������������hhghggd`dcc`bcYY]Z[T]PLKIAPXiw���������������������������������qfaYVSXUY\]`eicfmnloqjnnrfz�T.1,+.2;Fa�������������ʹ�S82-0-3Td@.3:Jg{���h^m2$!+ #1Mn(7Y[ONHN^Pc��x7T�utpKA3FR$2+($%+%,/4210182.901/*8/'&-"!#,R��mVl��˯������������ž�b\lx{|{��~�}����������pmrilxrot���������������������������~ywysx����y�������������Ȩ��|vyu���������������q^L9,0>JC>98;840/1J7289[U005X�����pULWXlB5DAG/.+/:-+24;5:;1+6BLbv����������������������������������������������������������������������������������������}��������������������kkggccgbbikc`][\[WURTPMJHHOZet��������������������������������{pi]URPPV\`ab_fikkjpqmoppkm��>%.$*7?Nc�������������ij�M/4/)*$1Hq_P_kt��lSIH^U+$'$()5]y-4aYQJONN]^�{Re��pos@8:`I+/.0*#)*/,6-./00+*+2,:-9($%$%#""9w��_a��ʹ������������¿�^_huw��|���������������xv}~~lmk|o`z����������������������~�|t{�{~����������������ɳ��������������������ub[NA2/8TSKF;75>94)1H764:UL-.4S�����[MNXfI6DB3,2220/)(2;=91.6:{Xly�������������������������������������������������������������������������������������������������������������hhhjfjhelmfa__YY[XWQPPRQCHL[h|���������������������������������qf]VSWUYZ[`ebgijfqppmuqqnl��@**'2Lbo~��������~�����tC32<:7,.8Gq�njh[WE5;Bei4("%%*2=`z'5ZbZH6DFVeq�{he��mNpEFl_6&--,&*-.+0/+-.1/003293.+1$&"#  *^��oYg��¢������������–``invx����������������������zmhw}dYv���ij�se�����������}w}x~|��������������������ʹ�����������|{q�up~X?B>=?@C?CXYUE78794/-07456CSQ502T������^UETcS@9<-.2/707/3;<C4226BM]t�������������������������������������������������������������������������������������������������������������ggfghnifabia\_X[Z[UUOQRJDHIYds~��������������������������������vhbTMQRS]]^egfigjqrpooonjo��U*/4Fj��������~}�����bA:@KF@37079Lv�yQ:?/3Gg{G'$%**086[y78OkhZ.2MYiv�jrq��cK\^��K*#'-(+-&-)-,,044+*/98/0,#'&##"!&F|��b\�í��������������YSilt~~������������������������mw�zn\�����qn�{f}�����������~zwz|���}����~������������Ͷ�����������jpnrrat]C;M<CUVSPWVSA;42<3)#,3/9:KWS04;M������eUB[bR866./.132/)48966606CZk{��������������������������������������������������������������������������������������������������������������fff`clihedja[`]YTTVTMOFFBJLUep�������������������������������}ugbWNPXW[`ckbgdlglnmjnnnkly�d9AI\�������{����u{q^REAHG:+*-22,0Q��qZD7Kk�y?6//,-21-Qu4NJ\a^8&3Sgoxgptq�ddyy�h)%',2.13D))+//.-.*,,0264-(%&#""#2k��nbi���������������ŚYQ_fnv|�������������������������w��{qn����{l���������������uy������~�������������Ϲ�����������oysywrylUA]OJP\WVQVUC667:3-(2>32;QMT4,6O������oZ:YbM=2;433561'/6>A2..64Eep���������������������������������������������������������������������������������������������������������������gghigkjd_bhc[YYVTVWVSRKJEHFTft���������������������������������ukeWLOWTU\\aegkmimpqrsnmonp��aoux���r|�����sOAJYTQZYI981'),/-%'<q���_Nj�kNPTI,6<))OqA;KTjhN+5\pebqy�uztw��o3$%2:3-*,1/43).30./,/4526-&'&#&Y���cfs��������������ĞYQQ`kn{�~����������������������������|~�����w����������������wz�����~���}�������������ӿ����������~|��}}vlRj_LRcbaY\RF:0:8/&$34,19OIR4+7O������v`8QfA9.69-,40*(.<=9560+/Pcz���������������������������������������������������������������������������������������������������������������ffjddeb`abb``]X]SSUSQLMIDBGRhp|��������������������������������qh\SOLRTVY^ae_fehlmoukljies��������������oUFGDCEEakS810(*,*3')56Dp��y���sgpvP*69#):gECEBlq\@1jjQRsw������y6()+.594*,4421.(.733.474,00'!  #<v��ncp��������������Ȣ]OS\cqvy�������������������������������������������������������z{��������}�������������õ��������������{}�~mVfgM]h_b[a[M?6?6-')32.3:>KO4+7N������{b<BeBB5)80*0'-+3DH=,)%.8Lb{���������������������������������������������������������������������������������������������������������������eegdcdd`_c]\]VZWURUYQMIF?CMTcoy��������������������������������viaRNIQQXY]`bchgjmlmiimkkcnw������������o_ELSL9@TeUQ5,.0%*=6+$757?g������{{sF461&)1XVND?bvkVFkWNG]susz��zt[E4@--)'+4.-+./0-.6,./+/*0'(+&!"(`���kg~�������������ʩ_JV]cmuu}����������������������������������������������������������������~��������������ȸ��������������}}�|scji^eheg]aYN=7@:-('45629;MG/.3H�������b?;\K5<,81292,04CC8)/,/2Pr��������������������������������������������������������������������������������������������������¾������������ddgecdde^^_^YYSSVRSQNMFG=;KTdp��������������������������������tgaUMPRT]b^_cchgojmmlmmkmilo����������wp`QMEBCCS`WPA;,$$(3P1.-?939S���}ryvw`M?18.(+3OMKF6@x|na]K@K@an_c��UU^_HZOK,+/,/213,'.18630/--,'#$%#$?y��sko�������������̶`GQ\_gnr{z|���������������������������������������������������������������|�|�������������ȼ���������������~||wsotlhmnmhfUQ@;D;/)*96-===HS365F�������_9:^A69,8:/83-12?;7.())BUs�������������������������������������������������������������������������������~��������������������������������hhcccb]a_][\YZWSQTTKMFA<66>L\p���������������������������������yh\QRUOS\\_]abfkhmmpmohmkolmx�������vtwoaH@?<CNjdYN62((&:=[;0;GC7O`cijsjk_eF;4'*,#(=>LIF56Nu�weKXa`haXX�j<?[^<K3500-),..-,+/)45//2*/2)%!%#0f��|dh{������������λp<NU^enpvxy��������������������������������������������������������������~�����������������ƾ����������������}zvnwpvrmibaS=:A55%-741:?8KS204F�������d@@^L/9*.910*-15:81,(3+Cdw������~����������������������������������������������������������������������~���������������������������������ddaeaY^[]ZYTQUQSSSRLMED<98DN`p|�������������������������������ug[WMQPZXXZ^aegibljnnlmmlmlnrr�����pmpxjU><9@SjgT9=?7)%./NW;8AW\XmeuMCJGAgiRI/,+$#586?VS4/2Nq�x}yvqJJln@@_�H&+10,,,-/-',1(+)067-32100&'(-G���iek���������������?ET`fqporx����������������������������������������������������������������~��}��������������������������������ztwqvurrj^UI>I94$-670@;?VL4,4?�������j=BW]./91<-*&(11;,-.)00Lf|���������������������������������������������������������������������������������������������������������������ff^`\[Y]\`TYUTQMPSTQIFF@=>AJXk|��������������������������������tgZZPKOR\]]adbgoippnlljrklmnuu���plhrolL?=JGP]o`B00<2++1=VRF<Ngktl|nF<14PmcU4&&*'2A-9=`ZF716G�����z`<=sKIt��,*(+1-2+/20,0.'0.12?00003+**,8k��obdu������������NJ@@MYajqquvw}���������������������������������������������������������������������������������»������������������zwrrsomncaU=>@88*373:@<<JB4*7@�������c9>SS,/5192/(,2464+,,*6Pk|����������������������������������������������������������������������������������������������������������������cc]`^Y[XW[YTPRPPRSNKFF=?=;BN\l}��������������������������������wga\OMUVU\[_e^hgkisnpqorlkr�tz�xpmltsgODYbx}yw]M93833*4/<]ZQE^wwng�dI45Ejw[G($#&/5-3NShqRB7*2g���|SB;CgSz��Z-/)-.3300341&++,(,15165245*.,P��gen������������̤@?GQ\_lptx{|�}��������������������������������������������������������������������������������½�������������������|z{xzsokgfZC=;96+5/29C<<IB4#-;�������l6;QH)&13D+*',566/,,,/>Xu�����������������������������������������������������������������������������������������������������������������aa^_^]X[^XUVWTOTUPQPEBD===IUZgy��������������������������������uiaWOMRSX]cad`fhfjnoilnpsmquyzo`ns��yoeq�����w\?889201/7Om`MPh�t_uj_?AGl�nR/&$&'02.9Obr�iUP=;HMOm�mT<\is��r;236342141376.+0,(/2/53-.11'':o��tli������������̰L9CKW_dppv|zy������������������������������������������������������������������������������ƹ������������������|}yy|rqkdTEA;<4)/24<;6=PI-#*:w������n@9EM(#263,5.07751+,-4Des�����������������������������������������������������������������������������������������������������������������[[Z\V^WZUSTVQVPLQINLGDA;<;EKXn{��������������������������������wl^VOOOQU[W[`agdkimpnmnoptsu|sglv�����������z_PD9=::A@<:QvdNGr�i{p[YTMg�u_A#"%(,*3+9<Qc{dUWVPEEcu{|w����~=@HJD@B>/,--63..,-(01,417,+2,)R��~igp�����������ɻY67EQRakpqoy~z�������������������������������������������������������������������z�z~������������Ƽ��������������������~|z{zrpnd\JA/84(-8?A1??RC2,*:|������u97JJ*%1A910*,431.01/=Umz�����������������������������������������������������������������������������������������������������������������XX]\\[W[TTVVURTNTINHB?;;;=BPXiv������������������������������oe]ZRPNPV]]__aeafjfkmmorru���������������vdMIG=?>CFFB9?`zWGRnyu{X\p_hys]K+(%))%)2-14:D[muTbllbXZN\�����vEDkc_RQUMB'%(434)&/+*)/--.+)(-Bw��najv������������z64=GKVgmrpux|{�������������������������������������������������������������������|�z������������ʿ��������������������~}y|vtlk]NG8<6325;71F:Y@)#&5y������wF4G<)%+B3+*,2891+-.+;[p�������������������������������������������������������������������������������������������������¾��������¾�����^^^]kd]YX\UVVTWOMLNLKBC>;:AO[gx�������������������������������~ph^PQOOWZZ]Zbaa]ddlnpu���������������zcRKLNXSA6789=CF>3IejTH[iyqSSbyr�vcE)(%)*'!+823.+5KTjeouz}pk_Vh���i@2_}�vfSVYS/'.26-,10+050+*,)'(-T��}fgp������¿���Ȑ403?LS__oruyxz{���������������������������������������������������������������~��|������������������������������������}�~{|vwrj[G99;0,18A75I;U70+'/t������yJ2A4""(C=-#09585/01*Eev�������������������������������������������������������������������������������������������������þ���������������ZZ\]gdVXTRVQSSSLJKIEFA?;99DMbl{��������������������������������tk^TONOUY\[[^cbfggks����������������M<D49I`W=89<>>?BFF:QmeVLVwrOQbu�ycV?/,*3),')(.*)/0>TPCFnu||vjM;51.2_���rca_J0-354/:--,00-+0)))&1o��pfov����������̨=*(6AKTZfqutuz}~�~�����������������������������������������������������������������}����������������¸�������������������}���zuuniWF:8=4-3@I6:E>V:+3+,g�������Q/D?/.*;9,(-393+.//4Siz������������������������������������������������������������������������������������������������������������������WWVXZXWUWSPULMSOMNKHJ??;56@Mat{~�������������������������������uh[PJNONRTYY[ahkhu����������z����~pC05.<QST>65<?C@D8:AERh^RO\�[Qm�~��\G<44595.-(+).*0.16<PO?Kjus��nL'$"()9c���}ujV>5/-.../-.0.-./10+,6S���srt}���������ϽX)$.4DMW_iowuwy|}~����������������������������������������������������������������������������������ĸ����������������������}w}qh_K9?<0+<;B>5CCU8,+)/_�������c9C6(**42,2689+0),/6Xo��������������������������������������������������������������������������������������������������¿���������������YYTSY_XTQPLNQ^MLMOHGIC?9;;CO\ky�������������������������������rfZVLOJTQVYZ]ggu������yu{}��|~�u`TG862B\[OL>B?A=9I=4?HVdXFS]vwco��~�u:5506661*/13.5,(0-24F^WA6??SjM/$$(12Ea���tgF78)./2.-+,-/*/3))*0:l��ssxu�����������|-!(-8GU`blow|{z~����������������������������������������������������������������������{������������Ƿ������������������~��~�x{ztiZF9@A1-/B<64OBW;4++1]�������k2:2+*.,6))2303**,+DZu�������������������������������������������������������������������������������������������������������������������TTUXSZWQPOROOUOMJGGDCH?<69?M]kz�������������������������������udYWORPRW\\^biky��xtuqjv�{u��s\_WLEKOJNZK:<=A96?:HQSnV<F`h�hx��v{sh@3--94..101*./-1/2718:^a;,,H]P1(&5Vcw��|oZFP:..&2*02*-./)'&(*2\��iyy����������͘5$&/2;ATaenrzw{||}|��������������������������������������������������������������������������������ǹ���������������������}|ykjV<4680/5B?64QLT4+)(,]�������x=/1'&$(.3*/98/***.Dct�������������������������������������������������������������������������������������������������������������������PPVPNTTQLPKLOQQPKIICF?<9=9>KZky�������������������������������~tl_ZOINSWVW``dlkwnmopsru���ygifj]i`_VUTZ[]?:BD5/:=CLbop=7JQr}|��vNH<XW/03?4/-1//+/-.3059)*-?X`>+A^@-&'"$/_bl��}kZf_70+#)+/,'&230&!*,<x��vm}v�ͳ������ѯB)'-967GWaimuxzx|z{zz������������������������������������������������������������������|���������������ȷ��������������������|�~�upbS<399.0:;728HVQ64*)-Q�������~B+6""*+/=3/43.)2,0Nj{�������������������������������������������������������������������������������������������������������������������WWVOTJOLNTIJMPOLJKJHB@<:;5>DXl{�������������������������������}ogaXJKPR[\\^aiinfelmopqp|��x\Z]NH[bYUYh_JQ=HO747BIUapsY6<GU����mb999Mi7165.00+000--)-975+5-H6QX;8YJ5+$',[fn���j{xT//835$*,*)2+'("$3_���swr��̱�������b('(,04DHU_httyyx|��y�����������������������������������������������������������������~����������������ɹ����������������������x}qnbR@;>:)0>445:G_M6-*'.L����|���S(/#&,*0K6571.1.+8Xn��������������������������������������������������������������������������������������������������������������������TTQMPRRMOMMGKMPHHMJEDBK88>EGYkz�������������������������������wg^WMOMZY[`]dcbnifonlnwt|�}nN][HHRUK^fcM@Z]PM42<EU_qvX<1<Ck��n^biAE?Gl2:81-*-*.:62121228-,4@119:0TR6)# )Vmk�����C13,(')*)%(1%* ":v��ptxu�̾������ʐ5#%,+.7EMYagusyu|}~��z����������������������������������������������������������������{�����������������˴����������������������}tg`L;9<7,4@442:F]H3''#/J����~���W)0(+*(4M:3663+.+BZt����������������������������������������������������������������������|���������������������������������������������PPRMNOMPNNOOHIGFIIIGB>9;;7=F]jy��������������������������������oh\XNKTOWT[bda`jjnolrorut}~jPQXTZPJfwq\B_fYD<;GXmuz]<18<Om�t[ftN5@mJ<:')-+5/77365.067.0,3H73532KW9'!,9Ofo��p���Y>'%$','#"&2%"")[��voos��ǻ�ƽ��ά:/+-5.26@OYelrquu{{��~����������������������������������������������������������������~|����������������ͷ�����������������������~zqh`E=;71(19845:HaK2*)',H��������a,-#+;)3<>33/-,*/Jby����������������������������������������������������������������������z���������������������������������������������SSTRLKGSHJKJKHHFI@AG@?=965CLXg}��������������������������������ui^RKIMQVYYY_jjheimmlqrsqurd@@Zwgh|�|^HG_�j`JGJ\lwkO;/+5;UPg��]YmkB>M:C;+*,,4>336371.3123-,H).-'1@[<(""1KYeq�mm���wX-%# #"%$#""!%9r��srpt�ƹ�������j20*-:-74<MYelquzxvx~������������������������������������������������������������������~}����������������Ϳ��������������������|}~yulUB9F7/,46131:M^I4))&*;��������n8,$(*&4AD7:3/-/3Ul�����������������������������������������������������������������������}���������������������������������������������PPKPIOFHJJQHCHKCDLDC<@@84;AHTft��������������������������������zi_SOOVRUW^]Z_biihijjqoqrtmU:Pz����yZ?C^cqbVEJdr�lF664:89;5X��l\^p<38A=52+6/3?/33,>3-4211=75,:A/00JD)%":A`fq{gZ���zE*"+/)"!")&"$*S��xstw{�Ÿ�����̗2)))5C,0<=KU_entyvxy�����������������������������������������������������������������|v����������������ӻ�����������������������wzqeSD>:4)'=12//3E]K.,)%+@y�������|;+)"$#1CC@-1835=Yu����������ƥ��������������������������������������������������������������������������������������������������������IINKLMGLILLPKKGGECEEB>:77<CEUgv��������������������������������vf\PIMZRY`[b`]behfkklnsrrqhRT����vZFCTmjqc?F]s�lL:99@8C273Gq�{^QzL2<<A:91331B9.,+520+.0%..+AXj3*$7C.*(+*QmrpaNZ����lD,(+&!&"# ((3q��iptw�Ǽ�����ѳD*#$(/>/4<COQchlpzz{{{~������������������������������������������������������������������{}y���������������Կ���������������������|~yzmaN<?1,)07/3159K_L0'&($5w��������H&0()$-A=:604.2Fbx���������������������������������������������������������������������������������������������������������������������NNLKIMMHQLKKLKKED@CD=96503?IUjy��������������������������������te]RLIINYYispb`ecfjioknoopvu����r`AKFPp}ikF;^|^;:79IN8R512@]�~kM�b828F<:6970E63/-/2.)/1/(+,Fk_1%$/E5*.(2Mpp{rVJu����pI-&!"%($*+*M��ydp{}�̼������u5)"&'?C1/6=GQdhlpwyy�����������������������������������������������������������������~�~}�|����������������ê���������������������~xwn_Q=?*(03:.59>>LXG1'&(%9s��������W7=#!&47?:/6215Lf~���������������������������������������������������������������������������������������������������������������������JJLPRNMKLLPMNRHFJGIC;@<652:GXhw��������������������������������tlYOPDOTP[t��d_dbjlgkgnz������tTH/@JXp��jQAV��X<467<fJ>VI>7Lr��tX��E(3A:B<@53I94-27+,)+*3'&/LIU2(.3=9---=`ov��hOO�y���n2!."&++('0`��mdpy��������ԧ/"%%(/9H76<GQS^enmwtz�~��~���������������������������������������������������������������z}||���������������Ȫ���������������������vwkZF<6010753>89AO]G*!$"$1l��������d4C$1(.;4<,-(*<\w���������������������������������������������������������������������������������������þ�����������������������������OOLKGGKGGJLJOIEGBCCB>>5374=HXkx�������������������������������viUUFHJMP\y�h_a`iigr{������aD:;61FSn��zW?]}�`9.,.5`uHHW68:r���Sl�Y=87874<:0@C1*).'(3+*:(&&?GDAGF>92*5<Qaf���rT9V_����Q)##(% ($;z��moo����������\' &#$%@N918?OT[belpox|}~�������������������������������������������������������������~{��y{}���������������̮�����������������~��xyjWC=43*16:2>97:LaP/(%%&3g�������h=7 #-8?5871,,=^z����������������������������������������������������������������������������������������������������������������������TTNQHOLKLLQIHKJMEA@B;92410@I]lw�������������������������������vn^PKMMKL_}�t]Z^]ijw�������nE*.7:5Qk���vIQ||[183/+;tnIMV75V�����\Z�p2546:7R>8C7,+%.&'*%)0(**ASMLCGM:.8HN[\y����a=5St���i& $# &[��|nkt��������ɋ1"''$+&DU8/59LVZefoqsv~x�����������������������������������������������������������������{zx{|���������������е��������������������zwbPB70)(-776D95?KWX0%&$,,b����}���oL5)$/88951.'0Nh|�����������������������������������������������������������������������������������¿���������������������������������PPJGLNHRPQMJIGFCFD@GA:7103@J_ix��������������������������������seYKJGOEQ\��{`a]dt������w�xeA',91@o|���b`yyH>2<<-4Q{dDi[2:`��u~�`D{�K33<6<I>3;>.,&&)'(%*0,1>Q[\PMUO2-HbWPc�����uH3Cb~�`&$$;��unp~�������̥?&###!!+AW<74<EP[delptv|y������������������������������������������������������������������|wx}{~��������������ֻ��������������������~ywp`LB6)'*192>F:=ALVY-&)(/2^����{���uP. ,:742,-(@Wl�����������������������������������������������������������������������������������¿���¾�����������������������������SSLPMNNLOPOLMPLEA>E>:83/0,:MVex��������������������������������wcXNJIIHMVs��o\ex�����oq|��X1*76=`~���SRzyH<?8>917cp]N�jALx�yds�rAn�b8<C?=L53:<,(%'& !!,6DI`lfVTLI0-S_Kc�������O)4Qf�wX$&Y��qooq�������εF'!!#*%#)GV?:8<EUUiflpvw}}����������������������������������������������������������������}�~{xz~{~��������������ĝ��������������������~ug^JI4)5,3537K@DOGV^-(('(5U���������T)#(:912.'%<]r����������������������������������������������������������������������������������������������������������������������KKSNKNJPPUHRNJHBC?C>B<5763<FRex~�������������������������������seWPFLPIKVe��ol����vjp���pS63?Hl�|}~]<cxSC<@C45B[ibHf�T;N��ufu�xFY�y=<>29>83;70)"'*%%$)6,:Co�{fVC;30NWf{�������^)3=\�vF$#7p��m~vu��������d(!#%&!'.KUD5:DJQVhikpo{~}}�������������������������������������������������������������}~�|xz{|{}��������������ʟ�������������������~zofZF:,(+-11-7C>DNCNX/)!"3I��������T) *80(,,,2Iex����������������������������������������������������������������������������������������������������������������������OOOLLOKIIQIGJJGEGA=?;:82,.5@Ug}�������������������������������~ubYRGEGJLL]l������wnsn|�ztW<:GOz�wqiCNk[Qgd|A26Tk\KMy�L:W�uucv��X[��J88).:85790(%#))%(=H48>]r�oO>8:AFfv{xv�����h,&2LsM& !%P��yoyvx������Ή1%&%'!#)')I\H5<EIMZbflrtu��}{���~���������������������������������������������������������{|}yxxz{|}��������������Ψ�������������������}vlgWD1((+,90,;CDAMHFZ4%$"#5H{��������W+%-;+).0*0Qd�����������������������������������������������������������������������������������������������������������������������PPQNOQJIKLLJFGGCD?A>6761,)3AZey��������������������������������rfYPIKRIIQX]n����uneikkr|tudG7C=n�lqQAiaZJKaV5?H`b[QqhK:c�nfly��\D]�I&-)*99A7;/-&),*%(08/D;@TkjO9;MqenuzgO�����y<#.=N5# /k��sptv������Σ8%$&)%&'"$%MfN:BGEKWaglqqy~�z~�����������������������������������������������������������}��||{y{y|}��������������ү������������������~ytkcUC.,*0742.?A?=NDRT-'"&4Lq��������^+"$77,)4.59Xr������������������������������������������������������������������������������������������������������������������������QQVPWNKFOKEEKGLICCC5722/0/0<Shw}������������������������������~rhWPJKFFOMZ\hoqx~vwztpr}��~eH454cvniOLcTWT^K39VYYXM]�xdT=[yaYp{��_:D{S!*(*.(209/+.(,#")6/5ZIFPX_S<Jj�porVAR����m5#%28/,""D��{qvs�����йI&#*&(,$$%"(S`T<AJKT]agjquwyw������������������������������������������������������~�~|����~|{yuv���������������ѻ������������������zvd^K9+(+-+444=I?>JILQ3'"!"1Ln��������m,&#/0'*(.;<_q������������������������������������������������������������������������������������������������������������������������OOPNTNMMLNFIJGKCDEA73443*+.DPgw�������������������������������~reVQIKPMPPSZ[]_dkv|{������{XG48Hnhg]Iah^Xi^:8OlcSIFv�T]_D^|\Op���j:5vn%$&*0-.0:31+1.-*9223e^gLK[JG[z��punZB;=ZOBD.*$):2!#0!,(\��uxxy����ʿ�/""'+)"(''(0VdZA7HESW\`fquww}������������������������������������������������������}|z{|{����}{}~yuz~��������������Ҽ�������������������}mdVF0'+)0-52BEBIEGHFK67#! 2F\��������r57--.(&-,LDc|����������������������������������������������������������������������������������¿������������������������������������TTQQPJJMMJNHOINCB>?<9503.$1EWes~������������������������������vf^UMKIKSSU\\]gl|�kku����zuX?:>H_VSMWdl`_fB9Y`bUJ@Kz�FFN>\qSFh���l?2b�6$'///4++,51/930//*1SgH?EOGRc��vacYC2DY_G;2*%1,7/!.OKm�vr�{~���ʫ��<("%'+'&,%%,Yj]=BGMRYXejmutv{~}����������������������������������������������������|wry}�������~{|z|{~���������������������������������~~ngQ5)')+/,3,-:CADRACEF.(#"/EY���������D,)/+'#$/ENh���������������������������������������������������������������������������������ÿ�������������������������������������PPOOPMOSRMQPRJJM@>@873.5)'.>Nax������������������������������~vnZOHEIKMQX_aiu�xkhmrz{|wg9:LVc\Z=Detse\@=Sh]MCC;d�o:/2AgtW=f���rF5F�S'(&1A.&/*I><0,%(#*,:b4.SOO`y��wcQHBGo�sO:/(##0/+#(Qeg~�jnrr���æ��}4$##)%"*%)*\l\A8GHOV]ghlsuuy}���������������������������������������������������|yurv|���������y{{����������������Ɩ���������������~~yqsdJ1,,(.-57.0;DCOSBIB9.""$3;T���������_75)'#(#-JYt�������������������������������������������������������������������������������������������������������������������������RRNLMNOOOMQIKNEIA:;6650+*$2<Tavz������������������������������}vi\NIDBJSV[h~}zljmknstrmU6CGUVXV2GkxbL?X\OFD@?G~�Y33=Nq~V;c����M9<�m+$'*2-+8LM@*'$$&796W87qrBP�����qhbgmh[C1%$$$2&""Lx�xzzgell��������ZE-#"+%+(("#.ZmZC@KNQS__jtqvv}}|�}�����������������������������������������������wrns|������������|}���������������Ñ���������������}~vsk]=1,-'*291+/D?FIKFGG15"##/0G���������](=*!"-++Qhw�������������������������������������������������������������������������������������������������������������������������TTWQTQNPQKPLGGCCA;?;<9/0,'0=Naw~������������������������������~zk[PGGFLWaw}���phhjllxtvreJENLI\b\=]s{yOEMZQBMH;9d�zL/(6Xw�_:T����T18g�?+/*05<JD<6++/!"%HN=YZl��XFT^m����_K=E3/('"%0,!"%G������vkmdv������n7)%&##'.$/F%.Wq[NFCDNYWckvrwz{�~|������������������������������������������������}tkmt}��������������}}��������������’���������������|}urgL1.))01-74/8CBHNLAMC56$#!1/>���������_3<7%""'/Xq~��������������������������������������������������������������������������������¿���������������������������������������VVUUQTPPPQPMKJG@A??965/.+'.@Pfy������������������������������~zeXOKBJS_q����ijcknkkquwngOCJ=?\^HRxt�nBP]]JARI/8x�]M2&7Tn�b>I���U20P�F+219HL64.+&79$ #58AOh���i@5@PYgqe?3*/)'!'$&1' !*x���������uw������e1$$$(&2'#'(%,]qcYCEJL\Zimotx{�x}�������������������������������������������������~xhpv}�������������|y|~������������Կ����������������z|zr[?.$))&&0-308?<@JHIM;/9*""3)7v��������kA22#"'$.[u~������������������������������������������������������������������������������������ÿ�����������������������������������TTXVUOPOQIKMKIHKIG?A=;,1)(4DTiw~������������������������������tkZTMV`n���te`iikhsvxusq]DOFH;[ZTnyuwULZOD=HCR0F��QK.,2Mt�cH@f���`25;�f.2?JGD1/(-:I=#%))0:G@kRO<+)5<L^tnQ1.% "!%(&;�����������������]A&! &5(/(*)(4[jgZGD=SX_iprtvv�{�������������������������������������������������ukrx}�������������~xwz~�����������Ϸ��������������~~~phO:-'*.,(522.8@ADE@JK>.5.%)804r�������~oP3+##&4T������������������������������������������������������������������~��������������������������������������������������������XXVSSMMWPJKQKHHADBB@?>-,++:MXiu�������������������������������wqb[Ymyog_^bdeglquxzwjXEL=<B[``ogymVWOHD619L@d�iN?3-/9k�eJAR���j9.>��B1-9?7+0+2;PC* !(*6J78//,((*2?i�rpG-'$$'".* b����������������wO7)$&&',)11/&'2Xi[V>:GUZ`entsv}|�}�������������������������������������������������tlt|}�������������~wwvz�����������˧���������������~~xoYD1)**,))69325@=HR=FP=-20)&4(*g�������xrP2.+%%%>]��������������������������������������������������������������������������������������������������������������������������ZZQOSMP\RMSRGHMIBDA<>?;1-,:KXe{�������������������������������}nbei`gd\]Z]_^aedekox}v{dWSJ25J]cibhzkjXLAK/%3Ql��ZS=B.*6a~mRIUv���C75~�_1).4,.0.3:_H% '++:LA?9+(%*3CKqbOG3))''&&,) !%����������������{L-)& """0-+&()%4`od\FMLU\]fmtoyz}�|}�}�����������������������������������������������qlq������wpu~���~zzyy����������ͺ����������������|yvhI1,*(,,--05236;:HG:=L=(06*#1*,W��������vV)$/"!)Be���������������������������������������������������������������������������������������������������������������������������WW[PPOTLQONKMPNED?BB;98631;O\jw��������������������������������ymihZSKOPXR[Z__fbdimvu}�\]PHB?MWe__n�weRLD@"$8X��naQ=R5.3W�n^WVs���\@7m�s8*21-3M<93\M' $'3,8?J=3+/3T��sD(&$'+%+,*% 7���������������[<5'%!""&)-//%')%.^nX[GPLV]bejwsyw}|z}��~�����������������������������������������������tx�����xV:89IYfrsw~y{y~��������̿���������������~~{r]:3(,&//--7;83>CAML7@N<0040$*(&X��������{`1(3(,/Um������������������������������������������������������������������}��������������������������������������������������������MMSPQNNSSIQHHMJFDBC;DA9:/5@Tbo}��������������������������������}qiaRDOLOTV^Z`bjihkkotrj]MNTK@UeYQfz�}cVPO5&$6g��]X;@^>+9Ryl]cXl���k4.Q�~;).116HMB=O=%##(!!)/;OB05g��~4#%"&+*.,,&%"!X�����Ĵ�������t0)*#!&&%%&,8.*.++-Wjb_KIQ`^`bkpquyxzz{���������������������������������������������������wy�����eA212@MY`Zcquz~y{������ǭ�����������������{vjK1+(.2.-(09654<CEPF6CQ=0232-,&(J��������y_6%/7':a{���������������������������������������������������������������������������������������������������������������������������SSROUNSGJQNTPTIGE@C@C>987=CWgu��������������������������������qeYJKINNW]][]aggjgpnqokO<RZR:\^UTm��w\NL>' 1;}�pR?3MoB-IGvn\cYs���{A5I��>$+7':CeY3G<.$##%!#'-0H_MBc��v=).**-+12+" "/������ŷ������e4#!((*%%&+*424/,''.ZmpiGOU\bdfintsy|y�}}�������������������������������������������������{uz����iWF;GQa]\WUY]rvv|~�����ƽ������������������|w`9-1/0,.+.-94/4;CFK@@IR932045*&$>{����|}�~`6#(@1Bdz���������������������������������������������������������������������������������������������������������������������������NNUJPIPMLQJOQNIJGAD>@GF=<@LYhx}��������������������������������|oaTLHDNSQTZ[b`cbgipmookTIb`N=]^^Tn~{fYNH+#'/g��hA5<goF.NBmt]UZz}���T0A��P%%1$+CE@2G?G<&!#$#%$),FVOu�{V7,.24485'& "#Q������¹���Ƽ�<#%#'()'''++/-.//)$)_kpfMNS_fcjlpoxuxzz}}~�������������������������������������������������|wz~��xsle`fmxtoi`dWaqwx{�������������������������~lT013+,/1+.,<307>GFS:6ET>1/-8<%$!;u�����}��^=*'7HJp����������������������������������������������������������������������������������������������������������������������������OOURQNNNNMPOMNJGAEKHEE?BBER[my���������������������������������{lYWNKMSUT`\ZaegfolonstmNJfdIA_\URNOmZHPH&#8W��qmA4HjnS20KtxddXyyv��g=D��_! ,##-217Xdv_11(*(# "(1Yg�T6,)4??83-$-.,;Fi��������������)%&'$*/+,4.,./2(1,10`nmdMNPcefluwquv}}x~����������������������������������������������������{tx}��|~��}wongbmyxz~������������������������sb@0/1178+(-*B23<9FHU<9CMF0-.7A()"2e�����}��kH0")NWt����������������������������������������������������������������������������������������������������������������������������NNWPOMNPOMOOKFFIJEDFHCDGBDS`o}���������������������������������yl]VKHFPTY\a`gaeiknoxyyqSW`UB=cZROBPbP;=1-'F��vbUM;VacP=2=x�nbRpus��xFOp�k"!'*2)/m��{C0,(%!$ "+W�zU2)& 2B31N=;USL^dpp{����������_7'& #(.8<,1/+*+1&//*1ctshRJP^flhtoquw�~�{{|��������������������������������������������������~{z~|���������~wwvtpxv~������������������������vmZ403-0831+*0@75@9JMUB@IMC2+,78+%#-^�����z��[S+&.Od{����������������������������������������������������������������������������������������������������������������������������NNQOJHRPNHJEJHLGDBABCJCMLKVfp}���������������������������������zodWOIKPOT]V]bddhenz~rqeXbS:9>U]WV>NVE4+#+Kq�ujND]HYWRJC5Du�iKFe{q���YX{�2!',76'0o���LP5$&#$2p|mM,/#"J[DMei^em`o~mmz��z�����c1'##$&*;RKKFE,,--'3;4,Wqyh]SQ\aikpwvtv~~~{~�����������������������������������������������������}zz��������|twvz���������������������������xi?/,/4.94,/3-=3;98N^NA9PRD2-,;1('$+O�����{��eY;''Pp�����������������������������������������������������������������������������������������������������������������������������OOTRTLRMQHKNONLGA@?FGKGJNRZfu���������������������������������{m^TLGGRSW[]^c]cekvzyuwgZQ.55>UaXVBLFB1%$7h�ziH?>\UUDOGX=>j|`XTc�qc��oc~��O# *=6*/r���wq/&Wy^F^O(#(Jb`diuosv���ajtklos���ϝ-)%,#)*2:CNZ451*'0#*+/5c}uccORYipqoquxxz}z�������������������������������������������������������}��������vy����������������������������xvU6,/-+20*2-/1;37<<I\`H>JE@6--<-+.",I�����|��bb7+(Sy�����������������������������������������������������������������������������������������������������������������������������JJOORNSKKGTNTLJMEC@EHLLKSRYhz}���������������������������������xp`ROLIMTVZ^[b``eiuwpsvlaD+)'2NaXZHM<<0%4\y_H20@Hc]CGQjCHnoaVVw�jT��zb���c1#$,>.*0i����}79xa56UF03EZ]lmhw~����rdufclr�����R%&*'$&)-18=A4010/1'%)&.gvy^dKU[gjstsuvt{y}~}���|������������������������������������������������������������������������½������������������~xl>4/1//41+.,24>7:?;SXMOKSDG:61B*1+"%?�����x��Uc=/0W}������������������������������������������������������������������}����������������������������������������������������������QQQQNHHNIGMQOMKJCGFICGHMTU]lx����������������������������������xl^VSKHRRWW[[d^_ekotrr{�tG)-$+PVQMEE=9-.Y��c@9/2>GTV>=\yP[~sd]czzfJg��e���y6)$&28,0W�����9)!#)Xb6(;;JSSdcbfnt������`dj^eu}����w0)*).+/*223-FA446132)*-1dwyWfNW[`nmsszyy|}|~z���~}�����������������������������������������������������������������������¿������������������vV1210.)0403*03<;><E_]EBERCA:5=M-.1))@w����s��WeF.=c������������������������������������������������������������������������������������������������������������������������������LLMPKJIDUROQQPMIELHDDGJQV\bl{����������������������������������yp^ZJKPLXWZcV_]ddegjqy���Z*&(3M[W@BFA?,N��oP3,+1=QMT@?PvVp}gikpzhTIU��p����Y2.)4@.6Or�{rgH7$(/CW>/5MJbkdprmow������[cp_jw}���ԡ:2.-48652:9>@>:839451/118`w�^gQT\emmruxyyy{}|}{x}��������������������������������������������������������������������������¿�������������������tI62503*//+216+8A?8B]bD>P\M<70>L)/.&"6p����m��T`J:Jd������������������������������������������������������������������������������������������������������������������������������RRSVPPPSSPRTPNMIGFHCAAFMT^ck{�����������������������������������pbVNJOPRTW\Z\_bfigpx����Q7*,0IWSG>OHJFx�pXD85,.>GMML?R[\kqcgsl}nWBP��kp���qH.)/@46Kj�{dI-;%/DG4#!+6W|~vpy��������eXojct����кK/.0004411-543A686622/,,04\ss_iUTdaiqpvw{}�z�|�������������������������������������������������������������������������½·����������������}x`;14451/1.*+-14BI;7?c^J;GYD9A6AB-6)("1h����o��Q^T?\k������������������������������������������������������������������������������������������������������������������������������RRNMKGFLQSSKNDHKEHB;>@FMWbcn{����������������������������������}lcUPJNLUW]b`baakhnv����rV?15:Lc\MFSPan�~\=<5255AJJVNEFM\gohZrn~viJJ��k]��YK>@?MLGljopD8C<IN:+*(18S���~���������Q`cYbv�����t85766A@>7738:4=?864,.2'-,2Zop]nVV`djptvx{x}�z��~����������������������������������������������������������������Ż�����������������������������uB120453/615/344DH=5E_]IAFXE??9F?5<,(#/X����|��QY\Dgt������������������������������������������������������������������������������������������������������������������������������NNRMDGHOMINQKJIIFDC9<<EKWbgp}����������������������������������}kgRNLHHRYSY__abghs����pbV8,;9C^L:F[qu��aB;B.-103@@CH?DCS`]PEeqmwrLGs�yV|�~|fQ?HL]PFV[TfIJA9AF+# .4Iw������������\NiUQZi����~9'%,+*1288;9@>CBLABB<::/9::\rtgpb]ckkorx{�}��������������������������������������������������������������������������������������������������{\7/0102023///.49SG;5R`V@;FLH::>A73:,..0N�������Y\dMp{������������������������������������������������������������������������������������������������������������������������������LLLJEFHKJKGJNKKJEA?;==BISUes�����������������������������������|maXNNMLRXWY\^b_aj����rlfV@2;=LX@Bbu�~rb479,-1/08KFBKLG<R_SHCWw\nsVQL��[n��zuUDCV`^W`b^^N>2.>B+%$4J{�������������S\jYZbe��Ǒ7,1&,2(41.13.-171A=<;.2/,+(&JponffTallqqpvzy�z}~}~y~��������������������������������������������������������������������������ſ���������������~uB6.6213-,0+-0.28LD;8R[TH<IPD@9?D5/2''"0Cw������WWpWj}������������������������������������������������������������������������������������������������������������������������������FFLKJFIMJFFNMGJK?B>;<BHNQ\gt�����������������������������������xq_WQIISPMTV]``\hs���up|gQCQC9OSHa|��YF?4DG01@201JK:YKBAKSFRC_|fh[WWGe�o_��zxa>?WipaVOKSJ+$$7G3(/@T�������������_XbZX_av�Ȫ?($$)41-,,154028<=L@=C:32,00-KwinaiQ^aisrst}z|�}��������������������������������������������������������������������ǻ���������º���������������xg5.*2142-110+0-1?EC79XYUF<JPL6@BC4-+)$ ,=x�����YPrgt�������������������������������������������������������������������������������������������������������������������������������NNODFGMHFHGMNJIFCC=<9@EKY`fp�����������������������������������ylfZKFFJKS^W`]dgt���sjwziN38A@RJXv��g0.37FD25<257OE8KR?=IZNGK\`wlNEQPY��i��x�g:6Jt~lNG9?E%&=7DLXp���������ž��Tl_Z[Yp���[,'$+-24.0),23+-132KC960142('0Lt`jgoV^cjnpsxzww�~~����|�������������������������������������������������������������ȼ���������÷���������������wG-011.712151-/4:@CF<>UOXH<@XH5GC;/3/"(#,;s���~��bJknu�������������������������������������������������������������������������������������������������������������������������������HHLKFHJLKFCIJJD?=AD>B@ELT[ds}����������������������������������zoc\HCMKMSVR\Z_i���rkp|x`>6DB8RTgy�|M%++-[d5<E808IF5F_A=BNSBLWM|p7@K_f��ry�yI2J��bB<,/2<-('6F[Zgy~��������þ�[]m`Y]f|��n/*$(+*+=@03011*.6>/ND><1-6/'&*Fleh\wX[ceopqrvy}{~������������������������������������������������������������������������������¾���������������}h7.../-.02/4--*06AHB9JPZQHB@PC9BE9511*,$/>p���}w�fNo{w�����������������������������������������������������������������}�������������������������������������������������������������IIFIHIGCGGC@CDECB=F=CBGNOXbq}����������������������������������yp_TOFHNMU_UWWfx��togw�ve;CC<E^nk{�q=(035;^<RE=9>IB;7]SA>EMFHARyq;2LXt��o�||�e7j��S/8,(,?K24DWfmejt~���������e][VYZ_r�•:*&*-84/6D82.353,4=8JA=B-.40,)*Acdg_{YQ^ivnmwwx}~����������������������������������������������������������������������ű������������������������~N/.7-1.,8/-72/,3<EC87SR[KGCEP?6GC2A14','&Fn����p�fOv���������������������������������������������������������������������������������������������������������������������������������JJEJGGHK@JDFGHIEIAB>>HMPKU_px|���������������������������������zo`VJHDPPRRR]]x��qplk{�v_4=B@Womp|~h6)0:;5<TTHCD@PA51T`KJ8IOD?PguT4ICQ{�{{ium�zU���:$1<(!+AY]ce`lagx�������ƻvWec[ZYp���>(,)$*7604877+2;02/A5DLMB67/.0+'Biad`zdJ\bimuuu||~z��~�������������������������������������������������������������������������Ļ���������������p>4-.+2.0210.+5843>A>GKPQQMDKJ8/E96?23*+()?p����t�hIt��������������������������������������������������������������������������������������������������������������������������������MMJDFJ@HFDHFDCCEA<>>BCNNQS]pw}���������������������������������{sbTHEENSWUY]n���fgfn��wX4<DSeh_mzxX:,7;42?YN>ELGFF=<AaLNFAKDBH^heC935Ps��ukoz�~��}/!+@+ &Rtrki^`_o����������Sb`WW]f���@))$(&-BR83929//859/:7CKQ?;8/-&+(>jffZqeS\bgjsov�}|��{�}��~��������������������������������������������������������������Ͼ�������������������������M5)-./.,:8321--2C7?<;CHPLNFBID99C9;:,0*'''7n����p�uEq���������������������������������������������������������������������������������������������������������������������������������CCFADB?KBHGFCHEA=?A=GHDJN[^h|����������������������������������~mbSEEGMJSQXk���lkhfo�|uV4LVZJFOxhbE-76<08FF?;EPF<DOMFUXLC:>DGFT_^c:.0>Ru��wq|����;')1Gh|��~qmit���������VZrVXcfv��r*&($&(7MQA410/(+80724:GHHGA0.2&,(5eg_]o_LQ[agxptyyy}�{��������������������������������������������������������������������������������������������{=,)/+.4-9D424,.074=@FLJQLVCALLABB?G900,&'&/k{���u�}Kt��������������������������������������������������������������������}������������������������������������������������������������JJA<;??F?EAHEIJBCC@?EFCGOT\i{����������������������������������}shQJGHJORU`~��madgep�wkT;JXD49T|hVD*7<54IQB9?>SE<@QaNJ\KNB;GIMSQUq^?-3;X���nz���['%#2Vl��������~������ĴiZlfZckx���9(1+,&*@UcF7:34+,?/3+54BBSQH12),*(8`Zb^od\ZZdgwpqwy�}�����������������������������������������������������������������������˾�������������������{X>/*0(,.56K41//2973>EEHKSOREAJLEKF;G>0-$$'&*^{���x�~N}�������������������������������������������������������������������}�������������������������������������������������������������GGB<?A<@AFKKIBBA>B>@?DIFSV^hv����������������������������������|neSEGJFLNXt��o^`ddip{wkJ9GC5'4kxhX:27C2?MHB>9<\J?TQkgJ^]SRHKKRNHL\qT883K`wysw���k3*+*(Cbx�����������ȿ�ķwP^qW\lt���E-0.(&**B_kL2030'*:5765ADDVOM/*,.**;[jWWfgTN\^aorsyv}|}�����������������������������������������������������������������������������������}~�������z>0.+0/+2569//01/826EF>HIUPZHBGXRCA;JE//$(&%)T���u}�]}���������������������������������������������������������������������������������������������������������������������������������FF=;;?><DE?FDKCCDB@BAFDMSU_j~����������������������������������{mdRKJJKOVg��vb^_^eeq��iPA=9((<rw}nF:9D3<>GC<87ME@?AbvVS`_UVMPPPF@HmtSA;:BUXWm����^+'Ssbel�����Ž��ʿƳW_m[R]r���u*((-%&**@_qR5+-3**;5586>>GHGD4.5,'+9TgOXib[HV_dlqsz}|{�����~����������������������������������������������������������������������������~u{~������Y012+3105:3612435:3>@JE;?TLZHDFQPCA;FH7-&&%%.B~���sw�c~������������������������������������������������������������������}�������������������������������������������������������������FF=><;9CA=EB@FCDFC:9?AMOIRYn}���������������������������������~yn`OPEEIP[v��l_[\acit��mE5/*(0Wl^�j<01B8:?DC8937@FC@_`Sahg_VUXJPDB[wmK429J`[f��}�~U4*:p�g]o����������Ļ�T\igZ[d|�Ǒ/%&(&*-'7KbI,+,5,'48585DJQFHL7//-*,=`pOXd]THTX^jqps{{~����������������������������������~~������������������������|������������������qfhv������x:0-3*.2+131/804618.9GKD>FUGXLIPZBA>7<H3-$&,,1@{���ro�f��������������������������������������������������������������������~~������������������������������������������������������������??@<<6;??;>>DHBH@@:<;BHKOU[hz����������������������������������zn^TIGBPSl��o[ZY^gjr���eC34.)2^S2jkM45H>AABC3;;499<Ab~uT[ldcaUPGIEBDWzmQ?<Mn`ds�ta||hZb���uu���������ɽ�X_jnYYdw���B("& *,)-(/CTI.1,.0(55/<<F<M=HN<))+..0_wN[]bRGS\cfolsty�����}~~����������������������|siilwx}�������������|}zz�|�xv|wry������remqyztc\ahv������[451/+/-096/0-60-8716QQ98BYAUCNQY=C44DEC.(",(+?p���wk�q�������������������������������������������������������������������{~������������������������������������������������������������5557=;7;<7=ABBDA=????FHKMT[hu����������������������������������ynbN@DDVi��xeWW^]er����`B5+-3H]5)CWIA=>9;AQOC96217?Ii�}eadidjcPPPI@>H]{oWHbpXQ\wyaUWt�����vv�����������eVjugZak���|-)/0+-4/-&%=QN0&*12/.12<>D4GBJSF,+,*/2VzERWkNMJYaclowuxy�����{}�|���������������������u^FGOYemorzy|}�xywu{upsnqrokkjqoopt~|}���rXMCW^ainidls������|D-.1-+/.576-1/2-3:19>II3=GU=O?ISR@H439EC3.!'()7f���l�|��������������������������������������������������������������������������������������������������������������������������������9997:@<??;A@JAA@<<;;EGMKSY`k~����������������������������������zn`RHFHl���i[VVX_q����|_E</9<bU7(6DC<;@C7HNR@>>12=6Mn��{gnl\gif[LMN?>MXzxcy{O:Gas`J:_����}s�����������zM`olb]d��ʮ<$'012292&$,6JN=0),5,*2.:9A1DBLOK,*''-6Tp>KXlWMESYfkpvvyx�����~~�~����������������������r\WTVMIHMU\ahhkkkjqosga_]_Z[TQX[\dgpvvx}ztc]ZT[bcntpps}������a5*60-%1.5=3.531.6<6:FKN7HOS>LEQTRG@-/?UG<1$),+6b����w���������������������������������������������������������������������|�������������������������������������������������������������;;6=675A?BBFBD?>@@A@>KOOQabr|����������������������������������tn]VLCY���l]PVT]g}����wZ<54@YVD.$)1/6@NM4CLU16H8;95Hu��ljfYgosfW^UC:@M]{��}IF>]LAA@So{zxwz�����������WWhrZbev�Ż`&&(0,021.,*.3>IG0'*+1,558:?7B?LRN/%&*(2Rm>QRcXKIQ^fkiwxyy���{�{}���������������������uldndbYZSRWTRV]Z]dblpjhgf`c`WYYa_fopswuu{tlonhdlt��~x|������w@-+-0-1.2472,**/4;22@KB=1;SW@PHOQO=:,+:XN@1'.1,5Y����~���������������������������������������������������������������������z�������������������������������������������������������������::76595<<:@?E>@@@<?A>GQPT[dq{����������������������������������wp_QLU|��t^XQTZZt�����tX@.7QO<@/0(+9>LNY6DOH64X?<87Cu�r�o`dZ^hdfpjbXMQMXh��zA76NF.9D[u�������������ȹ�M]iVX_w��ń2-1,,73.2+)*+09ID4-68-0558:@55>JPS9*+/(4UgBRSbYSMS]Yeiszy~~}��}|~}���������������������y{x}|tnkb^_^a`jkhqqssnpqnlpjlklpmkpsz~�����}xx������������T4*.2,+-123;.+-+,/814GJA96=WMHP?JSRD;,27OP>2$&1*2Q|���|�����������������������������������������������������������������������������������������������������������������������������������33:96>:;?==BEGB?A>@CAJYYWZfoz����������������������������������xqYUZu��qbVNSR\e����{oT=/>T:8?82&+C<<9:;GXG47YU?=<=|���ncddcc^Yhvmjc\U^m}�wVJFBR8ISo�������|�����μ�l]j_Ucu��ǟ<,)0+20.40,2()15C><-+0*4=6:8<?8?BGP>++3/2Rp9QWVVIMN[`efpqvyx|y�zyz~�~�������������������������}�~|stolnnruruz~||�~���~}{��~�������������������������u80-//4.207;4/./123<:9GH878D[HLILKSUI918>]a?/*,/+4Qy���y���������������������������������������������������������������������{��������������������������������������������������������������666:78;;;@:;B>B><=9BDJ\[_Ujv|����������������������������������ti\d}��{\QMOV[_r���zz{g]E6IG;AE7*,:8/8;.5@VE8;Jf:92:����lLOc_d]aXebkoia_eT\Slf<=cHfh�������{�������|Yio[_s��ǷU(*/1:3472/-,%*;9B;>.)013=9@8A@2;EJPB,,(,4MgBJQYVLOPVbbeqsuxx~{�zz{|~~�~�����������������������}|�{xx{xz}����������������������������������������}L2,*.2-01-8<-.1.2/3<=>N?3:9F`JEKRISUNE02;Ma=212.)0Mk���|��������������������������������������������������������������������{|�������������������������������������������������������������885<?:=4>9==@>?;=<;IIOWS_^gs����������������������������������vok����ePMPQUWm��{vvud]K?EB6KQ<.89-#4/.1@aM74FbB81?����oO9TUafifmbb_UXaV>;@iyT:d]zz��������u|���̬�_]nfeo����}91-30796555-1''4B8<82+-03<@<@:B6:<FNE02117V^ACJSTPPSObcfptsvsx|~z{{{z����������������������~||~}��~|{vzz�����������������������Ŵ���������������e;-.,2.4+63026/0.+-3=38B488<K[KCOGKXLAC;79Q_E4%(0.2Sj������������������������������������������������������������������������|}}�������������������������������������������������������������99;8?99<;?=<CG?F=:8ECNUR_^cmy���������������������������������~yx����_MLKTRV\p���pqurbcTDE>>TdK<C3*'4,*/EcL<=:a]/5=����hJ9;K_mnilk\QMUdV<;=RssTtpx�{������{qy��ӹ�l^jgnz�����A4,62-47480.,'*&.2:688*+,32A@26B<8;BI>1*-2:M]J>VTNSLHMX`akssvuqvvvyw�z�{|������������������������}~�~�~|xwz�~���������������������IJ��������������xC.++),/152356,)**(739146.38@KfKCJNLSK8607EGZL4&)2+2Od�������������������������������������������������������������������������{��������������������������������������������������������������5587;78A9?@DD:A?A4;?IMST]\bpz���������������������������������}{����dJIHLSSUc���ufgtkfd?@@2@p~A><.&&2)'3QgQ=8:^h4-F����mF<4IQ\llwul[U\^K=>7N_pcm�|�������tw���ʙm[jrj������V..796:753626'+1-/-6>0<6+,.26;5=B6?CDNH:..18GWD8VPSPCBHSW`gnpquot|vx|z|y~{~�����������������������|~�~w���~vxz~}������������������������������������[5,0/.*../6257/**),85<9>0436ENlM=NNORJ>95BL<ZU8,+../Nh�����������������������������������������������������������������������{z|�������������������������������������������������������������559:76;=;>9@:;>@@75=ETW[[bcmx~������������������������������������|\KGGILMT[l���khhlbhUAJJ6O��FC-''.3%*BfcEF;9Ql?.B����nO1,BQWYZlyyk]\bH<T:CZ``i���������wt���ѹiUlsr������p2/33+15513552/,0(/+3<6591,,/6<:9B???FLC?-)*8AQH5[QWR;ENWZeijpsvqwxvwwvy~v{y�{��~��������������������~|{zw|����~~��~���������������������������������u<**0'/,/,/C2/4,,+*(1.;G<,,*69QpLBUQXUII@9C<JXY8/0-,3P`�������������������������������������������������������������������������y|�������������������������������������������������������������::864566;<:A?AB;:4<>ETTX[]`m|������������������������������������}cIEACGLQUj����lhnjaXDALV?f�wP8')%-,(2Rhc8OF5AnP<W���{}fB8<ZPRKEX�vi[WRTNHPZRg���������rw���ΉNdtw������p<+.371,/57<:531+,).)07075231.1:C979=?EEFD8-07<FK5TONN:KPR[c`joispxstuvv|w{zx|~~�}|���������������������}{||zy�����}����������������������������������T.2+)(0*0/0:/.2*0.&/5-7K91.*;@RmN>QL]_F@<@H:A\U114/62R^�����������������������������������������������������������������������}~y~�������������������������������������������������������������::824:3;994>;6?:766=FPQY^^`ix�����������������������������������yiRA>@EEPPZt���oifjmmO8=@TF{�bG=344/0)-Sj`:GcJ3i`?b���p{�W57KUZW@@W}�rYjuS`Mgdck��������wn{��Ծ\_u~���ʻ�y64-51/.-15587<82.-,23595=674012:JD;9;>D@I;10.7ITX;NUTI9CHN[^chnkopvqsrvqyxx{~~|���~���������������������~~z{zy~����}~�������������������������������i=/)02/0---3=0/413//56+8D4...9CQmF=HGaUGD?DI=8T^:-1-63K`������������������������������������������������������������������������~z~�������������������������������������������������������������<<72968;<;3;<;78:67@CNUYXZZhr�����������������������������������p_PBADGLOYn���lfcfptcF3787P��Y6,+07+0+8XnS2BjX9a]C}��toi�r>;OQ]eA3J`��jx�Ntk}tn`�������rl���̟]n~����ֱ�Q5:6::8:5;97@9969.2-287532-774441:D787BHGM;2.4:IRVAUWOC;DFHNZ`inioqnprrsswuwx�{z~��������������������������}z~x{~�~�~�}�����������������������������{b=+2/000+-/:?.1.33-.>2.:E717-9EUfB>JEaSJOEE@;8_^2-9../Fk�����������������������������������������������������������������������{y{�������������������������������������������������������������44.13:8777;9<896798AJSQX_j\es����������������������������������zh]JFJELMPb���hadlttgJ7A21c��]2'$.52+:DgoI/9Y[KW\H���mlV��XJN_msN=:ST}�vxT���}{Qn�������qm��Ŏf�����̻�g402:7-55414=557@49.45:534014745775AD>9GF@F<55.5AQV>DVDL=?AMOQ\efjinllnssvt{xy�|{z�����������������������������{�|~|zy~~~}����������������������������~cN2'+/1-5203=:356?5/5;409A87./:FVeD;MHbXENCF=:<[b9+7852Bq�����������������������������������������������������������������������~z}}�������������������������������������������������������������004/33727695:696756:ERX[Z[Yfq���������������������������������~skXLKBDIKQp���obgeq}pXH051>o��Q-+446.,0RniF-8;ZPXWR��rhCq�y[Zfy{]E?>:X��na���}�fa{���}��tq���ȏ������ǐY>7598966627<>>77L:644695:930<=?<==7@BA6?EKKJ?=41@DV@@YOPF=FQNNXacgehhinsoxp{zu|y}}�������������������������������{~{zwvx{|���������}}{�������������]KN4&'2.,*1/-:2'-8@0.;726?9;21,<KV\G@OF^W<OQ<<8>Vi@/4,3+:e�����������������������������������������������������������������������{zs|�������������������������������������������������������������AA33-03167??8:<4584@HR__WSUhq}���������������������������������xk[RFDCAG[���necdfsyfJ<5;6Kw��K&%13.#"8_o]D750TSXTU����b9Y�nlq{wdEKAB7b����wkp��fK���n��uw���ʖ��‘�װe>975786:358;7<<C;>72-7;?7745/5>=>D76?GD;7=FCC::25;COE:YURC7GIJHTWbfllijhlpspwuuuwyz~�������������������������������ztuwsuwyvw}|�xwu{rz�������������o:UB6-),.+'(+04.*1997;:22579:1/0?Q`YFIU@\T?RF?68EP_>00//5=i����������������������������������������������������������������������yvu}�������������������������������������������������������������9933456203<485:2<77?OX]]XWVbq|���������������������������������wlWSCAAFKa���i^`jhonX?12=8Kr��G+&233*%=g[E81-)6O_Xt����W8Kk�}bo{�fC>DK2D`���}_Xy�s5x��i��x{�����������v:4247//359;8642748/+..(35;0040,8=<<C;78BC;D>?D75058>RM9LRJ=:@AGGTSYdfmlhffnmnpxuvzvz{�������������������������������~~}}uutuswwotstww|�������������|E6Y=),1-(&+.110,07<6:E8.581349.,=Xm[DFSEc^GOD@@C=UX?06454;f����������������������������������������������������������������������}zztx�������������������������������������������������������������22012859078.33//358EQZ`]ZUXao|���������������������������������vnZPC?>EKe��}e[dmnkfE2*5>=Xq�uA/./5/.'Hd^@;72)-?Pa�����gC=Z��ttw�oGLLT8Ly����zk`uf:n�{Vz�u{��Ϯ�����Ȍ=0/.112,0500536:<7A:8,*)2973673F5:7:DJ72D<;>8A?83535?LI=IYR@9;GKNPQU]biihiinjjjtvwvv~{~�������������������������������������~yxuvzu}}~~���������������a19V;++--3(/.,.714843LC74?7386A).:Jt[>HMC^fKHGB=@?N[C.=H77<e����������������������������������������������������������������������}{vou�������������������������������������������������������������6632158:5.3541//146KW`_a\]]cr|���������������������������������ynZTE@AJM`��sa_cirhW>8538B[|�[E.,0),&4OcY@B>33+0=d���}�{\9W��}r��pUZX]Tk�pw���~ebXNm�|Rf�mu��ќ����NJC4,3519<;835/779886>80+2,687/)206027:8<6496;=69@=6:/56DD7COUBA3HEOSNU[Z[`ecfogliqrsuzx~}�������������������������������������������������������������A.<W60/+0+,/,23?9:819NA:2:4748@+09Nt_JOPFc]K@K8=HANbF5@/442a��������������������������������������������������������������������}�~zvuy�������������������������������������������������������������--/1265342543112.1=Unccea_dlsz���������������������������������|m`JC@AEO`��v`_`i^OJBJ643GXz}B8451,$'0OXM84C=9+%5l���|��}T<e��}�xuaahq{ufUbx}w�jTJUw��kg�jn��Υ���ءR56383455516525:=9:;A=642568<849=4737<@?=<:>@B:>CEB;165BB6AOSG>7>GUVNX[]Yceiglnloqryw{|��}�������������������������������������������������������������]-/?P6-0-++,3/+.>81:45@E64511+1;)-6Iq[EMKF]`JCH==>9M_Q/2/521\��������������������������������������������������������������������}|{ux�������������������������������������������������������������>>3/652514205403.5@Tfbibi_gmv}���������������������������������~oZVG=C@Jb��yeWacWXUMI:;CDJrf6;252+#*7Q`S74CE6/1A~�����w�rLH����zkiav��\PTQ�~u�rG7<p��pi�xz����Ļջ{722/4005,.2-2.08:841;;40+01<;433614824:9599939;:@=?=,/1=@<9LDG977=HIESSYW[Zfeefioqosxx{~��|�����������������������������������������������������������z?(-MD0>1**+'13-4:43=678=71488037,+:Os^GSPJ^YHHGBBBDNWO42396.Y���������������������������������������������������������������������~|xzsu�������������������������������������������������������������5542/271/1300110+3GWdilheahnr����������������������������������yn^OG@JDKZx��m\daY`YJB;GPJMdW-77--.'*5VbJ47AI59CBi�����^v�uRk���gmf~�lBGWV|�u�zA78^�}fr�|����Ͷ��~P8,))-.4:70150,.0>95/;912&23B3//327212048:<>9<7<;B;?8/,65>?9CBK>:4;DJGFNTZ\Xajgglmqotsw}{��y������������������������������������������������������������X1,3TD42"(++04./3661C979>@2257+4=+1;RtaELCB_XTLMBFFBPUM940;8(R��������������������������������������������������������������������|~|svv������������������������������������������������������������4407371201//.)-/27NZfigiedgj|}���������������������������������~q`UJ>BHFVp�riqbZ_VGADWZNDdC5?:..)))>ZZL/1>F=8,3N���z]av�jZ���{motsqZHMcZ]pv��VPHj�qIv�u������ЛI862.1/5446-2002657>::@89-&.0892/68;2-0733=>;;6;>:D?@:,-27<?7=<M>:59GFD<LU[WY^dhhgjmnnps{}�~||����������������������������������������������������������;,+3ND/-.+1,.3215216L68:?A11?8*36*2;Xw`DLPHbQMKNIGKTSOFA01@<.Q��������������������������������������������������������������������~|zztwt�������������������������������������������������������������112.-4375031/0325@P_fffcgchky���������������������������������yndYNHFCMTfx�ymioZMNFBJ^jXO^>564*)&)*@X\G+.2D>823G��lmuctfxx\u���jpyif_NOXTVa�z�`cct�i3g�bv����ѡR513.13555;==260,549;;9=61.*03?82567=4031.-2;;864@9?H:64002;?=<;JH832CCG<DERVS^dbciimlqopx{}�����������������������������������������������������������e+'(3G74,,.--1/--2<7=C4AH;90282/.6./@ayaFIPIfLJKJDDMDWVBG84;?2K���������������������������������������������������������������������}xuyvr�������������������������������������������������������������0004,0.1314445314CRaefhggagny����������������������������������zkaXLE@CKP]oxrhgiVFANDNdaYXc><4--*(,-EcaF3)0=@>77A��hdhVrxqqai���upylce[WPILV�~�sp���g<U}cc|��ϠH73924.334667:2564:07?67A945)067>/61698/,.0.17=99588DC;71107:BB;;AF623=INC=<AJQWYZ^bfkjjrrvzz~�����������������������������������������������������������C%&-7I5.+1+/321/66::G=;@K4243?071651?asaIOPMiNUNHDFPLYM>K:;:7-I���������������������������������������������������������������������~{yvpv�������������������������������������������������������������--112.-5:38/13306<NZfdhfd^erz����������������������������������yp^ULB>GMT]hnlecldHIOEX]__`V;5>4.)'(/Id[A++.4<AA=A��`_dTfozypjo��~my~njm^NJMR��~ph�~�f5P~gm{���z442=40334942-23.6-*7<B75B60/*17<?.0308>0,,211087987::E<7301/9=?6A9E720:GOE937BFOYY\^begjllss|�����������������������������������������������������������q.&*)>M4-)0)-4,/1<7;@;<>=;10;AG>.-33/E\qeEPRNiTYM@EDLK[M3MB?7<.R��������������������������������������������������������������������~yzwqz�������������������������������������������������������������--.2.1035/0001:46AP[gmkji`gqx����������������������������������wjaULBCLNVYank[cl^JEGKMHL[_V@4A:12'#-Bd[E20647?GJOx�[gnZL]hr�|nxy�w~�vpk\LJMv�~ae���l.Dn^s����[/.?C1.+,.1/05405.1/5HH@476,++/69;4-150;22-33231:972946;@85815?=8<<<;75BGNL:438>FUKRUabb^hmmptv{����������������������������������������������������������`31,-LP11)0..14+4=5=E925AA./8FD'1-/98J_xiFNOJlQWI@GCLLSE1PO?343M���������������������������������������������������������������������}�xstz�������������������������������������������������������������00//,.,102-/5.1.3AVZeqljheaju���������������������������������yn]PIB@ETTZgtj_ioU77DR>7J`r]8.A755&&.@dT@-'0:7?LPOn�WmnG6ACF]{�{n��|x�wukVHRu��c`���m.;`[}|�ľU26[A1,254855:1.88077`A>;;7/(%178=32/03?531.05302;5;?7<;A33;42C=:6CA@7.7FOL@5.47:DEMVZa^_dgkpru}~�|�������������������������������������������������������@(++2RD-0/1:640-5:4<G9::A7*16V=+4/5;7K]ykF[LLnNUJBMIEJOB5NX=/11F���������������������������������������������������������������������|xst~�������������������������������������������������������������//23.57/3..2200/4KYY\dhfeadkz����������������������������������|q\TJ@@IOPZdje\\iI88QI90Dm~P4/7:<<,2)=cWC2,;B44DTWy�SifA/8;<CTw�����r�|yvh]Oj��nhw��SELP�kQ��D9P\83060676564215/-<?@::984.+39:B0.).28=5-/.-4000588<26:84879;88:;?@A19EGOG92-14:DILPX\[d_kmtw||�}}~����������������������������������������������������l7&'/3O?.-,3034002959?A>=@4-05K7/9.067Mb}kONKJqJVO@QONMSA3IY>17,>�������������������������������������������������������������������~�~{tsu��������������������������������������������������������������//.-1923-.-.,35,6DUUW\`__`foz}����������������������������������p_TIGEHQTZac`eVKI<<FE4/Hx�Q/3?=>5-03@ZUD,36?7-;Q[�VbeF92873JUl�����jp���xidd��}w|���n^MHy]BVQ:@kF233853A:3201767/9A=<=:=,.,18>:0385.2>73.2.6245;:4C;7787896;;;6:C@B65<MJLA15.-/27BIQXWX[]hovuw{~������������������������������������������������������Y3)-+7K73429463206>38?>I842*15?8+02576D[ziROSMsMMMARXIRVF/JW<8@*A�������������������������������������������������������������������{�{uvs�����������������������������������������������������������¾00.256960*+.2917AAQQY]`_`bcoy����������������������������������xq\OEAAHNQYjctvX6876;981N�sW2/;0>8110<NNC/-1A3+=N`��eoxP0/B?6@RTmt��vol���uol��w����ZYqfLhsK79:KH<453155B;41-61644;C@@B?4.0.46I=-224719;2,..00.2;96:<41884959H;36D@D93;JBK=3.,0-08?AKKTRZaejtrx|y}���������������������������������������������������xT/-)5AA5386:863955668B7P642/1:9;+14-;9KfthCRTOoJSRDTRLJND3WXF:E,G��������������������������������������������������������������������}zyrt|��������������������������������������������������������ƿ����11,,/7522402..-1?:JNR_]acdfq{����������������������������������{k\OLDDFLQY`eyk95659;6,4N�ndA*5:AD:1-9UGB3*1>..)<f��t{�X629F??Z][kl�~y����rlpr�v����iMnkWszQ77CH8549/,68:9;53/30/45@;<@@/1*.:8H=523451BB89/-21./409;><0:C433;?;85@F<905JCHEB/11-+55=>EQSUW]kmqxzz{|~��������������������������������������������������pR,%+2E@15629;:654689:;BL84217817249.;?MhuhGJPMoDMFAQWOFMK7FXG4<,E������������������������������������������������������������������||wtux��������������������������������������������������������������33-/6455201/11.,26CLUZa`chrv�����������������������������������{nZOG<@BMNX]rxO;21483<-1Z}^dI039<GB11DRAE2&07/,!<]��z�j916FGA^kWpmjpx�����rjrzs}�����\TWL_kZA<F<5?85320/45220,00.8;A:@C<5/-,44G@0-237-3;9/,128-.317?=827;93307=D<<F>948@LEPK;30-*))07?@FQO[cjouquvtv}~}�����������������������������������������������nR-(+/?9338<=7:7965:78=@RA1.884089050<HOhtePNQNjIPJJLYNNXI3KZD46-B�������������������������������������������������������������������~}}vuu{��������������������������������������������������¿��������qa4432/11.,,,--67042<KQW]dcdmy�����������������������������������ylZQ@;<ECDUi}`D<40-21C88giR^B02>=EI:1JHBC2//84.)(K���x�tM9.NSKQf\azYc|x{�������or������QBGV\T]O?564<35068;7967123;8>DCFM@23,*-7E>//24:55393/0/7330.27<;68<=C:49<=<<E982<IRFLM?>8454./3=7?NPWYbdfckpry|~|����������������������������������������������}nX-,04B9549;<6:9<889:16FN<859A0/2:9975EUdqgPXWLfISKNO[RUWN?O`I<8.F��������������������������������������������������������������������}yxuv{������������������������������������������������ÿ�������scR=;80.-,--./.-&,+05579CKY_`fhot����������������������������������{lYND?C@DLc|rSA898,-5CIHhRBWF509B:@C@GCFB3*)852'-?���w�~[=8D]NJRW\xm]n\l�����zyry�����]FMknkyZ93307023262162863989=BCHQA78018:I?7/35>3:9<;3352787525:;;><BA89589=:?9983<JFGGK633//3/,46>?NIIL\V]X[`kpvpt{vs�����������������������������������������|jU/,*4@;=@:6<=59<59@;6@TI9:4;H37<35-1<>TbogJXURbNZLJQaQVTJ?S\G?;1P������������������������������������������������������������������~}zwst�����������������������������������������������Ŀ������s`LB9310--,6//12630,*+47119=LU_acikpz����������������������������������xiZQD67AIev�bWFXe2-++CP`lL=LN>29AF;>AU>9E2)+86;$!0y��x��W@8@QMGEAVkyhq[]e���rp{z�����vsz�wq�oB220.026<445338116788EBNN8/11.3?K>482631:48940337/*/2,8368=:;866=?A:D?9499ASJHIF==5<-4+48:=:AEFGEDAFMTZ^^fpsxqy{y��������������������������������������vaA+,./9926896373;8871:6K@4347:46/385@=@UarfOWULbM[JNU`R\ZI8M\H<<.W������������������������������������������������������������������~{uvuw�����������������������������������������������������kVA3310.++)),)04.1-.++,(*3,34<EW`c_c^kt����������������������������������xk]I965Ga���__Y�s12*/9L_^K=AGA<=@>79KB<894),6-8,.-~�����`I@@ZXMDAP\zsx}eU[x�vSn{���������������e?.)+)+,//142994335BDJFNQ3+'*(5?S;3..//16:<70...51++0466488>=;>9@HEABBA4<>>MIGNMG==:>D<9@@=8B9:><CJJQO[Y`^cfjzzvy��������������������������������������oYG33-71.57<447;;;:;;69;QD579994:6-2;;BDT`roR]^OaQTFRO[O]_JBJVN>=1Y����������}xwx}���������������������������������������������������{xwqu|��������������������������������������������������fJ:4,+++..++//0,--10,/*-/*5*)2?@BT^__\Zdtz��������������������������������peYC9AJl��ȍ^es�w0-*)1FQUG<:<B:<938FI<-.?6+.2.3)$)c�����}YOQb`QA8A]t�q�lQNe�p[l�����������������L56./.016805992743BIJEPN91*(*.?X<130<3107:96-2444/53/53178<?CA9BG=G?D@95<5JJEQYJBF:<<8>?A:@@EDHNR^\Z``bg]fmrxytw�����������������������������������i\@9348556;787592?75::68M>37:7.-44./8A?>S\qmQTWTbSXMVJYPX^GAEKRCM4U���������|qpwxyz��}���������������������������������������������yz{wusvy����������������������������������������ž������s_K<4+)$'))***-00-,/>300),,1()'*.1?FLXc`X[dl{��������������������������������zraTE=Lv��ԡ[f[��f2'+./?SNZA45<I??9@GH03164*/5*4+.5\������zdao_LC9;_h���sQ>Wlqilp��������yz������pG<574634352332166CRTDTR713,--?L<21.74..3:76,1/185+.4492:<>=>>989>;;@A5.66<GCNXXJA@B>FIW^`\`fdbkmnrsyuxyuwxyy���z}�����������������������������������~k`A2/0639;8B8?C3:7A;8-7;PJ9::;04>82-6D7AO^sgMW^Z`VUHTOQRYWK;LIS=G5Y��������{q~rnspqt}����������������������������������������������}{vsut����������������������������������������������u_I@7-.5/#'&/.1/3//./10,0())),**&'/3@IKW]]W^^hu~�������������������������������ym\TIVy��՟RMKG��c5-(&':K_XC216FD87<I@<)46/*-0+/(&-Y���}���pPXUNE66CYu��yCBUh��fOa�����~wRFbq�����qT=5/+),-.3412162AQMFWM81'*'0FJ6634140-389<4,6366/+543267:;A<A>9@?8<<;966@GKQSQGDKJRV\nmkkmmty�}~�����������������������������������������������������pJ@>;7577<B:<<976;97599A@47@5.-:/6,5G5;N]qqVR\WbQYPTMYUTWAAMJJ@L<`��������xn~splnqsv|~||{||���������������������������������������|zwsstr�������������������������������������ÿ������xbO=25-+(&$(#*42675//61453241)+*,*+*-4=GNZVZTOWcr|�������������������������������ymaX^���ݙQG>>N��F2++&*3KaRB@9;AE@9EI932985+*/*2+).]�{�u���hJHTPJ;89H^yzgDC]t���YHg�����}`5DMSn�����d@)(+%-/(.55+.1<QGEWN7+%)*3=E:/0-60223441/)31620-386/039=;=563;7:=<:6.01=DADNOTYP]denmssyw������������������������������������������������������������rcPE;49>?528;655::57;=A675501985/7J9:S\lmRSPWjVTLKM[V\ZH=FIFKF:d��������sf{vlhmqsqtxu|zu|x��{~����������������������������������~{zvruv������������������������������������ý������p^H90,$))+**'110<;<>22;>7349/-*(+&(-,)4?DINVPLMWhy��������������������������������vndl���ۜIYXB?]��K@7A2'0F]ZKF?BBC:CO724:@E4*17.43)9h�zwyp��y`JLYO=93>GUe[KRo����aJU|�����vF@>5?t�����rD+(),1-/-1327>KHOWF1-&&.3JP323-1.-/64858-11001-,2532397:<975@B894321114JEGRZWRXfkknoxvz}���������������������������������������������������������������qZD@7947727=75634<7=>245*'383/3I=;NXqmRSPWcQYMQSUR^bMJJQHG=De�������seyvsiimpmmqqzysywyzqw{{z|{��������������������������~~{{wxnr{�����������������������������������ÿ������wbP:/-+1.,):%++2=FEBE99467:;5./0)++(*+)3=DFKROLJRbu�������������������������������vtq���՗MDvfJ<L�fJ5+7)+&CgWEJ=:?;JRG8254RN30)110//Bp��wh~��~hKOR<0/79EifVj����bVYMv������vaH,/Tz�����m=+(+/0000725:JHLWG30()&8ST5-02135,04<66/16417,22702;9:6:C;28H<67430115JIQMNPW]gkrqv~~~�������������������������������������������������������������¼��kM71<5447562330844/:1)45F9/08F?KYkmTRT`aQ\OLRML]_HERP?J=?k������znjtv}qermomrsrpruvvsqvuwstw~{{{����������������������}{yyyov}�����������������������������������Ż������oVB4-/'&(&)1126@GNPKI77677@E3<15,.&+&)(8;=BHLJMGPas���������������������������������}���ЙN@TQFC9QuW2(*-#(0;c`WI=99?MS>79<3ZV:305/75/>l��y�qb����[HF?+),;Pw~en���qkUQ_q~��xi��]J;AV������u?,0/2.4.74:DDOVR@76)2*;V_2.014527139:92..0.212603159989=5239E;59-05..AFJRQU`fjprw}���~��{y������������������������������������������������������������ķ��jK=:3:6:45.63974.3/(*.1,4/4S@OXirRLTUWNdGTMGOZ]IJMPAHH@o������~zsizn{yofqnrtomvrorqsssuxpsvuttv{{{�~�~����������������~�}zutpt~������������������������������������������s\E701'$&)).2:<EHLPKPI99?A=B6852/032/''&.98CIPPEIS`r����������������������������������Ӿ|J;FSA617n�J3(*.'/(?`[TFH=4:@G28::9LmN19D67.16Of��~�kn���uV:4*-8L`��v����W]iXTolo~�p]_�xY85I������k<.143406<=BFNZR>3/.3-@GR843.25:,012587-/0431+/244656:>A@:;;@81846936>JQUQW\`qtvxz����}�~|~������������������������������������������������������������ƿ��vVJ>@;58;676=:6/2-41=5;7>TPSZgrWHQQXUcOURMQ_]JPRTHM>Eo������~zzutz�yrqtroowuqsoptpornmpqsttvvyy{��~��~�������������|{ywsvt����������������������������������Ŀ������zaJ@1,.*+/-35=>EMURUQOI@@?FIBA:953522.&*'-7;@JJFAKKYjv|��������������������������������ͮkG6@PVJ20W�w5(%')%!'9T\YIDE8=?E>/88:Cv]@=<,:51<EUg���fk���wM),3;[Xn����qANagUXccu��qQcl^M5Ki�������g1+-,,.69KBFLaP<51),58@T787/<755/0152:99500827;=78/3:>>AD987825>6025<MSVSU_gowzz��{���x{|��������������������������������������������������������������̽��sWE=<9566997:83355;258=FZXZos_KTP[T^EQTMN`[LKNQOSBIt�������x~u�~}��{uu{xqsssslpppornnimkmiolnuorw{xxyx}{yy}������~|{|{wrus�������������������������������¿�������wgK;.-'//.279<>BKMULSNJIKKCH>>C=<7;5675-2/17CDCBC@CL]dp~�������������������������������ɣjNC=R]J?5C��o2)..-((,4KfXM8326II3889:@njO>;59706IDKi���tXa���uTSTVUap�����VMCHhnVS\e{��mGIFc`Rs��wwy���P.-/716?>DCKXN<93*--8FW@?4.8<60-1,66:?21.29455743/189@<:79<?:66;519=IPTZW`itrv{z�}��{|������������������������������������������������������������������®�w_G>634315<1+03&0,2;=AZVWdqYJYO^OUGLOIU_TMEDUUN;I�������s|z������xw}yztttsomrpinkihljljknhmiimrpsrsuqytz{}ux|{{x|utxtrns�������������������������������Ŀ��������fU7/*)'/-5<;;BLPOUYYZMRT__RQGEKA=>28586/1/4CE=H?9@:GR\lw~�����������������������������̠vUF@8MHI7Af��U3(%)($"$4H[XN>,+5E=.5596CxlUIA>L@87>59Gq��~eRZ���x{xz~x�����]IROOUwoXa[j���WB>^�uv��wvWX���I<,,266<:@JSE3+'***:L\>5/.3:42324,49<42/58663.49416<<;:9;9;;5499/34EHRY\diuow||z~}{}y{|}����������������������������������������������������������������ò�z^?411*05+&*2**'336>QYK_w[FLLXPTJJRER^SPGBOZK7J�������z����������z~{x{tqrrginlgikmdkkgjifmkrqpwwsrptntrsxvtsxxoolmps{������������������������������ľ������q`I5&+&,.07?=?AHIMRWUNXP[\oocgXWJBGB?6641.154BD@B;5:=AKVis~���������������������������¿�{fXF>AALX?`���6'!'$*-&"+1GWOJ/+9>;-0408HkqjQ:;EC<>>)*0N���sZYjtov���������l@BSc]L[sl`adt{xcPKd������}S5y��q=)+*0:64AIWH;.2+3.7TU=62/:81,2,0.6;6755-03.4/73/*/6>>?9<9@=73=9-57FKUV\^iwurzz|v{��~{}}{}}������������������������������������������������������������������˷�xbA0.12-*&$&($*5:CU[IXuZGQM]LWKNVDV\QRDCEFD6M�������~�~����������|~}�wxwyzusuqlihjlifgbag^gjjikothliiinnpkopjmoomgggk�������������������������������������|dQA58/+*+1:99<@FLPSUWWSQSYYyytqcc]RQLI?A984487@<48<6/2;AJ\mv�����������������������������sgVNBGB`bU���V1+$0.1('(--;LUT@0GT+%--6.;YlfU=IJ?8MQ,"$<n��yt[W=<N[izr{����T@GOfi]KVrwmejnucdau~��ś{_;@���W3)0.936BKXL7..(138U[:.0/851-25.+0376431-335104337=B>F8;:@4479<124>OIYWbmvyzzzry~�}}{~}}|~|�������������������������������������������������������������������ɴ�yW92/)'$(%$$*61AQNKRsaDJOZMVHQPAQ\MI@JK@I5S�������}����������������}~wv~ttorojijhibfcefhbdZadlfnedefeiiehmkqid``e_a������������������������������������yaF3/-+0027>C=@AEDJTRRQQRUVU[��~yrohYWPOMJ?;85<FB@88>7079DO\gs~�����������������������������vh[KDHU{]���^>/)(*#)')+/-5<G]PJYS$&+41<SrfbQLKF<ZS(!2G�{�xaH4=CMXHU���II^X[_lcY_b��orhymgmx|p��{^Q]MAF}�~3+.1<><EFXG001,(.9S\?/1-57./*64-1=>6513061/-1.38::?<=6><=>A99:./29NQT[^jov}yt|{z}{~�}}��y����������������������������������������������������������������������ɴ�jH2)&&*$#$(20BOI]Ul_AGOXOYPMPDPUFIAOC9P1[�������~���������������~��~{ytuzsqlkbhifecddga``bfca_e]cdadnnlnoc]ZXTYw�����������������������������Ż����`E4.,3327=;EBFCCILIVWUPQTWWYY�����zqj`YVVQAE:=@GE@:584/3:BLVip}���������������������ü������xm[OBOour��`@.*$%'))'&&-/*-AXbaqM  #1199MulbUMKBQkC%%!(8L���{xhVJLTbKQ|�x9Aeqa`cZcgfc|puosplps_���RBWJQNKk�d3/4:51?L[@5/-'$,:P_:1-.821--52/16=788:2410.-1<8866>=7:EI@74<92035GMQ\\klpstuz~~yy~}x|~�|�������������������������������������������������������������������������ĩ�]71+%%&&%13HJJ\RlfCOKYJUJLLBRUIIEHJAQ1]���������������������������~�y}ywzonqkiojjbecabaa^c`^cY]`d^hnkrnfd\VNMYk����������������������������������iL-'-+/5A>ABGEDGKNPOVTSSQXUSST�����}xlb\VWOGBC?NK;?8905/7BFVgr~�����������������������������yj[QQa�h�͢<3.%'.&(((&*0)*)3M_wwG!&*29DwxjUIOLbrA%"#$*9Qu����weYk]@Z|�i@3VyggditlTZ��}msnpw�k���~ZiD5S_P��W37648DFSB310,'*8RO55-+54/0.1/),487=62343..2049::6>=>?LJA87862127>FQ_bggstrwzx|{z{zx~�}���}�����������������������������������������������ÿ���������������������Ͽ�oJ,+)!$%75NGHWRh`FHJVGOGHK<ROFKHOL<K3`�������������������������������~�~ztuqsqrmhgldcc_b]cbaYYZbZahouqnnh]OLIPi���������������������������ü����sS8/(03@IQLMKJLILHPUQXROYR[\VVV�������somc[YROHFNQH@:951.0@L[`p������������������������������ri[Td��Z��7/.-++(+/(*3,)(*5DP�F!$&&/5Ay�qQKMOvyC1-.$'6=U}����|ie[Yu��GCE9Xz�mcgr{]Go��voyu������{O4.?hdc��96646AJO;7/(&%(;WM76329;2.-74,-7>9<99:1:5225369738>ECHMC=6?=246:AKTefikotnntry{y~~�����~�������������������������������������������������������������������������Ƭ�T3,'$$49KF8WWffDAIQFSIDJAJRAHLQE8H6f��������������������������������}|{|{wsqppmnehbbd\^``YZZZ`cpv{tyqi_SLGRd��������������������������������rTB3-.8@EKONOPJGMNISSTYUS\S[Z[YW��������~ywk_]UQQRSMID=;/624?LXgn|�����������������������������zn^^l�ea��^(,3)'(/).*,+((5>=HG~tB& $#$2:K��tGINavc7-7+'(4IQXUMk��ycc���EDPA=R~kpnylLR���xv���xlil��g5//Z�d��W3/7:GHN43+.($(=cW?83.7<<216..-5>83:OG23220424/:5::=;AFLC8A:9518>OPY_cmonpvvtzyy�|~|���~x�������������������������������������������������������������������������̺�c:."%*,=<0A\ecA?JKLQBINEMTKGFK>:C:r����������������������������������{�{x~yrurtnjnhg\fc\VYV`_jvy�zwvqfYOLLc������������������������ƺ�����`P;.-31@FHMOVPJPMRSSUUXYZ[YQQYXTU����������zxng`ZURTSOFG82/*/@HTho}�����������������������������tozp��Ul��;..'&,+(.,'**-%@ic\Xvi@'!#*Aq��cCIUneD.2:/#+DcY]A9FWumjy��aMBBTVG>]�zrvpubVn���u~��{_eq~��b3)4Oen��C299EK?37,.(,.9_ID11388663:/1.1596:FE43735+254626>>;FLSL:89:417DTQXcejwvwrrttzx}z�|��|z{����������������������������������������������������������������������������ßsB1.1.::49]c_G@LMNPHEQI[TJ@HL?4F=t��������������������������������������xzyz~upprihgllf]ZVYhjir��~}sjjUIFQi������������������������°���yY@//*26>EKOQRKPOTNRRVWY_Wb]YURSWQV�����������{woscb^`[SOF>/,+1@KUeqy����������������������������}y��~��`t�t.0,+)0)(&$')!$,5j}{u|mXD.-+3Kp��vH=HZYJ=@6--*<fpaMA6:Egl��~W@99GIRR@E`�|{vqjfv���y��dNmcq��K%.1Nr}�e845?=>53--,+/=ZOH:23;4382723251=77@KD5374943:>=4BA8?MQQE<94957:QO`[finttsxwwz{�~~�zz������������������������������������������������������������������������������ȫzI-,58009WfaG>NGGPCBRFPSCDEF56F;{������������������������������������|�|{y{yx{sunoopsgdfZbcltx���}qnbSNEVu�����������������������ɿ���lV<0',)3=MPPUWTLOJOOXYY[[_[^]\SUNRW[������������}tqja_bYSPK</+*1:DTesz�����������������������������w����m`|z[5).-.,,-'&'$ $%)<d���{qi]\h~��mL>HCQDFPY0'-:_xuO<:<CQw��nNQL;;QRNXSENhuu{{s~������}��v;B@=w�~9.44jf��B36A?C=7531,2C\KG;68@<5816//3:7;89@@>87673235>@=>D97JOOH746=82=XR[cdqqustxvutx��~{|~z��������������������������������������������������������������������������������ʱ�L0.7/+.N\XA=FDEF<AF?NRHEEH24H<�����������������������������������������~�yw{wvwusnjkhg`[_rn~��tn`WQNa������������������������ǹ��pS;@'&(4;MZSTXSOLNMMNRZZ\[_d]WVVVNQTV��������������ztfjfZYKDA5.+56BWfs�����������������������������������T_ntY:.,,*+/2,"')(!(.?Yjp���������dEFMQ>EBHWC),=g}]?9;>If�zbH<NF<<;GZW\QFUquy�z}����������W//.=��k5&.Qg��n21@?8643+./2>`O>:60<55:.53/081999B99>85431.2<C7DFC8IVOR578891BWOW^glqvwvuxyy�{�~yy����������������������������������������������������������������������������������ͷ�N40+*2H\V@7=AJEA<KFVM?KGF229>��������������������������������������������}xwwvyuquqmkeeemwx���}wohXSUj������������������������²�ZD0+6.2=KT^ZXWNOOTLOSY]a]cfa`__STSTX[��������������|spj`ZRJD51)-6EVcv}��������������������������������̞Ft`pVD991''()*()/,&+'0=BD<FT_kx�~ubILRSZ=:<?E6;Jf��h>-.2@Jz�VM:9EE7<;>Ofc_LLazs~~����������n3*&7���a.+B\^��B/?;81.(/*/.5^KDB10@646773+-1.4A=@<=:984222.<C9AL@<NVW^B::/91@VQRZllsttwv{|{{���~u{}�����������������������������������������������������������������������������������Ϲ�P5/)/CVT<2;=H>;9JJTI@Q?E,/6F�������������������������������������������~�{}zzyuvyn~kginru����wkdXV^z�����������������������ƹ��wT:,**;:OZ\[^Z\WUQRNQ[a_d`ecba]ZTOSP[^~~��������������zvpdZQGC</)&3GUgw~���������������������������������nDfEXNL@=0,.%/*&'*('/,2>H<'(-7IUZMN@=:DFK<8=DOVjpylL.,'*;c��;89;;MF9:;@ZegYW\alr}�����{������K$!&k���N+5UP��\62588/--())6XO@:24632:=7935>52>?F=A3/2945569N5?C??UV^cI>211*7WSWZpsqsqvy��~~|~rnv{~������������������������������������������������������������������������������������ѹ�T1)6APTB2>9B77@LGPC?K;D).5L�������������������������������������������{|~�xwwzwutnkmqz~����voi_Zc�����������������������ȿ���gG0%+17FP[[^ZWSWZVQQS\aagdoe`\[Y\ZSW]`||���������������ztkcVGB;6*&6IUfp|�������������������������������ެcZdGY;;?A82/,-1)/)&*03APQ9 %%3FNC>B@C:=38<IU]ilrkl]H9. %.U��v6+6@>AV>B>?LejgSV]Xdqs�����������g1#%<����;5`Wb��686/1-'1+/-9UP;:46<5161;26533.<8D?A7,252915;R@L;@GRY^`YB9-221MVJ_ostsrvxz���tqqtx���������������������������������������������������������������������������������������ҹ�M55FNXCAE@D?@JPPUJLK?I.7:V�����������������������������������������������z{{zxzspptu|����vqnfbn����������������������ÿ���|W;,%-6GNU[^WYYUTRXSU]bhfhefi`\YY\SV_ef����������������|wi^UH@7.+7KTbn|�������������������������������ٖqx�iV-2,762145@637:/;@@IM7-,-8LYLGBB:<5400=?BFIC@;@:4#$%=b��s@/0F?@XIED=BLgshVXR\gp����y������}J((,^���c>qUL��G/2.)*+0,*15VHD34396/74985/477<>EBD37315749;S;EC9OO^cgfM63,-+CLNSpvqxtww~~~zqprx�����������������������������������������������������������������������������������������ѵvD-9AP?0;4<58IPTREJDEG(38]�������������������������������������������������}}��wwuvrtx|~}���{tpehz����������������������ú���pQ9/,2?KUZ\U^bZ^ZYQWV_`akljib_^XY]YT^e^��z|���������������}qbWMA6)*9ASbq��������������������������������чy���_%$)8&+14:=;<655D=ALF?4-+9X`QC>89?:@AB468;14,/>22/),:V��rP3)8:DRQMIJADUomZ[PU\i�������]��sG58I��ȘXyU>��k8:58/24517;XIC8>7<6;<<=959;;<@?ECI86738399@[HG@9KUbhieY@72.-?TN[rztzwvv~yysgoy�������������������������������������������������������������������������������������������ϳp;87HA/14>75@DPF;MJNG)08a���������������������������������������������������}xyztxw}|����~pon����������������������ý����gH5509FVZY[W]\_b\[XUXdijunjih^_]VUSW_`_yyu~~���������������ym[YF2-,>IQ^n~��������������������������������u\t��i$%"'#%0188<<<;9AI?OKG7/':RH@<833:CC@D@6=-++/20>C7/.8Npkph=)-8GRJLTIPKN`ygeeSUgv�����|��_u��n]TE����t`B9[��@3.,,-1643=bKE;=9F5>6=<859478<<ADI9;B=>?5;B^IIC@NZdhig\@885,?RP`w{u�{vsvytltx���������������������������������������������������������������������������������������������ϯf9,?C.3/;.6HFJ@>HNO<)1;i������������������������������������������������|yvyxuvzz���~�zupp���������������������������|^A218DO\a_\[[___[[YZfkols�nje`c]TQT]`a`ggkp{����������������pePB4*/6HXep}������������������������������пgNM��O$)$-).-,4361,41AMGGABA41567;4,14GU]IFA972$+++-?L5,,44GRgu[5/3;GD?HGUIIKovf`VO]v�������~di���uncyz|��\02@��W.0220-3,2:^G?B=8G467162-./35<<AH@29:947338IEED=K`hkoh^K=/*,=MHdtxwyvuqqo|���������������������������������������������������������������������ÿ������������������������ϣ[01;'*-2.8ANK=BGFJ6-2Cm����������������������������������������������~���||~~{|}yx|}�����}ysv~���������������������ž����qWF5=IOVa``YVV][\\Y]_hmuurokhc`^[TX]ccgeYY^gy���������������udOB5-,1KVes���������������������������������l\Cg�:&%&%+2*,1/6/(.0/DI89DH<2/-64-+)7GedS?7761&)*++@cN0#%(9E\rh[7/0B?>BIVLAE[zrg\USw�������ph���aOk}_Py��2.5��v6.+-),(',?bE?9@<?04-0721+2;6>:<S>889/00.48BFCC?K\ivvgdP6*0+6QLWpzv~trqlm{��������������������������������������������������������������������������������������������������ɑG1:0*'-32?LB<<C9E0&0@|�������������������������������������������������~���x|~z~}�����zy����������������������¸���{dQ@<?LQ__`\^XY[]Z\]bemjqoolhg_\c\\`]ejgfGGN^nx~��������������{nXH1)+7EWapz��������������������������������qd@MY(&&&20/.'+.32..-7FC439A?0*+2,-$.3Ogf^A6@=8&%*-,9n\<+%(-=QnmfV/+:AKMLPH>ILcvteWQr��������s���l;i}P8dðU.4qӡ7$(&$-(%-<aI:<66D42.4;*-.1225ADIC853-.2,.7CJBK9N]iu{kl\B+2*0NV[lzprjmly�����~�����������������������������������������������������������������������������������������������~<90.)+34<FC49=><-&0A���������������������������������������������������~y}~}|���������{|���������������������ʿ����oYJB@LNVac`ZYX\[[]_cdjpnjonnjd_^^YTZ`bghh<<EWjr~���������������taH2-,5@Sbu��������������������������������tzwCV7**)*')5'''*6//'-E]@0.8;993/.,+**?boed:8KIB,)1*)7cd@'%,.<PceWaI./BCPGKGFJUFoxdZXv���|�z���w���|W�yO.=�Ɔ84dڻN)#&+0$%*7]A:<58@33027/+15336;AN?/014*,&-4IJ=AB\fsv}oj^A-0)/IQW^ys}efxu�����~����������������������������������������������������������������������������������������������ӱlA6-*(3,;BE36?E>&&0I��������������������������������������������������~���}~}}��������~}|��������������������������{bTFGEM[_cc]T[]_b_adcejmtpomjdeb[_X__bbggh338O`iv|��������������wgU5*&5BS]m��������������������������������z}�MT?,)*(*(3++++6,..;_N3/0;<5851,,/)0J`olZ4,OSF.'(+'3RvS1'0*1S]LTZeC18BONLKIGUC[th^Xywysuowt��}����|�j@,;f®Z;U��f,(%&+%*.7YB=@6:D678693-265:5>AD;5<<65.+/7II>?ETiozxsiaI3/+1PTVbshsgu�~�����~������������������������������������������������������������������������������������������������ЛT60-,03<D<038DA,)5R��������������������������������������������������������~}�������������������������������ż���jWIDFJR^a^]YX]d^^]cdjlprttsic__]_[\bfjedfe((4GTdu{��������������ykX<+*4AUau�������������������������������ڏmrHMQ7/(,+(--&&*:,1*DgA1,3</.4:1-+-'-PdvlK+)OZL7(+'$)MvfB3&)*LbNIL]eI9>G[X_J@L?Cni_Z}}hcokm}��x������_0$*6��BQ��q'!#%'%$'0X<<B2?A01544,4*16.89>D77>8433'-2BJ;5MXou|vqkcK6-).JNVdl`unz|���������������������������������������������������������������������������������������������������������J,(*040<6/.5@@%*5`����������������������������������������������������||��z|������������������������������������u`PNNRPUZe`_W]cbdbdehmquvwnib]X]]_\a`ijiiih%%.9O]ns�������������}pW:)"0AR]q�������������������������������מocF[c/%-%)/.*++17/.1Tg6124..E=372/**3Qi~mL2*=X@;+$)%'=anT<-'*;jO@9RnaF2C^f_SSG@;Y[c_u�\Qkvq��wy�����uQ+'&)P��NO�ӊ($" " %$7P<JD3AG40483)++-+07GLD:788->>-/.A;77O`hvx~qqlQ2&)(OISfck{v~|~�������������������������������������������������������������������������������������������������������Ӵf1&'/.3=;.-3F5%&9a���������������������������������������������������~����}}�������������������������������ɿ���jVIHPPST[`^WX^cca_cfjprrsola^ZWa[_\aecghldf&&*4CScnx��������������r^=-(/:K`s����������������������������������sI{(&!+*1&((60%,FfR2+)21*2@092220/Us~qS,+:N>;'%(#!,JbbC3&.<kWE;=XbbK;Nrc`YPC>EJ_]p�^Ql���qlu�����{P,$$%3c�iO�ڟ0$%&$#&*3P<:8/ED23.47/+-514;DQRA/4;8><+*8=:=:R`psvxumaU8.('<KPggu~wy~���������������������������������������������������������������������������������������������������������˕>$%(.9m:(.7B3$&7l�����������������������������������������������������~�|y~y�������������������������������Ƚ��t]LKKMXU^`_YVWafedbeflsunpi`b[X^Z]^efhgikijd##',4BOer��������������|]D)&-2Mar�������������������������������q��K�x2"%#.5+0(+31-4[RB4,**252612.4-/4Ln�sL)&4K;H.'+$"*7E`aJ1%/aVE:8KdhYOMgfefe\L@DS`tx]Rp���jh������xd8'!+H�}N�ܲ5"3$)$(%:OE><4GD2,24/--*33467KZ:.<792:-.7?9<GXetvwxxjcR8+*(?Daihuyr{����������������������������������������������������������������������������������������������������������ֺj(,'+028)-7=+&&9l����~������������������������������������������������~��z||vy������������������������������ƻ��nXMLPSUV]cVW\[^iickljotqiee]VZX^\^ehegggjekf##*+27Hep��������������x]<+()4BSp������������������������������eyŸLZK,%#,25--*,,55DS<41*,-.3<1(1-4102Yp�tV7-7SEF<%+'#(,0BcaF6+R\B67H\haVN[jhoqxi[E?YkhYPq���hy�����}]eU4(#8L��`�ܺF%++'"%&6PI9<>NO264/5./364.29JT:2/868/)07;7;N\hsqoqum_P/('%BJYhkupq�����}������������������������������������������������������������������������������������������������������њD:%.-32/*40'!(=�����������������������������������������������������|}}|z|x������������������������������¯�jXNPUX[^\ZW[\`dgkjlorspoi`_aYXSXZ^fggggh_bhc%04<Zj�������������{b9& &+BSs�������������������������������k~̕GE>,)(+3-,'.0?39K?50+,-.42/4-+0*010Ru�sE+./HTL?'(("'/#,JccZ=?gK8.;OM[[XL^stqvmnL?S[^WOf���y��z���\><N=#'9O����ټM( '&$%&;SJ3<<LI73.540-15039=LF5427/40+,374=U`^lijt{kd[43));Kadkxqy~~��������������������������������������������������������������������������������������������������������ٽg+)*.00(,/+#+D���������������������������������������������������|�z|x|�����������������������������ƺ��waSPTY[^`][Y[\fgehknorssnha^XYW[XXaehgjiceibh"" #)3=bu��������������{bA'##*?[o������������������������������|ml��MU:((010+.();43@A1;0+,4)29..*(-)/.:Xy�x9'':HZH8*!&#+0"#9HdiSGfXC,4N@M]aMK|mlmsoW?LV[WIb������w���j4(7F5->EsÜ�׷?,,+(%(DUD4;EOO20464-03094;8GB7*2./252,656<O^`njupo^eZ;1+,@Pebg{zqw�}��}y������������������������������������������������������������������������������������������������������К:#.&03'',*+'+J���������������������������������������������������}��{x�yys{������������������������������Ų��m[SXXW[``c\VZbdggfmonrpngd]_[SSYZ``hhhflgacje&&'$.59Qn~�������������wX3")(-?Zq������������������������������|ig|fru.'()141***21:F;6:10+323,4**./.-,:`��t.*./<_M6-%")+G&*6>M\hai`D-1NA;WjWJrslnfjbMSRZRIXu���������<#(:TJ4:kì�ӭ9" ")GN=06LXO132.72(3.=766DC63-049E?4898KX`lmqjhfcc\@6'9<Qb`pzyz~�~~�||�����������������������������������������������������������������������������������������������������ؼb*))/2&(). +M����������������������������������������������������~z{{yz{}������������������������������ļ��~eYY]W\bc^[ZY_gfdhklpopmnge^[[X]aZagmcheee^fji""%('79Tg{�������������{P*(%3GXm�������������������������������nkhm��3(-+25./)*//=>064.5--,.2:,91.*,3Ml��r6$&+:TN21(()251)776@OUV[J:2YO6H\eW`sji[^SPQ[]NPZv����������S'$-]P12j���Р.$)$%"#)KFJ14OhY1+08/++62-*67N>34./08.23<8=T^jsroja^dmeD9',8S_Xtxwv~����}�������������������������������������������������������������������������������������������������������ό9)*,'%$'+ +[��������������������������������������������������~z|�yyy������������������������������´��o]XY][Z^f_\_`fjefllnpsqkhcbZYX]YYbaelegdd\fifg('+26Q`z�������������mP.&%&/H[o�������������������������������txhz�i/5143//-.2:?@:.472/4-14-01/-32(6O}��n6&&'.KYB5#$(?;.#/:9757=H<.-N]>:YjZVfqeQcUGR]YLVbu������y���j( 2D6-1g���ŏ/ #)'(%)MPN/9Hg]3/885.3=+/.;<P;5.*)26,-;=5DWblrkd`cgmodB3+2@T\Xktw|��������������������������������������������������������������������������������������������������������������ײS'&))"#*%  /a���������������������������������������������������}|�}{z|~������������������������������Ż��zf[^V^][b_W[`dajgjknqrtqjfa[XVXX_^dbhmfha_bgdbo$$)1+04I`x�������������qT5%$(-GZl~���������������������������������F)+2:9**+.09=;014<41+./157690...:Z���d<+%"+GYJ>$(0G>0&3>D8)#4=2.08dP6Ofg`Vlk[X[KLYQPQbp�����ms���wM*-.,09[����r*("(,+-7WSV37G_O;85:5557641=;C<6.,*-00-9:7LWajkb`_nsut`D/1*?`\cfqx|�����~�������������������������������������������������������������������������������������������������������ˈ1 %)!$%(!#3l�������������������������������������������������~�|||y~������������������������������ɾ���scZ\V`Z[^]Z]dcjkllnppurnje_[^[\^]]ibjpcg`^^keli!!!&.6@H`u�������������rQ3! ,@Zn���������������������������������zq61,5:/%(-0:A=11/.6+++&-,4510-2+3@l��~d9#$%(@WM9+'2KA9/5=B9+$*27>64YX>CeleYrvdXd\CRH=Vdo����lq���krn3&0#+1T����U*&!"%)8WUW);JUM//9;47812227AH=@3-+0+0;:5=R[\c]ddgv~{tdI6/2<d]_ms~����������������������������������������������������������������������������������������������������������������ԬE &($ #($3w������������������������������������������������~|x~�}y������������������������������ĺ���j^Y\^\^ZZ_V]fggiknqptvqoc^_\\[Y^_ajcikacc`brhne %$.DB]v�������������vW6#$+=Yo��������������������������������yr70+6<*').7IB450*,>1*&$.39:*+,-&3M|��vY8$-(*2@D9*!9M?3+*?J>,('2;007Na?;TgY`jxsab\XOH8Viz���~k����kg�N.1-+1T���n=4:("#&+3VRG+:MQK009<00--33.7@A<B<,.-.0:95=XW[fcios|yxreK3(1?\Zcpqw����������������������������������������������������������������������������»�����������������������������������j'/2#"%'!!9��������������������������������������������������{z|wzwx������������������������������ʿ���ze`YZ\]\\\XYbgkkhsrpsvtpo]_Y\\ZWYcdigfkecagchljg!! #)-E[t�������������v[9$ $0@Un}��������������������������������suq3(,:60+*5B@560+-16,24)*94)'&&))9e��pX5%)0+)8C6-%<U<46/559<,,/403.<PI4UhG`ntre[NRWK3Lbx���sky�����yD4//6h���UBkj)"( $?SON4AJKK4279-3344./=:25A864/16;<7EORbklrxx{yyqeL0+.L^Yknrx�����������������������������������������������������������������������������������������������������������������ў>,*%""% ">���������������������������������������������~������~�}yx|������������������������������ƺ���o`^W\^_]ZZY`eeeekqrpptrrgf_YYZ\_abikgjihc`]ehifb !%-=Wt�������������pS8 #%0?Ri}���������������������������������hHF+.:0'01=D;136*'3*,+*'-85&$%.-U����o[>02-035A2-)FU7654421@4(58,/,8OK>WbCYr{vlNDKEF:>Pt�������yYs��y^Q>G����=q��/$%KXOL2ELA?23961?=/-34884605C6317@<<JT^kuqwv�~xzteO-+1Q[dikoy����������������������������������������������������������������������������������������������������������������ٸX  $#&H��������������������������������������������}�}��}y��|zw�����������������������������������m`^\Za\[^__^dfflvvsuvsvpba\YUY[[`ckihjdfidageb_^"$#$,:Yj�������������uW7!#(/7Wk~���������������������������������H-)&,86)65<:5--(,),/-'(#81.'#(#'>r��z�nb>$*$'(/657*EL42;6'.27.-6?-+11IF8H`BLn�yt\:69<6<L���������h4B���rxny���qW�¨D%%++?PJG/?G<>84<33C@.360276443;:2:5:<JP]isuvyy�xwwgO0-4YV[hpt{�������������������������������������������������������������������������������������������������������������������u&  (U����������������������������������������~����~~}��x~yz|�����������������������������ź���sg_``^\\[YY`^agjmosprssqhbaZ\XWYbcghfmmkgegffdibW "*:Np�������������y]8#!#)4Sj���������������������������������wC*%-17978A94-.2,'&20$//00.* &!&8c��k|�fR2((+,)+5>/2F@.471%*-0+1::33/)BDA>FA8d}�d<499?FV���������}Q5z��>Vz�������ȨF###(FM=?1>F8DA:91:CD4./52:10405>6087;NVjqzv}|{}xxvdT.+<TVbfpuy�����������������������������������������������������������������������������������������������������������������җ4 .a�����������������������������������������������}�}|xy{���������������������������������~mbaad[\XZXWZ[_lhmnmsrophc`c^YZX_bemjfji_dk_`ljh`[# !#*6Je{������������{_>$$*7Pm���������������������������������}<1(.258:D?8))+9%,)3,-/*1-/"(%,8S~�uNswT?4$,(',)/6:EM='+93!'&(/*7G78*&@J>B524Fm��nE.BFUM]����������wJT��D<q��������{0'-(-FM>50;<3=D=<45BF8216734.372?/B>;JS_nx{t}|}�yy{t^F3/KY^_mpx{|�����������������������������������������������������������������������������������������������������������������ظO!" -b�����������������������������������������������{{~{zwuvz�����������������������������ǽ���yfd`bc][\WRZde]flmpuutohf_d_\[Y^bcjjhhhghehoajkdVO"" '&6Kg{������������|bC($()8Sm{���������������������������������D12.;D>@79*$&+-+,-/,,103*(%.)=XzqI>nrC93).(*/.+9<IK@'.;7#'%'.7>H;<)#=UA8GE4BgyqW=@Ne`b�����������x`|�[c����uMQ^M;(,/(3GJ<6.?=1ND@322>=5:6?>2,15.2.4I@>OSer{yw{}z|{|q\F3,CZZ`jn|w{|�����������������������������������������������������������������������������������������������������������������t$" 4k����������������������������������������������~��|{{w}|x~�����������������������������ö���ufhf_c_]Y^V\`[bklpososnlc_^``Z^]aehjgiggkabeba^YWS $-+<Kf|������������yfH* &)8Og}������������������������������}�tG725BG<4/3,*+/-=.*0+*./*(%&,4a�z]B8?{nK>31.+))236FPF7&(3:*'/(0/7E:5' /TJ54<<d|ptolaSUjZ_��������z�����������@-&-()%;N/9OL603>B8>8E2.3?;617?:3251183<L@JPXnz{{}~|yvvvp^71.P[]`hrz}||�����������������������������������������������������������������������������������������������������������������Л/ $5x����������������������������������������������{�~|x|zw{z�����������������������������ǻ���{pljhghe^^c[abaghksuvrijf``Z]\\^chiijkgjhh_\bd_VQZ]  "+4Jky������������iF'$&)6Pf}������������������������������||tD<9=EG4212+,+1-)++4/-'04/5/1E}yV>..M�bIUJ0-)./38=KQH6.&86+&$$,1:DF5()O_;@8>]xniowzviphq������uD?s����������_9)#$ "4aB*6L=1/7=>0<8@9,9;<21/?:7921569CEAKMZqx{�|{{xzsfR<0,O\[]fp}~�����������������������������������������������������������������������������������������������������������������կE'>������������������������������������������������z}~{{|xxz�����������������������������ô���|qmijkffd_]`__banrwvuoikgf]_Z[\_bfjkllggad^^]\\ZRRP"!"(6O]}������������~oF,%$(3Pdy������������������������������yvkSC:;DH7,++++*/0.++..6-&-)8;;JYL/'*4^�WQS<510,1/0?SPD8/')50/+'+46CL<'#+SaJ0:47KXP]ry�{�yq������oQ>Q��|�������xW@)$'3ZU2)AH>43=N=+=:A@0:?<2,5>;1/24215CEFOVdox||�z}||~{vmN;/.T]X`jny����������������������������������������������������������������������������������������������������������������������j =}�����������������������������������������������}}��{~{z�����������������������������Ǽ����ypojjjcjfbadba_cmtqturoiji`a\]`_aahhldjhhbi[__UVRTO" %(2Jo}������������}lV4''+>Nc~������������������������������uteK<?7<7.(.--022-+.2**<,,BJLSJ<02)0:ozQYT>0/0-,$/FX<:;0&)0*,*()59GA6("*OcW:6.*3==Bgm{��|}�����o_YNa~�z���������\I<Zt8(2AK83/<H81@=?C;7C5:0;=>201260=KGKMWfoy}~�|{z{�{lH900RY^gjr|��������������������������������������������������������������������������������������������������������������������͆#!G������������������������������������������������~~�z{{~�����������������������������¶���~xutlngffdaaa`aeekkqqpooid`]Z[_^\dighffig\]a`ZW[TRQL!!"#"(/Bg�������������}tZ7)$/>Ocy�������������������������������zwG;-/91..1,00+-+.4641--7S_^>62/(,;9d[O[[U8,8,&)4MR2@C4&)30*%.03>I1-4'.P_YA5///867Bax{����r��}{knVRfgo���y������yr�r?5=RN9214B04@<ISN6=820D<93/2*03BKCMQYgrx{�w�|y~{|n?:/8T]blny}}��������������������������������������������������������������������������������������������������������������������ҥ@"N���������������������������������������������}���}z|||{|����������������������������ɿ����xxvysjigb[bc]bgacenrrnpqg`\\YY^`cgjgegkl`\]_cYY[VVPQ  "'-Hct�������������xW2,',6Cdv��������������������������������zC?;/73)/-2-0+--02?2/.2?WiJ-*+2/3/>]LM][K.&814-<A505F7,-&13,333@R8%6>;T\T=C1+,'4;AYx����y|p��x�cmhF>28PitYj���������rkvtgS@9FH.7BH\[J9;325887/13//6HIIJQ\ir~{zx~}}�xx_H9+;T`bel{{}|~������������������������������������������������������������������������������������������������������������������׶W$]�����������������������������������������������~~~||}�����������������������������ĵ����zwu{qhgh___ccchlifnnsknfac\_[[\\^glhgbildbcibRQU\XQQ%"$4@\m�������������u]4$",8K`r���������������������������������q<GM-//++.3+*,.++-738+-7MG5*.01223;`UYYWN;(3.07<3*.4<:'53.0//5..RK(6<F]eG/A7"#'*4@Kt����p�v��z�a[sG%"&'2`Y2:?RIF{�p�����~sgjthM\jd_;>=9-,.5:62/01/>HKMSXenv{�y||���|zy_L@1FUcmgr{{�}�����������������������������������������������������������������������������������ÿ��������������������������������z" %_����������������������������������������������|�x}|{������������������������������ɽ����|wrwysjjkfafcb[cdhlplmnmaZ]Y\[Z_b^mlhhicgb^]e`TTW]Y[X#%/LYq�������������vV0%&*;Kcx���������������������������������k6FO,*)*2-)9--.+,697-+10G0:/15:55+4]WVOF@75,.>BL8307C<+-6<+93.,2MC&.8WisA$<?&""*0E\k}��h���j|�oMk](#$-Tj,('*)4eH4;Iq}�{~�����tSA/<F38831<6/1626AFER][kqw�|{|�}�zv\P6.J[_beq~����������������������������������������������������������������������������������������������������������������������Е(!(m���������������������������������������������}�|~{|{}||}���������������������������ƺ���~vvt{tmgjgcd`e]`gghjonnj`bb]\XWX]`ejjhhe\`a\c]UUV[\^^T%(0DSm�������������wW8(+.;Lcz�������������������������������}kb<>E,-75,(-;,.-4.431,-)002435>67.14NXTOHA5@7)AA44'/.D>-781-+#&(7A;1(9Uoj9%5I7 '85ASb}�uTq��n\k��dbtP*"%,G|2$-.*MO(!"-LJYIDHy��~mmhF<DD782?774*775;IHLVY^kt~}|z���~��uSG59RWgigt���~����������������������������������������������������������������������������������¿��������������������������������ԲH!/y���������������������������������������������|����|��~���������������������������������ztqpturihjhk[__eikkjphjed^[XXUTZafgijlhg[W]b`_UXU`^\Z]###"#,:Nj}������������rW:$**8Hcy�������������������������������ydZ97?,08133*99.0.024.)+60/*-8<C50.'8JIIG??/316?C42/,2CD4**(/*.#68E<8.1Ysh4!#>S-+5AE[_t�rLd��q]Xy��]v8&,/<{B#-*3W/! %/DBA55:OeX>Ie�iUN=54688=3)553GDKUUWciu||z�|���~~dPH,;MTg^lx������������������������������������������������������������������������������������������������������������������������׾_5u������������������������������������������������|�}��}����������������������������Ǽ����xxupwxjkgffc\[_fbejfofddb]ZUUVX_geiihhik_[\]b\X\V^]W`[!!% #0/Nc~������������qWD&'+GG_u�������������������������������{kU45/).45:3+-..-.-2./3,,8109A=501+:AGLHC:;4-57<10+0<7DE6*.'-(#$1<?(+-6\tcD%$+WV=AIS[aay|`f���yeY{�~x�Z+&+5yP&)&JF&!$=?F;573GCL2<Igr}`D;8:609-,/-?KDLYUbemw{wz�}����~gT?2LTaeer�������������������������������������������������������������������������������������������������������������������������˂! 4}�����������������������������������������������|}�~����������������������������Ļ���|zwwssssnkiia`]W^eehckhb`WUYSUY]`ehlmjicfb[ea_aZXUYaa_c!! "!),3Ff~������������y]E%&3<Ghx�������������������������������|mY778-,4<B,(0))(/)872.00-49?>?50-118CPCG::23<<3,/7.1CFKB,1+%('&6H5+'-?WjHS9$">l]AKP[agzxyxsav�viq����{C)1=p`'))F6%.)-BGIA1,1LD24?;>G}iCA9//.3-129CGKSXZ[kqy{z��~�����ybS60PWeffv��������������������������������������������������������������������������������������������������������������������������Μ)!<�x����������������������������������������������}������|��������������������������������yzwsspqolkigb\[Z^bdgdghaWUU[WZ]cdkdkghhdd_[af[\_XZa[^ac''"%'(*,/Mix������������wa5)-2FFcw�������������������������������wm`497+317F+(0.,,-)90),1,2=IKC=0*4222@C@C=I8?A0**,,++79JT,')(..);L-)&9Q_M?]]4&-VlVGNarakttx{dji`ruuz���k1+1jv)*0:)''/;D>=?;.4L=.<?=<1NTFC7-2/**,-:CHPVX^cktw|�}~����tXM73RVighy��������������������������������������������������������������������������������������������������������������������������ԳE >z���������������������������������������������|����������������������������������ƿ���{uvvxqpmlhphgaZb_]baij_Z]TLRXWfcfkjjccci_]]`e_]`ZY]Y\]``&&%)"!&'2C`w������������y^D.-4AM`w�������������������������������qi6;7;4'45++,.)()492.+3-:EED=B1(0604@G==8??C@-+)161133J[5)'*+-3>B.#)>^[>6UlT<=>UhfSOeNAUe��gnj]KZr}����X.6Xs+,6/*'0.<D<35?)4E>;?68+0;>6B552(,--39MOSVUchiqx|~z}����|xmSI58V[gnl}����������������������������������������������������������������������������������������������������������������������������g#E{}�������������������������������������������������������������������������������ɺ���xrtrqospfmkbaa\Ycedje]VMIKNU^cgilhlfcdc^ZUbc[^a_c]X]ebc!!#$"",2B_t������������zaI5/4<J[u��������������������������������zt;78=,0921','&'-4<.(,;FRUHB:0/-4).1D@;66AA?67263316/9<K6$(+,',?E3,/OoX3;=amQ411]}jBGVX@\��}riaB=Acr����R6Yl6;4("&(CE6A0-+$;I:D=37434:7E63/5*4149ENOV^jlgqw}t{���~~|hR;/>P]depy���������������������������������������������������������������������������������������������������������������������������Γ0Nyz��������������������������������������������������������������������������������ǽ���}tsqoprmkeic\`^YZ`eff`YPFBLP\dhhhigefae\[W\]^^X^`\d[_d_[%%" &&"&5>Zu������������|lF..;>I]y���������������������������������y71GF0(=3**.%%')95247TcdV;86/,--,4>D<=>;@6101@/0<36(3/CV)#,.-4=>5&,VcFA6DMfbA'%<}~ig�[s�}��nXPE7@Usw��oSY`.9G<$&%3B=:65/);>6I:5614113B30'6,/4<@JPWX\mhlqtx~}~����v_J74ITbgls}���������������������������������������������������������������������������������������������������������������������������ѮIS{���������������������������������������������������������������������������������Ÿ���yosljpoiiedbWb]\`efha^ZSNFNS[cfnniecgg_X[W[^\_[dc\b`ba`T++(&(#%#/9Vm������������~eS445BN[r���������������������������������i93WO62=**&.&,,/12:HQcZH9312-*-+69CE?=M;/50-2==5:87/-7Dg5**276/:A5:XI>E;FKirN'&%G����k�wY�~slbZ<CBrl��blr:^�v+!*;<@85;0.D<=E86.04607:4-$/-18AHOTQY`olmtvz|{}~||wvZE5>OY`dox������������������������������������������������������������������������������������������������������������������������������k\y������{��������������������������������������~����������������������������������������{opilkhhmacaX[]_di`a_]ZPNFRXbfnpjhcfecZZVXaZ^`^eY\acg_YU,,,/(%#(,8Qh�������������lXA65CO]u���������������������������������_A9eU4,7$%%)-#(;6@U^]O8-2'*.+.(+6>BA==>43.914;E>:<8,3.7^C'4:<5*4MMRI69:<<:Poh8&%M���tl��j�r[dUG;BDi�qy�{w�M���&",.5;:41/5?1>?63.9500438,.,-24@KUVUVemsvtyz�}~�z{vmW:1BTaagmz��������������������������������������������������������������������������������������������ÿ�������������������������������ɉfx������rz�������������������������������������������������������������������������°���xqqspkfeg_^ZT^`bhd^]^UMKKTS]cfonkihb`bY]XV[X[e]d__^a_[QK**& $$(2Oi|������������r^A::DI\q���������������������������������b?=`W952'('**+?NNZ\O>@0..0*,))++2BI58J=13/66;E@CFH;3)++G?17=2.)-S`a=105778Ef{Y6#%+HcpUn�so|�WTK;1?3^z�s��||s��Y&%6-1:3).'2=73010137/2-)350'/2:?JPY]bilutzyy}~{}|~{rbP8,DT_crv{�����������������������������������������������������������������������������������������������������������������������������ͫmw�����xovx|����������������������������������������������������������������������ƹ���|vponknea^aYZZd]d`bdYVRNIOSUagllokfb\^ZX[YXZ\^bba_[bh[UQH'')&(( '26Jet������������w]G9;?K]q���������������������������������hAH]\/=22**1*0DPPOD6021/102300,29EB8CNA;73<>:D=DE>:;0,/?I:H9(**4Lnh8)+.390C^h_=C**1?:8P_lt~�jRE<,93IWt�������9$-21;90-),;>7044.32.:+//3/.1/8=CHP^ajmqsvvy{�~{}z{|oVD67N__br{������������������������������������������������������������������������������������������������������������������������������Կ~z�����ijmsyqxx{|��~������������������������������������������������������������������vtsrnkg^bfa]YXZ`f``_UOTKJRXXgifgled_a^[YWT^V]\`^_]acfZTKE((%"!!-)+5F[r������������pdC2;?NXp���������������������������������k:N]a398+*1+128=7<44392,3,050,11:C77OIE7610<CB77?7E?=38CFA4/'$0>UoW5,,'+74GjkbACO*"1/,68Db��nR9,01?EH�|�����j),324;=.0+4@69A450370-.+4.0*1,8@KPPUdpmmpus{z|z{|{yiR7/CUcXkt~�������������������������������������������������������������������������������������������������������������������������������ʗz���{vabgkphoputw~�~������������������������������������������������������������ɾ����xrnqmljje\`S^[]fdf`VTXQLOSZ\dhijbg_`]_XRX]WX]`a_\Y^b[[TG?%%)#'#&+%.Og������������v[F:;=M]p��������������������������������b8G`E=:2))1*2+8223.0500/1),<.*.4;=2=J>A8<2B=O:=.8<2496?:>.',#$*;[gA7/()-6LWuyoZ4RM%.A30)(7Ps��[<,7;SO4Yqx���z5!'-00;/+'&2F7472,1220*((,05/43:@NJOZhoqstuuz~��}{{yo\B12EV_`m}��������������������������������������������������������������������������������������������������������������������������������ѭ���vo\VX_o^gjnkquwu{����������������������������������������������������������Ÿ���|utqqlibe^[[T]^fib`XPJMJOT[]abikgdifga_[W_^Zbaea_\\_XXPID;''&*' "(&0Ni�������������uaIB==LVn|����������������������������}���];K]@4A6.*))(-./2,1370,*.,7>4+2=K59CA97647?LPC9.-4915AD7,+)'&)+GhP1461,+6Hk{xwoC6_=+=:3))$>]��^3/5BWYF\BW���[&!13196/'%*9?8334*+7/,,%.(/</+1<FIQUcknonvvxxv�zyylPB43M\[iu}��������������������������������������������������������������������������������������������������������������������������������վ���rjiVNS`hZ[\cejgnmwx{~��������������������������������������������������������´���uqqnngba_[W]Z]`ccbbQNMRMTYYegfheeac^a[XTU_[_bbfc_[`c\OMF6='''!#)*3Oi}������������pZG;@AM^n���������������������������������dCR`ABK36,1(0-.141<3.1.+,*.7.+;K>,@G<63>:9D`UK;3*(1+/13/13.+&'+RZ7,766//6Fd|yt�i8CU<040#./6Ex�u;3/>flphKMU�{K)'105D</%(&15/13.,'0,(-+-,26:;7EGLSZcjoqttut{z}{zyviG849RY_i~����������������������������������������������������������������������������������������������������������������������������������ɚ��gZ\MKOUgSQX]^^dcnopvuxx~~��������������������������������������������������������xqqhhd_XSXOUV^aeg[WNMBFJU[clmhfea]`acZTWZ__ekhg_^[YZVKGB>4%%'!#!$#+5Fgs������������oZD==AP]l������������������������������|��aHMaI>D,'(-.,32354-80/0*1,0032=H91EJ=40.59GPRH;.,*1*)/871,,)+&4PY0'1AC618=Oy}{}�I2EL@,' '/7<I[bG1)=\xy\[R�:#)33<<5%5+14.03/2..-)$''),49>=CFFOU_iposwsruy�~{{yqVD62=Q\an�����������������������������������������������������������������������������������������������������������������������������������Ӯ�uXRPNEONbLLRWUVa_bcfgkmpqs{wyz}���������������������������������������������ż���~uplgf[VMOMNVY_febZSMGEKSO[anfead_[bd^\]Y_[ahficZ^^TVQL@=A5##$!()#(0G]o������������xaB>BBJWl�����������������������������|�waSN_QK@-%(*)/3:;A6/160:+-0,;6<FA38E@:2559:LAIN972'0(*761/,()&(;ME),/>KP?7<Hd|�j�s459?E;'*-8@NE9B2*@V~n\dh_�u/'*30481).(/2+,/629)*#&%+4-4;CEDFMO]gnrptsxt{zz}}~{vbL1/5NX^bw�����������������������������������������������������������������������������������������������������������������������������������ع~dQRQL;=IMECPQPQZY]YU`bfcinosvuqu�|��~�������������������}�����������������������yumefY[WMKXQ\]`c_^WIIGJMURckkid^`_ec^]_\V\^hjiia_^]R[NMD<6;$$&%##"%)0<Ui~������������jK?<:DTl{������������������������������omQESSU:+%&(24:B34--,/,/.+/4=?DD429DB@03219B9AV;5300./*-',7-*((9:38(:9Chba_]Wy�t��S50/?XJ))9A2:40-89R�SDZnf}S(&0.324,"&/333+13,*)./$&-122<KCHIPT[jotrqwtsrv~}yzznU2(1HRZ]n�������������������������������������������������������������������������������������������������������������������������������������ĄZIIMOJJULBCFKMKOQ[OUYZe`_`akjhfnnuvtw�w|�����������������}y~����������������ǹ����xnhb[WRRGQPQ[ebe]YWH@HKS\_fhgb]__b]]^[_[^]]enjfb^^W\OKE:9:9##)!#!.33Mk�������������oP9:<ERo}������������������������������~kfWNR\dD+&-*+0B:.,-'+2-+/-34?GI50-@F?36876C@9DQ:765/,-(,%(61)+(>/-34SF+Iu|oj\d����uC:15HcK+1F47?<,<Hj�M=Zhr�?&-*1931'&*66-*21((2*+(&)-.02>HILNV\eusvywqvtut|vuyq]I0,9KW[fr�������������������������������������������������������������������������������������������������������������������������������������ΐWDNSSCYaMGJGEEDHLROQOTZ_WY\]^``ddilnnnosz���������������������������������ɽ����{rj_X\TSQENQUW[a^^TPDDNUWdaisf`_]Z`\_a`Y[``aeijc`aa_OIK=6859""!!$&3+6Ec�������������v\;5:IUk|�����������������������������~|si^JL\^D')*'->C3220.//,7./,5AL783-CE>4-38=<G?CH=;233.,/*.0524422--.JuA!0I{vp`a{�h��zV<09GUH4BJEJK8Ci��?->EU\32+)323)$&/90/+-,202),'))*8966GNNQU]knqvxyvtwtwvx{}eK6&+>WX_oz������������������������������������������������������������������������������������������������������������������������������������ե^IQTXFW_SIRPQNLOHQJILRRVSSRROXUX]\b_fcddon{z�������������������������������Ĺ����wk_\WVRIKGLSYbc`^ZSHHEPYagchmf]]_\a_]]\W__eciee`\d]WKKE<726<!!$#%'"%'6Fn�������������x`<5=MUi}�����������������������������|lk{\DRY_;'.+,0?<(**--+/,,,/39HH4-1/DE908105AJ>@G669946-./+0+89911%10Gt/"$2_t[P]j�pw��pUN70/ALCZV`[R^b�u.*64;777573.+*%(1A.((,/-.+-+.+1);::?HTOS[dspwsy{zqvtxvxts]9--0EYcfv�������������������������������������������������������������������������������������������������������������������������������������׸bFRTZTX_RSQSRNQSJRSMJJLGMHHNLNPQQSVN^^Y`dlmp}�����������������������������ʿ����xka_UQKHEJPTV^`ZWWQOKKPS]dhkgcd`_Z_a]Y[Z\g\fioi_gbaZWOEI@:-54''%%""'0Go�������������~kC<@FWgx�����������������������������r`p�`D[[`8(##,37.''0.,(--,..@EG@3,./=GA02335?D@DG?7=6B<+))&//12544092BU& "(DfaITd�d���jpX*17WgZm�sb?=Z=.00-/0760>13-)&//51)-++6,.),5)+./<:?JONW_kqwzxx{vttywwuqcC/*&2E^ily���������������������������������������������������������������������������������������������������������������������������������������yMJTVQ`_UZ^YTWRSMWLNDI@KGJA?DFJHLGKHQPJISWaeuw~���������������������������ź���~pbZPLH<>>FIPUX\ZSVOJLLP\acln^V][^`]_d^V[Z[aegidX^b^\QPN?6:335''&"!!""*4Gg�������������{jE5=KSku����������������������������^Rq�eSY]_9'%)2;4)-1/..)-),0HHH?60/44LK9/04439FA<GC:8EB<5)(&63423:8461-3%&&'.NV^O`u�q`����xD>LUgb\��j@74('80++.487HA3-++49./*+)&)'&)-+-+46=;DUUP]fiqvvtxwvv�yxuwjO7%'-ERijq���������������������������������������������������������������������������������������������������������������������������������������͏JFNZSd\_`b][UQXQ^QPNNHLC<>CE?D=?@D?AB>B@RVX\kwy{������������������������������si^SNJA:>=FKNUVSMMPOKTRVbfjmn^WYU\Z]\^]W[[`cghgga_\^XWKB;;:78<))#(! #")0Ef�������������|yF8;FSdv����������������������������qKRy}dQQY\3(#0;:/*0,4+)&*-1=X@<:5+*--PM873/-9BD<=G>AEC=3:4').7=*847520$$+$,4.);agZf{~q}����gJq�WjWf}s]H1'$0+..174;4,.(--21)((&&-*,'),))/37;;HXXW`hpuwrruxtvvxxulO5'$/4MWfoy����������������������������������������������������������������������������������������������������������������������������������������ԬXENZXd\_b^aW]^`WWRXLUMODKD?C?;>4:8624/44<BJP[ehptw����������������������ʾ���|j_TOF??9<AWPQYYLJFJQMU\Vkloif`[]_Z\X[`Y\]Z]efejfac][YOE??;9745++*)*&,-))1Gd��������������nH=9K\cz����������������������������dB_vv^STQV9)-.88('&'-,%*+09MR52;6/+/1IF61)16>GC;8KB6>;?97<6*)2>+-:>>:9,)/5<8.$,Glj^o��{s���hs�_f^ONcp]I/(/(+/036=3,.,)+61-)'&)')'')+',,2<DFKXY[gelvostuxqytvwt_D,$'/GY_hs�����������������������������������������������������������������������������������������������������������������������������������������׻jKSYY`\kcbca]`__[ZYTWYOKIIA@?485285*+311189@LQbcgv����������������������ö���o]YOL@=96:GQNPUSNMPMU\^`gilijc\[[WVZVUX]`]Zcegfgcba\]QL<8;8455322/..-52865Pi��������������lL><OXg|����������������������������eMZx[FCFF0)*5=2)(&,0,'+/7JE>9/4>60.0A@6--+1EPF?3:?698?84=:4123-')/8?=4*,280/$(,Lcmmq���xdu��knrPX_9CnpVD*')'0/7;1.*70-3..)**./+(")*-+*,3:CDQU[^ilqrrwnwwsxwsqhG2+%+7O\fr}������������������������������������������������������������������������������������������������������������������������������������������ˉNQT]_^dfdffj_Zb\Z[X[TRPMFD??=;:49/-/.1--,15;A\Wo���������������������������ykWMKD;9;?>IPMSRMOKINZ_chdojqie_[[XUYVSY]^[aebjibcb`XULI;:<83302000186<<697Ll��������������lO==G[dw����������������������������`Y[|�_D><<2'(55*/,//9,+2A595<//9B:,24=A;0.-6AEB>7<>=>;80*:<C=20,(-'2=>9=/371-(&,,C\jho���yeq��eYaMbZKc^NK-)'*,572+(,-03>;:9,-+2(&$***((.<CKGUYaihqnyrsvvxwvzvkN6+((4BTdm~�������������������������������������������������������������������������������������������������������������������������������������������ӦZNV[`admiiffefeb]^Y]XQOMHIJJ@<:5/41&'**#&+546C`{������ú��������������ǻ���iYRFJA:9=JJKNRXOOMJELWZ[^dkkff^_YV[]QS\TWZ[afcmfid^^TTJH8>=84335..9FCGECACDUgy�������������hU>AJZhx����������������������������\^X�hGA<1>+-27%,(+(31:?7-*022/7?-(,-17>8+*7HDG8??8:97=@808B5/&(,##'0AH:'+6:5//.+%<\gh����p��uIYb^yt|pU@(%&74770)'%1(+*-*)&$%.'%'((/20:GLFMV[bjmptstvvut�xyjV8,)+/>L^kt��������������������������������������������������������������������������������������������������������������������������������������������ԸfQV\_dbjkfhdfhffg_`\ZXVQRQHKE==7253..%'"#%'.6Ae�������Ľ������������������x`OF?;9?9BFNMTSTRG@DJSZZgeolkfb\YVVSSP[OP_Zaaklhggd\\WRE;:A66:439;;MQNLLJFHFVg{�������������sZE<NZkv���������������������������y`gV��kIC468''2A,+524:DB631)*105;;--2/.7F@21;G?>6D?44<9<@1320,*'(4+&).<J90&7P:0//11&1Re��������rPQer|m��iQ-(!(277+%(-+-*#(),),(%'+&0*,04;JKGQWadilstsqwvvrwwo`?/+)*5M_dw���������������������������������������������������������������������������������������������������������������������������������������������ʁTVX\aejjhlphghg_dcZa_YXUSKRH@9>9.10*2$%%1&#*Ds�������ǹ�������������Ǿ��{]VKI5;<C:IGNPSNOKIBEKW\`nonja^[YTOUTVUXQRX[eejonrgc_\VJFC?H94446=IITVPTOTPNSZfw�������������ybICSThu���������������������������loc_��rIE28.'556,.7.GOH?0*)-+/.4?=6./754?>48?E<65AK97N7C>210./*/)43,'%+4<8.6]F5<311$$3Mh��v����xh\_ze?]�xl-*+,38-.4)2*.)-()(/&%$+*1))-.<JPOM[Xfhrvqwvqt|wzttcK4,,),AScqy����������������������������������������������������������������������������������������������������������������������������������������������͗XVV[`ebhmiilmiodee`ebZUWVPPPGJ?861)-/,,%# $,Es�������Ŵ�������������µ��bKJA?52?=?HIPMNPPFDLLTY^goqnrY[RZQUQVPTVRWY]eglpqkd`VXVIIGD??;44<?ZZ]XXXQSXW]apz�������������wdKCJZit���������������������������oq]l��k]K0/-%332076;AO670313)+0734<47.-4<5/<EG:1;CH887=DB3-.////'.3+,.'(5F94ML=5*/),)*=Hl�v�����siqic]Wo}v3+12451&-*+*-&&$,*$%%100*-*.5EPNMO[aenrtuzttu}xtx`D//((+8LYny}���~������������������������������������������������������������������������������������������������������������������������������������������԰fQS^^eaelikiphndgdb__aZ[^XVMHIA=F:0,/-*((&$*Dl���������������������¶��pQ>>76<77@DHINNMIIFIJR\_giksgb]VTPJSTUQRRTOT`fkmtuff`YZVOJPME@<>86<__]^XUSZ[U[hsy�������������kODRWiv���������������������������p|`m�z_TV/'&+22(:B>9<908--4,.+502-4*4/8+796BHB25=DM9;D;@=0/*1//1*-566,%#6LI5=O;521+11+DDCq�}�����s[eTdty�u6/.5--)/,+*,/0+)-*(# '''),+1>IOHLPVbhrsvqwswu{zrf>,*)@.:PWevz�������������������������������������������������������������������������������������������������������������������������������������������������vOTTXbhjmlfkkllehhg^a^TZ]VUNJQID=<;5/0'-%(,+Cl��������������������ļ��tYB6@65;A?JDLJLDDDGBKTXcfjknf`\[UURRLMQTNVXY\ckuqroigc_XRLIOHD><:9;BYYZ`]\Z[fb]hwz��������������pTKWbes���������������������������rpap}|c][9-,((6,2>2/340,,3301200-3313113022DA8+/>IP;?I<>AB*,/0)*,)1897,(';PF5G=7<4/,55D@CF[t~�����eGXg�xK2-56-1&/+*,+++*/($%(##)1//17?MMMKR^hgustp~vuwzwbK*($*-NNZctz�~����������������������������������������������������������������������������������������������������������������������������������������������ȋMPUZbailljlnllihbb`j]WZ\[UXQJRKBB@;/-(-*)+-Jp�������³��������������uUG95655:=C?EQSCAECELPSabgmmnj`XQPTMPLOONOXX`ahjruveb_`YUPSOTDA>8<;ECTTYYZUZ[dbdl{���������������sZERbfq���������������������������fmbr|v[VR>--*442/,+.1156,--0*+874C?1423*-*.;12/9?BN<4B71<<;9*+/-2*,6A@72#0=K;JA=<6:BAA9>GO>FJd�u���^bwXLA3/35/++*+(.-(-01(""$#%*-6..4:EIMPSTlkjtz}svqytuf>*$##,=LVeo{}~�����������������������������������������������������������������������������������������������������������������������������������������������ТbJQX^_fkfnkkmmpkkhcc[d[_YUNPRPJH?F;53.,5199Gl�������ƻ���������ĵ��wZA;875167;EFGPNFCAFMITXakjkib\XQLHMJJOJKOTW^ccekrptjb_^TSTVVQM?<;9;DBVV[^[Y[bcfnr{���������������w]GQ`gt���������������������������dnft{vZXQ47.39-)-2..410-.1'3+.456A<4203/10*0+03:HFR;1:72>AF@-(011%&69?F:%-2:AIJ,621?CV:;AJU:;HsLh��{x{>40*013/33).65)+&2)(&"!&'125.6<HIKTZX[ijpq}ywxsuo[>/#"!*4OWfku~������������������������������������������������������������������������������������������������������������������������������������������������ԶkMSV^`hjninmklhehbkc^c^\^XRUXUMFGA>;644-078Jc��������������ƿ�����yXE>6334456AGLCLBAEDNNTZ]ckkl_cfSQLKLPRRMLRPVZcklrsshghe[VTQRSIE9:>@>C@VV^ZWbcbelnu����������������w^HY\ft���������������������������\Yo{xq[XJ,...90-+0.1+29/.2-0-2627A;.,:3760/*,+2<;?D969/.FHRS51271+%/C;UK8*./8IX33;/5Gh[70ESYEMwGHdx���k4+,/16-,)1+/7+*+/,,)$"!)+,356BOLGFV_chinwyvsuurY:,!#*2=L\chtx|}|�������������������������������������������������������������������������������������������������������������������������������������������������ȉOQVXY\egjnqqlmhhhgcbb_\_WUWWPMLKKCBA?4;6:>IZ�����������þ�������viOE@24695:@EELEACBHGWUb`bfhgfa]]WTJFPKKNRTRUZ`hhlrulia^\_VRRLPDE=:<GHGFRRXY``aiimuy����������������yeJM`ft~��������������������������VOqvmYS?-'-A/+-3:/0-4../160++2.4A<902-500235.7N;<E71,34KQZU-(477(!)<@XaG/,07?^L,:/.@]nK08@g]hPBUfy��s@2330//-20/21.*'+,*'))*2--/8:IKEMQ^geenqyywpqgN*)!'+2@LRdery}~{|~}�����������������������������������������������������������������������������������������������������������������������������������������������ΟaQTS[a^gfimloihigl]]ae^b^YaUTRKHTJHFCBDLJKO`�����������ø������t`TK:624496@@BJL>AAAALTX_anihig\XZMPOJSLMLRNQYeblrruohea^^bVYQIDD>4?=DJGEIIV]cckkltz{����������������{fKR`gt���������������������������ZM{~wh\L4))(83105/,-03(4-;:3**906A70-.44-*013<BP@DT@+248P[WX2,./2-'$5IXoYD4044Qb-0<89Wm`6:Dcv~�^7ESS]mhP;,.5.,0*/,+-2*)+'(%%/%/A13=JMPOOadfhblmwtrfW8'#' '3IW[ehksz~{|��|�����������������������������������������������������������������������������������������������������������������������������������������������ԱjKTV][`gcgkjkginge`a\gdc[\\[SPPOQNIMKFNKJPWk����������ȿ������rZKIE<7665D?EEHHICB<HMQRXcjmofeeaUULSJHLKMLOQZbnipspokff^Z^^ZROKLC@<ABIA<;DDQWcgqpsrtz����������������ybQS[iq���������������������������cNx�sl\P4)5*:6)/354-18+07@85-4159C81*-0,5..5F>QQBOL=,-9=LVVT=*),76+%/THYgQ>7:9=mC*8K;BXWOCPWx��v@:O05Fbc?*1.,./)*114-++%*#"#%+3/2;EFNLQYhbfmkjkreO6'".#+.;O]bfipuuw|x����������������������������������������������������������������������������������������������������������������������������������������������������|NNWZaf`cdihkgffleh`\]ch``bc_SURSNMLUOVPOW\s����������ƻ����}b]UM<@6545A?CLQJHFDADKRVZagjkmei`[TIIKHJIORMV[[chkouqodhb^XbZYQOJD;=CFFB>7<??Q_\fqrvruu��������������vlQQ_hs���������������������������lKi~wuhR+,--43*0>:/-@6-.9A51)52168=721/',-1+8FZT=`^<20@:FRV[S;*-+-.+*C[OGTHA<H2]b2.DE:4QPMEP[���kMX:$3MiG,41(4.+-64-)*'%*&###*'+07FKMQU[eenfdhTN:+# ',;JU^dfiosuvzz���������������������������������������������������������������������������������������������������������������������������������������������������ʎQSPZ[__fhbmjefgkjdcecee^c`bXXSWTPUSZXZURR^u���������������p]UMJC?<6<;7JECJML<ECENVWWedpjihe^\TOKGGAKLPLOW^]_mpttrkehh^W\`XJTH9;A=FNMEA877PX]fpnsstpuw��������������viZ[^in���������������������������mFayllgL,'&-2'+.3;29?@*(:B:9-219F9G?6+&'-+5*3FSEAzT;4-A?Zb[YTI.'/(1,,BaXA1BF54,FvR+;BM10[RJ@Xj���H\I&5HX[4(*%&&-,13.&'&$/'$%%))-:@QQTR_be_`[M>,0-&./-@HTbeihnsvxwx}�{}{�������������������������������������������������������������������������������������������������������������������������������������������������ΠZNRUb_bdeeehbhioocg`_`c\bbaZZYVSX\^W^]Y[YZx���������õ��}iUQDA?<B:4:?>J@NFJFCALHRZ^dihlifa`ZcTJFEHDEDSQT[]]inqrsoleifg_\^PHHB6@D@DHEK@:77MU^hpoqsljow��������������wcUX`gn��������������������������pDVvmka>,'%)0+.-0>.-?:/3;C9.*3.1+ELGD30(-3/.6PRB<�a@0,7<NVcTS[?'*3.6-0\_G*-810/Kzw>2?DC9ZOUBFa���HOG(9IBS9))'#(-11-)&+$%-/&,(*,6GHPPWR]ZRC:9J*&.'$2;CT]`ddhlouwwvy}||~{��������������������������������������������������������������������������������������������������������������������������������������������������ҲhIMTY`a^ahcdfbhdggfb_idacgedUXWV[Xb\^`_[W[q������������za[NNKL@AC;:BIJMTMJOJFIFXVbhlknqiie[YXJKF>BI?DMSV]^_kqrqkqmgec`]]SLI@89>KEDFGE:600BRV]fifggfgu�������������yfZWajq}��������������������������vPUogm[3,+*+0902>51366'4<G79+)0043LHG6/,/33*;UUA>~`;0/:AWXi^P^L-(.74,*FnW<#%,769`�[(4B7+ILS[Oly��nXE7>R4FB2,*%16/2*%),-(/41++05:BDIPRF:721,4&%,-6;JST[cfcimrtz{~x{}}~������������������������������������������������������������������������������������������������������������������������������������������������������QMQSZcafedfamfgjhccdggbge`b]^b^cbbgd]^[^bn�������¹���bXRHPUMHFE=EMIFKLLGJCKMQW\dmsnpsh_`RNLOLG?>@<HMQ\a`elqpponjjgca`XOEC8A?IEBBJF@?9++=HPY_Xc^bchs���������������jXV^cq��������������������������{]Tc^`[4(,.)*+6/3:/:;-*-IE<3/.510/MR6).005./4KU<<�a?*(9DVOmhOi^?0(/1,+4]fS&'+=A2D��B.K-69OHlgls���{V*2D(4T/&$$-)-,((.?(',,)+/258846650+')(()+.2EPNX^^afkknqsux�|{|{z|����������������������������������������������������������������������������������������������������������������������������������������������������̟WLUYZY\accdfelmlkhdfkekidfb_]egdfgohegc^\l}���������~`VTT]U^POCEJMOMNMLNJIFMK\_^gktpjka[[MPOSQGF?C=JNWaeiinyqppoiihcb`WPBC<=DMIC?@@<<7--7DIPU_YYb`lv{��������������mZV^iq~���������������������������`NLY]K,)150-31.883:;3'0?A>;/+343-PY6&-52031AIH3BtS6,!1JSQizffkYD7.30/+MpY+*)6AD1Y�o1BD66CGcqoqn���iC/801I/#-)(0?.+4.0..(3////111/'/-4'%)-9?DRQZchhmmolpsvy|z{y}}||~�}����������������������������������������������������������������������������������������������������������������������¿�������������������������Ь`LRTXZZa`b^e`jhmjjdghjdfbe^_cbfdljilmjdjdjs��������p_ZPSHSNMDPINKKLHQRNJHEIRUYdghpsrbbZXUQHJMF@@@BGPS^eljmvwqtxrifhe\WPEB@@C;DE=AE=29/,,6C?JOV]Xe[ip|�������������tbY_fo����������������������������fEIXM8*235*'+...41-4:98F@G4.31260Pe6*'335-97FE4JlM=)&3NdUh~xfu`I8<B60.8ihA(G",A96u�N3X63=R^xoqk���}f>;#,E7#!./-,&&4403-,1,,,,$,,)(()(6::ADMUNU]`Ybnpsvz{��~��}��������}������������������������������������������������������������������������������������������������������������������������������������������������лqHPSYUZ[\c`aadgolpfkkljjfeeibjigkmpoomekifo������xgYUTOHKJKOKMOURUOLMKGGOPOSa_fljood[[XFKFEEF@=?@IO`ghskqstywqtifbi[TIHDBB><@@B@B9:10,,35=CWQ][_^`oz��������������yiZ`kp{���������������������������j=@OL5)(2.0--0'1/7/9//8@;<.594962Ri2,-64.15/>>7ZpK6/(58]bituclgK4-/*5C.bpa0%-"(M5A�yALM:=HUlzzc|��oaL53J)***+)-()+1-3:))*1(&%'(*947?LLNRVVY]]deciprvvywy{{x|}�����~���|�������������������������������������������������������������������������������������������������������������������������������������������������ĆJMRSTVZb`cfedflgjjnqmhfcbfegmmlstorlojjnlps{}�~xqfXVVQNQSPNUTSVZZPTPQMAGITXbeoggjhf^[QPJBDAI:;:BFRTchfnprwssrrnefg`ZTJJH;CA>89;?6781-332;>:DTYRYZZjs}�������������yu]cmrx���������������������������o??NL.#-8+.'-2.33-/1.:9=?>4?./D72Sj?(,97/35EFI<`kB5%,03]_iotmdjM6-'"1[ASpJ"$,=P4Lrf9BN54N�uj�dJe}nlg9):+*.4.1+*-,)*$&+%($%./21;?=?GQST[^XY^cimlxsux|{x{zzyz}~�|��������~���������������������������������������������������������������������������������������������������������������������������������������������̝YFWRWV^]Ycbagfjknhmlnpjiiifdroptxqqpnmrrompprvqoic^ZTUXTRUTU^\VUPVVPNCKFOTX^edhls[fSQINGFCF>C=@@LR\jkjomprw{twqjmi]YOIEFB>>@9=A<4552///955:BIPQYVYdt}�������������xna`iv|���������������������������n>:GR.+04+4-9JG1,,)826@ED;8=88@?2KwO,'/2*31=>FJ[^:4'+,6JYgbl}nyd3'.%.O`Ii�n1%'1RU@[}]/PN1Gyz_{w?6`vjqL390.-69;=B99/')((&*()1;=AJEKSNYUVZc`^fosrrux}|zxyxy|y~|���~��~|�����~����������������������������������������������������������������������������������������������������������������������������������������������ϭgHROPS]Z\d``aeenmjrpmqlejklojxqtttxpxqprnnjqpoojgaZVXZZ_[W\db_U[YXPFJFOMPX]_hnmcb[XaSPGOILF<C@:IP[dlgsokrvysonine`\TOLKA?<<;<;=?663?822:86/ACNUWXSduy��������������ydckrz���������������������������j@>OF2290/*-:9547*+/28ACIJ9?38@=+?m\6%8.(00:@T]_T8/,+'5J^q[J}|xi3$/$ 2Y[`u�N+ ';9YJ:xz;1VL:dxbz}b8@oqaW66.---.1**(%!*&#,,599@FILMUXXW^`fecknotsxtvxvxzx{z|{~}�����|��}��~��������������������������������������������������������������������������������������������������������������������������������������������Ӽ|NNKTWRT\]abbfgnkmhsnnokiolsrtsstqtorstwqminfhhgb``[Z[Yaaa_gb_[UUXNNNRQQVY^gghgchTO[NOVKKJ@CA==OT]gilmuwxz}qqkhiebSSEKGB<88=?B<9687;0::;8;:=?INRQRWnu�������������|rfcmo|���������������������������^D<IH86280:(/4/1;#(/31:E86;K02<66:Pc=-3/,624;JalB+1.().>drZ<l~{wO,&) $Emin�e;"'=NIUu`.5FDGphpy�gLSiP]D3&&&,(N8#'$&,.*,45694CFOTV[YXegmnlmowruvz|x||}z{}z|z{������~~�|������������������������������������������������������������������������������������������������������������������������������������������������ŋSJHNZX][^db^fggnomspkmmpoptqyuwvrsorslptqnkgiig`\]^[\bfhhedi`WW]TOJUTQTW^bmjd`^XQUKMOJSKN>JHDDS]cgztou{wunkliea^TFHC>=>=;6?;5823:4322C:??@=EMMQL[nv��������������{maln��������������������������uZG;EH<JE11,'36*.60,695:D?94:;>>>34@eQ22.(-+.?Dfb8/(.+'2Ddnj=Jw�|i6"('%2dmf�oD-$ *>bVtwH#0CGerkwysiULDIG))&'+%7.*)(.1<-./58:;DNOVU[cblqpqpqppoqvvy{|{�|��|���~~��}��~��}���������������������������������������������������������������������������������������������������������������������������������������������������̝VFIRSZ\]]ccdhhhrnolkntpvrssvuyzzxtqttqqvmkjekifiebba^gjmjjgcb^XWRMRTTVV^acdaWPVPRLEEKLNDQKILAOSXbjqtqvzzyukkona^SMFH<:9<7A96340835.-55::DA;<B>EIJTgt��������������uhbju}�������������������������uNF:.AI@=46+1064,41/+<81<B875565AE;16[`8/+/0')BIod3/$%*)*=app@6i��{O1+*/1Eie�vRH*;WZa�f3%+?JeisqlUOD@5I-*.0%-0.+.21+/66/46ADKSZ\^e`lprpuutrztvxwz{||}{�|�������~����������������������������������������������������������������������������������������������������������������������������������������������������ϯaDDIRSXY^dbdhijllppqqnovtzwwqr{xsvorqxmopmgkhhdiea`eckhoqmllaa[VTLKPRW^_]de^SOMPHFJFLHJIIHAJNRZbfnwts|txxqkhie]ZTJAE8<6<;6:60450,0/7448;::4=B<=GDHfu����������¸��}ihpu�������������������������[D?16:>7-;;1.7>;--0-0:36@C579938>C=20MeU2(-17)?W~o;D&41.):hixC/T���f;83('QrexwHM="%#/DSJ�W*$)6VS^kykA1-'=4).4((3&54*-/232/9=NQT[]ddfnmmqtswsrstvvxz}~~}|}|z�~����|����������������������������������������������������������������������������������������������������������������������������������������������������������нxFCMVQUb]^fikjjinpnnnrr~vzxwtyxtpuuupvqqqplokihdbbcdmppqrjkd^[ZYTVQ\[Zbfbc]\WUMLDB@JHLFCQBHOMWejpqxrv�swuqibcV\VSFF>?<6;;9B84778275322486527E?BC@H`y����������Ǽ���id{r{������������������������whRJ:6??81320(,:5-(7.-438EA:337=>;?>0+AVi9*)+),>k�oC2#//14FulyC2@w��}T?7*-HUfe�PIO0 !#<VAQ�zK1#,=IQ]t~i@,)8E/*'(.8098/132612<JMT\^gbijsptrtt{sssutwww|}|~|}}����}{����������������������������������������������������������������������������������������������������������������������������������������������������������ňKAQUQYTRahhfmkjqhklqsptyvwzy{rstsrqrsuuooqrkiikgdgjorxuxojfabXVUS[bbb_ebbVYPPCAHEJGGIGDaEKVRafnswzz{|vsonmda[YSKAB><69:3:>1463838A@008?=327<?>>JJh{���������������pfpt��������������������������rh]@<976,4:>1+61..+0-7/7==5:9379IA>34:FiM&&+-2Gs�cB1)245*?ug}K?@f���m>2+$%9RivY-MB$!$0VPAl�d8%);WDNi|oaN*5S2%. +($)1137079>KMWW`^fgflprruuswtutttuyx}~x}�~}|z�|�||�~�|�������������������������������������������������������������������������������������������������������������������������������������������������������ʡTMMPPUXV\[VWZgpmkfliswxz{w{zwttxuvptssstlskkljkhnnqusuuqpjjb]^XVX]b``cfdeWUSPEDJCCPBAHKFGQ_Ygjmuz{zzvxolmi^[\NOFI:@4;8?:9735;9:7;FR116781047<;>=Hi|�����������÷��sitp|��������������������������tmNE>52(2=N:);03(14*@C646;4???C;BN9)34Z_%'/-.S��VF1+14/)Gsk�@BIS���uN,+(',>bnf.<L9&(+MOEHlV*)<Y;VbsRR_\JW2+2!$'&*'051:=FGNXU[Zfflllmnrpsuyx|uxxrv|y{�~~{{y�||}}����������������������������������������������������������������������������������������������������������������������������������������������������������Ӱf@INSQZca^ddehifljopsywwv|vw{wuywyqrttrtmsilomnooxxzyxtqqkiba``]```cbdZ``ZPPOQIHJKKKWLFMPSYfqqty}{}{vuljndY]WIN<?:9913=C>560.1>;DK\00515935<C9;:Jh������������û��{fss�������������������������{�wVG97//.9A228?1/.@1RB:<79874@?<@?C(01Tq<(3)+U��P?3,0*1-Tvo~7AWKh���T/)&)*3RdvL+;M>((;QWBHnp:#3_IGXyj>`spc+#& #$)+,34<DHONUU_fjohlooqmmrvxy{tvwrzzz~��||}~||}~~����������������������������������������������������������������������������������������������������������������������������������������������������������ҾCHJPQY\lkgfbkh`dnqjvzrwzzxvwxu{wttssqumqnkprrrrvuz{|zwsmie_]Z_a`hgcaaS[\TOSTVKKOQ\JHGSVTYelox{|}}�}wtfkm^^VSKG:>484148:9;K73<FFGNV//7527439=87<Gj����������������gnv~���������������������������q^?<55,,7>('285-,D/2?B?5=8B8>NBGGP3/,BkH84.0a�hNL<+2089[ut{/:WJO]��p?-,4(/Vgzg/-?O9+2M[GFO`W,.HN<Ww}Uen�xR3%$$#&)-.3>@INQ[]Xccjjgekkwpmrxxuyty}uwzz{|���~~}�}~|������������������������������������������������������������������������������������������������������������������������������������������������������������ƋLOQEVVYVZkegfbdjhhqvtwyxuutxv{x~xswutslqrurpuxy~�wvpkia]]_^^cghbZ\USXSZVWOXUIONEMMNPYbhouy|�y}vvikicWXQS@=942/,/33483E:=FMRR[^00946629?37:@Fh�����������������imu~�������������������������y~f]34221,/:+)6;5)K624=<-:A6@;KXEUCQB:8:ALH8)5g�YKK7.03:?Pjjy%3_MSE���^2+%0:X|d�P3.IG87;][>??W3'6MOQp|HT`v�vP/"'%&+*17:>INQXU[_affjkiqvtttsy~xyxyuxxw{z���|}{�|�~�������������}���������������������������������������������������������������������������������������������������������������������������������������������͠]EOMPRUSWY_chcdjhkqspswzvzw{z}�{uztuusqtvwxxsw{�~�~�yurjh]][]W__c]WYWWMOVOT[VOWQKSJKOYZ_huuy��}�|uonja^YOKG@=A7,,/;777:CB9AKNaZX_660/55279=378@`x����������������isux������������������������wihWW54870)5,-+38;0*8:<9C5:H:?>LSIYHOG117>AQ=1<��M<E>.35>>Lorx)*V^JHq��sC,#0;R�e~e4333DG9N_[AA;>(45MLRiQ?Q]��~`0$)*(/=@FKKNNZZ]\ioeilnvrqvo{wyz{xx~{}�z{�}|{��������~�������������������������������������������������������������������������������������������������������������������������������������������������������ҲiHHNUUW\\]Xcd`aggjjqrvstpvwx�}~}{~rwutpvyxw}|����}~wsoffdZ^dX__c[WRUMSLLTUXVSTRSNKSZWanouw~���}~|vmmh_TRRC:8159.56255:47@CNSXZ]^Z..224123;7:67DWw����������¿����dmo}������������������������sd`VN37<C.',&'.;?9/+:I<2M<9D6C>KN@]FLO4.75?TE5O��A2E>01D?9Qwvw+(K^KJLh{�f=),;O�y{i80'#(:<MZWK=5E,**88=`\KNWf���\13617HINP_SSX[\ajmmmpqtyvxsvyz}vy}zx~z|�}~~|��~}������������������������������������������������������������������������������������������������������������������������������������������������������������{ULQSW[\]`[W`V\ekoivstrkuy��~x}z|xwyxyzw��������~|uuqh_\b\][U]XQQKSPKNZVYUXXVRSSMMWf_iow~����~~zoe`WPNH;9727-4141558=>GKPY]dfb`++2/6/21<5-78@Rp����������������imx�������������������������xIWZ?/9G=0&.+,/@A=)(6M25A9EF6??MG<LFKU8666<UWGi�w</<I8&H?5Hwss+"=[JTFO^�xZ;7-I~�ec3'/*'2=>[DRJ?BA.)4,9SoE9LPlndtZ793=ORQNUYSXYcbjhinqpuruwvsw|}{z}||~|�~{{~}{�~~��}��}���������������������������������������������������������������������������������������������������������������������������������������������������������Ŋe\`]SXY^^]WX\daeolhnmwqu|}����~|x|yz{zxx~��������}}srid`\[bYVQWRLOHKKOW]_aVZZTUQUOT\^fjtv}~��}�wui`XONF?:536.-1-04.45;FEOP\`dhdb,,736/23;3/355Om���������������xinw�������������������������N_^E85G0+'+()6>F<"&6I+/KG?U8@>HF9FHETA95:IhaF��\:56LC%3;:Hrqq2&0QNKDH?v�v];2@�]U-$252(02EBOQC@G/(654Jt`-)>_fISyZ:9KSQRRT^Z[Y]fdkklnnpqpyvzv~yyx~{}z|~}����}{~��}��~���������������������������������������������������������������������������������������������������������������������������������������������������������̝vmpf_^X][]Z^b^abkhjifx|~������~�y}~~y}���������|wvld_V\ZYTQNHMJHNEQVY[Z]Z\\TWSPTY`^fpw~�z���|{wqe`TK><;::33,)*2.46;DHLS^Zahdhil,,7B6/23;3/355Om���������������xinw�������������������������N_^E85G0+'+()6>F<"&6I+/KG?U8@>HF9FHETA95:IhaF��\:56LC%3;:Hrqq2&0QNKDH?v�v];5@�]U-$252(02EBOQC@G/(654Jt`-)>_fISyZ:9KSQRRT^Z[Y]fdkklnnpqpyvzv~yyx~{}z|~}����}{~��}��~���������������������������������������������������������������������������������������������������������������������������������������������������������̝vmpf_^X][]Z^b^abkhjifx|~������~�y}~~y}���������|wvld_V\ZYTQNHMJHNEQVY[Z]Z\\TWSPTY`^fpw~�z���|{wqe`TK><;::33,)*2.46;DHLS^Zahdhil
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/make/make.emx	Sun Aug 12 13:14:34 2007 +0200
@@ -0,0 +1,20 @@
+CC = gcc
+CFLAGS = -O2 -DEMX 
+LDFLAGS = 
+LIBS = -lm 
+PGMLIBS = -lpgm -lpbm 
+WMLIB = -L. -lwm
+WAVELIB = -L. -lwavelet
+EXE = .exe
+MAKEDEP = makedepend
+GROFF = groff -Tps -man
+RM = rm -f
+CP = cp -i
+O = .o
+LIB = .a
+LIBPREFIX = lib
+BINPATH = bin/
+OBJPATH = obj/
+DOCPATH = doc/
+INCLUDES = -I/usr/local/include
+INSTALLDIR = ../os2_bin
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/make/make.linux	Sun Aug 12 13:14:34 2007 +0200
@@ -0,0 +1,19 @@
+CC = gcc
+CFLAGS = -O2 -g -DLINUX
+LDFLAGS = -g
+LIBS = -lm
+PGMLIBS = -lnetpbm -lm
+WMLIB = -L. -lwm
+WAVELIB = -L. -lwavelet
+EXE =
+MAKEDEP = makedepend
+GROFF = groff -Tps -man
+RM = rm -f
+CP = cp -v
+O = .o
+LIB = .a
+LIBPREFIX = lib
+BINPATH = bin/
+OBJPATH = obj/
+DOCPATH = doc/
+INSTALLDIR = ../linux_bin
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/make/make.mingw	Sun Aug 12 13:14:34 2007 +0200
@@ -0,0 +1,20 @@
+CC = gcc
+CFLAGS = -O2 -DMINGW -mno-cygwin -I/usr/local/mingw
+LDFLAGS = -mno-cygwin -L/usr/local/mingw
+LIBS = -lgetopt -lm -liberty
+PGMLIBS = -lpgm -lpbm -lgetopt
+WMLIB = -L. -lwm
+WAVELIB = -L. -lwavelet
+EXE = .exe
+MAKEDEP = makedepend
+GROFF = groff -Tps -man
+RM = rm -f
+CP = cp -i
+O = .o
+LIB = .a
+LIBPREFIX = lib
+BINPATH = bin/
+OBJPATH = obj/
+DOCPATH = doc/
+INCLUDES = -I/usr/local/include
+INSTALLDIR = ../win32_bin
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/manual.lyx	Sun Aug 12 13:14:34 2007 +0200
@@ -0,0 +1,966 @@
+#LyX 1.1 created this file. For more info see http://www.lyx.org/
+\lyxformat 218
+\textclass paper
+\language english
+\inputencoding auto
+\fontscheme default
+\graphics default
+\paperfontsize default
+\spacing single 
+\papersize Default
+\paperpackage a4
+\use_geometry 0
+\use_amsmath 0
+\paperorientation portrait
+\secnumdepth 3
+\tocdepth 3
+\paragraph_separation skip
+\defskip smallskip
+\quotes_language english
+\quotes_times 2
+\papercolumns 1
+\papersides 1
+\paperpagestyle default
+
+\layout Title
+
+Watermarking Source Code
+\layout SubTitle
+
+version 0.4
+\layout Author
+
+Peter Meerwald
+\layout Address
+
+Dept.
+ of Scientific Computing, University of Salzburg
+\newline 
+Jakob-Haringer-Str.
+ 2, A-5020 Salzburg, Austria
+\newline 
+
+\begin_inset LatexCommand \url{mailto:pmeerw@cosy.sbg.ac.at}
+
+\end_inset 
+
+
+\newline 
+
+\begin_inset LatexCommand \url{http://www.cosy.sbg.ac.at/~pmeerw/Watermarking}
+
+\end_inset 
+
+
+\layout Abstract
+
+This package provides source code for some watermarking algorithms in hopefully
+ portable C code.
+ The programs can be used to study watermarking techniques, perform comparative
+ robustness tests and develop new attacks against embedded watermarks.
+\layout Abstract
+
+However, the provided programs are by no means suitable for real-world applicati
+on (i.e.
+ copyright protection) and the code solely serves some educational purpose.
+\layout Standard
+
+
+\begin_inset LatexCommand \tableofcontents{}
+
+\end_inset 
+
+
+\layout Section
+
+Introduction
+\layout Standard
+
+Academic research in the watermarking field has grown dramatically since
+ approximately 1995.
+ But surprisingly, source code for the proposed watermarking schemes has
+ not been made available.
+ The reason is most likely the security of many watermarking systems lies
+ at least to some extent in the embedding and detection algorithm itself,
+ and not in the keys used -- violating the Kerckhoff principle 
+\begin_inset LatexCommand \cite{Kerckhoff1883a}
+
+\end_inset 
+
+.
+\layout Standard
+
+With the availability of public robustness test for watermarking algorithms,
+ StirMark 
+\begin_inset LatexCommand \cite{Petitcolas99c, Petitcolas98b, Petitcolas98a}
+
+\end_inset 
+
+, Unzign
+\begin_float footnote 
+\layout Standard
+
+
+\begin_inset LatexCommand \url{http://www.altern.org/watermark}
+
+\end_inset 
+
+
+\end_float 
+ and very recently Checkmark
+\begin_inset LatexCommand \cite{Pereira01b}
+
+\end_inset 
+
+, the situation begins to improve.
+ Now it is possible to measure the performance of watermarking systems.
+ 
+\layout Standard
+
+In order the compare and evaluate new embedding and detection techniques,
+ it is also necessary to have some reference implementations of the older,
+ now often called classical schemes.
+ In this work, we provide some implementations of watermarking schemes,
+ some of which can be considered 'classical'.
+\layout Standard
+
+It was the goal to capture the main ideas of the proposed algorithms, as
+ layed out in the respective papers.
+ This is clearly not an easy task as some papers do not disclose all details
+ or state which particular parameters were used to obtain the results outlined
+ in the communications.
+\layout Standard
+
+I am very interested in hearing your comments, complaints and suggestions
+ regarding this software.
+ Moreover, if you have source code for a watermarking scheme not yet covered
+ or some useful utility I would be happy to include your code in this distributi
+on.
+ Please see the contact information at the top of this document.
+\layout Standard
+
+If you use the accompanying code, please cite my thesis:
+\layout Quotation
+
+Peter Meerwald, Digital Image Watermarking in the Wavelet Transform Domain,
+ Master's Thesis, Department of Scientific Computing, University of Salzburg,
+ Austria, January 2001.
+\layout Section
+
+Software
+\layout Standard
+
+Most of the software provided herein was written by myself, as part of my
+ Master thesis.
+ Some contributions were made by Vassilis Fotopoulos
+\begin_float footnote 
+\layout Standard
+
+
+\begin_inset LatexCommand \url{mailto:vfotop1@physics.upatras.gr}
+
+\end_inset 
+
+
+\end_float 
+.
+ The software in the archive is organized in the following sub-directories:
+\layout Description
+
+Fotopoulos/ contains contributions by Vassilis Fotopoulos
+\layout Description
+
+Meerwald/ contains my work
+\layout Description
+
+images/ contains the Lena image in PGM format; the default parameters of
+ most algorithms are tuned to work best with that image
+\layout Description
+
+linux_bin/ the place where the Linux executables are stored in the binary
+ distribution
+\layout Description
+
+win32_bin/ the place where Windows 32-bit executables are distributed; tested
+ with Windows NT 4.0 only
+\layout Description
+
+make/ contains the 
+\family typewriter 
+\size small 
+Makefile
+\family default 
+\size default 
+ options to build the code on supported platforms
+\layout Standard
+
+For the purpose of this software package, a watermarking system comprises
+ four parts, namely: signature generation, watermark embedding, watermark
+ extraction and signature comparison or detection -- with the exception
+ of Vassilis's code; there are only cast and test programs (corresponds
+ to watermark embedding and detection).
+ Signature is used more less as a synonym for mark and can be thought of
+ as the payload (at least for some schemes :-).
+\layout Standard
+
+All programs only accept the image in NetPBM format and will also produce
+ only NetPBM-format files (see section 
+\begin_inset LatexCommand \ref{sec:prereq}
+
+\end_inset 
+
+).
+ Unfortunately, most programs have only been tested with 8-bit gray-scale
+ images of size 
+\begin_inset Formula \( 512\times 512. \)
+\end_inset 
+
+ 
+\layout Standard
+
+In order to simplify batch testing, the programs allow to read either from
+ a file, e.g.
+\layout Standard
+
+
+\family typewriter 
+\size small 
+wm_cox_e -s cox.sig 
+\series bold 
+image.pgm
+\layout Standard
+
+or from standard input, i.e.
+\layout Standard
+
+wm_cox_e -s cox.sig 
+\series bold 
+< image.pgm
+\layout Standard
+
+The output is usually written to standard output, i.e.
+ 
+\layout Standard
+
+
+\family typewriter 
+\size small 
+wm_cox_e -s cox.sig image.pgm 
+\series bold 
+> wm_image.pgm
+\layout Standard
+
+unless redirected to a file, e.g.
+\layout Standard
+
+
+\family typewriter 
+\size small 
+wm_cox_e -s cox.sig 
+\series bold 
+-o wm_image.pgm
+\series default 
+ image.pgm
+\layout Subsection
+
+Featured algorithms
+\layout Standard
+
+Currently it includes the following watermarking algorithms
+\layout Itemize
+
+Bruyndonckx [bruyn], refer to
+\layout Quotation
+
+O.
+ Bruyndonckx, Jean-Jacques Quisquater, and Benoit M.
+ Macq.
+ Spatial method for copyright labeling of digital images.
+ In IEEE Workshop on Nonlinear Signal and Image Processing '95, Thessaloniki,
+ Greece, pages 456 - 459, 1995.
+\layout Itemize
+
+Corvi, refer to
+\layout Quotation
+
+Marco Corvi and Gianluca Nicchiotti.
+ Wavelet-based image watermarking for copyright protection.
+ In Scandinavian Conference on Image Analysis SCIA '97, Lappeenranta, Finland,
+ June 1997.
+\layout Itemize
+
+Cox, refer to
+\layout Quotation
+
+Ingemar J.
+ Cox, Joe Kilian, Tom Leighton, and Talal G.
+ Shamoon.
+ Secure spread spectrum watermarking for multimedia.
+ In Proceedings of the IEEE ICIP '97, volume 6, pages 1673 - 1687, Santa
+ Barbara, California, USA, 1997.
+\layout Itemize
+
+Dugad, refer to
+\layout Quotation
+
+Rakesh Dugad, Krishna Ratakonda, and Narendra Ahuja.
+ A new wavelet-based scheme for watermarking images.
+ In Proceedings of the IEEE International Conference on Image Processing,
+ ICIP '98, Chicago, IL, USA, October 1998.
+ 
+\layout Itemize
+
+Fridrich (2.
+ scheme), refer to
+\layout Quotation
+
+Jiri Fridrich.
+ Combining low-frequency and spread spectrum watermarking.
+ In Proceedings of the SPIE Symposium on Optical Science, Engineering and
+ Instrumentation, San Diego, USA, July 1998.
+ 
+\layout Itemize
+
+Kim, refer to 
+\layout Quotation
+
+Jong Ryul Kim and Young Shik Moon.
+ A robust wavelet-based digital watermark using level-adaptive thresholding.
+ In Proceedings of the 6th IEEE International Conference on Image Processing
+ ICIP '99, page 202, Kobe, Japan, October 1999.
+\layout Itemize
+
+Koch, refer to
+\layout Quotation
+
+Eckhard Koch and Jian Zhao.
+ Towards robust and hidden image copyright labeling.
+ In Proceedings of the IEEE International Workshop on Nonlinear Signal and
+ Image Processing, pages 452 - 455, Halkidiki, Marmaras, Greece, June 1995.
+\layout Itemize
+
+Wang, refer to
+\layout Quotation
+
+Houng-Jyh Wang, Po-Chyi Su, and C.-C.
+ Jay Kuo.
+ Wavelet-based digital image watermarking.
+ Optics Express, volume 3, pp.
+ 497, December 1998.
+ 
+\layout Itemize
+
+Xia, refer to
+\layout Quotation
+
+Xiang-Gen Xia, Charles G.
+ Boncelet, and Gonzalo R.
+ Arce.
+ Wavelet transform based watermark for digital images.
+ Optics Express, volume 3, pp.
+ 497, December 1998.
+\layout Itemize
+
+Xie, refer to
+\layout Quotation
+
+Liehua Xie and Gonzalo R.
+ Arce.
+ Joint wavelet compression and authentication watermarking.
+ In Proceedings of the IEEE International Conference on Image Processing,
+ ICIP '98, Chicago, IL, USA, 1998.
+\layout Itemize
+
+Zhu, refer to
+\layout Quotation
+
+Wenwu Zhu, Zixiang Xiong, and Ya-Qin Zhang.
+ Multiresolution watermarking for images and video: a unified approach.
+ In Proceedings of the IEEE International Conference on Image Processing,
+ ICIP '98, Chicago, IL, USA, October 1998.
+ 
+\layout Itemize
+
+Piva/Fotopoulos [cast|test-pv,hart,sub], contribution by Vassilis Fotopoulos,
+ refer to
+\layout Quotation
+
+M.Barni, F.
+ Bartolini, V.
+ Cappellini, A.
+ Piva.
+ A DCT-Domain System for Robust Image Watermarking, Signal Processing, vol.
+ 66, pp 357 - 372, 1998.
+\begin_deeper 
+\layout Standard
+\added_space_top smallskip \added_space_bottom smallskip 
+and
+\end_deeper 
+\layout Quotation
+
+V.
+ Fotopoulos, A.
+ N.
+ Skodras, A Subband DCT approach to image watermarking, X European Signal
+ Processing Conference, September 4 - 8, 2000, Tampere, Finland.
+\layout Standard
+
+More algorithms will be added over time, I have implemented about 13 watermarkin
+g algorithms in the spatial-, DCT-, and wavelet domain so far.
+\layout Subsection
+
+
+\begin_inset LatexCommand \label{sec:utility_programs}
+
+\end_inset 
+
+Utility programs
+\layout Standard
+
+A good way to check the effect of a watermarking algorithm is computing
+ the difference image, i.e.
+ subtracting the original image from the watermarked image.
+ Alternatively, one can also have a look at the modified coefficients in
+ the transform domain.
+ The following programs facilitate these tasks:
+\layout Description
+
+cmp_pgm compute difference image, PSNR, ...
+\layout Description
+
+cmp_dct compute full-frame DCT domain difference image
+\layout Description
+
+cmp_dct8x8 compute 8x8 block-based DCT difference image
+\layout Description
+
+cmp_dwt compute DWT domain difference image
+\layout Standard
+
+For example, to produce the difference image of two PGM files and compute
+ the PSNR along with some other measures, the following command can be used:
+\layout Standard
+
+
+\family typewriter 
+\size small 
+cmp_pgm -p -i original.pgm -o diff.pgm watermarked.pgm
+\layout Section
+
+Usage
+\layout Standard
+
+Note, almost all programs will output usage information if called with the
+ 
+\family typewriter 
+\size small 
+-h
+\family default 
+\size default 
+ argument.
+\layout Subsection
+
+Generating a mark
+\layout Standard
+
+First, you have to generate an appropriate signature file for the corresponding
+ embedding/detection algorithm; e.g.
+ if you are going to use Cox' scheme, then you would run
+\layout Standard
+
+
+\family typewriter 
+\size small 
+gen_cox_sig
+\layout Standard
+
+The programs outputs some parameters and a sequence of Gaussian distributed
+ random numbers (which is the watermark sequence).
+ You want to save that into a signature file, so you run
+\layout Standard
+
+
+\family typewriter 
+\size small 
+gen_cox_sig > cox.sig or 
+\layout Standard
+
+
+\family typewriter 
+\size small 
+gen_cox_sig -o cox.sig
+\layout Standard
+
+You can influence e.g.
+ the embedding strength that will be used in the embedding step by running
+\layout Standard
+
+
+\family typewriter 
+\size small 
+gen_cox_sig -a 0.5 > too_strong_cox.sig
+\layout Standard
+
+Usually, the programs for generating a signature will supply reasonable
+ default values for marking a 8-bit gray-scale image of size 
+\begin_inset Formula \( 512\times 512. \)
+\end_inset 
+
+
+\layout Subsection
+
+Watermark embedding
+\layout Standard
+
+Watermark embedding is performed with the following command (for our example,
+ we are using Cox' scheme):
+\layout Standard
+
+
+\family typewriter 
+\size small 
+wm_cox_e -s cox.sig -o cox_lena.pgm lena.pgm
+\layout Standard
+
+The signature file is parsed to obtain the particular watermark sequence
+ and the embedding strength.
+ The watermarked image is written to the file 
+\family typewriter 
+\size small 
+cox_lena.pgm
+\family default 
+\size default 
+.
+ Now it the time to check the perceptual quality of the produced image and
+ also have a look at the difference image (see section 
+\begin_inset LatexCommand \ref{sec:utility_programs}
+
+\end_inset 
+
+).
+\layout Subsection
+
+Watermark extraction
+\layout Standard
+
+To extract the embedded signature, we execute the command 
+\layout Standard
+
+
+\family typewriter 
+\size small 
+wm_cox_d -s cox.sig -i lena.pgm -o cox.wm cox_lena.pgm 
+\layout Standard
+
+Since Cox' algorithm is not blind, the original image is needed as a reference
+ to extract the embedded mark.
+ The embedded mark will be stored in 
+\family typewriter 
+\size small 
+cox.wm
+\family default 
+\size default 
+.
+ The original signature, 
+\family typewriter 
+\size small 
+cox.sig
+\family default 
+\size default 
+, is used to get the auxiliary embedding parameter correct (e.g.
+ embedding strength).
+ 
+\layout Subsection
+
+Comparing the mark
+\layout Standard
+
+The final step is comparing the original signature against the extracted
+ signature.
+ The result here is usually a correlation factor.
+ Values around 0 indicate that the mark has not been found, values around
+ 1 
+\layout Standard
+
+In most programs a analytical detection threshold for some detection probability
+ is not used.
+ Hence, one has to observe the output of the detector for many different
+ keys (around 1000 I'd suggest) to establish a reasonable threshold for
+ detection.
+ A good value to go with initially might be 0.2 which means we claim the
+ watermark detected if the correlation factor is > 0.2.
+\layout Standard
+
+The appropriate command for comparing the mark is
+\layout Standard
+
+
+\family typewriter 
+\size small 
+cmp_cox_sig -s cox.sig cox.wm 
+\layout Subsection
+
+Batch testing - benchmarking
+\layout Standard
+
+If you want to run many test you can pipe the images to be do be watermarked
+ (and tested) through the embedder and detector.
+ The programs then act like a filter.
+ Try something like the following in a Unix shell script:
+\layout Standard
+
+
+\family typewriter 
+\size small 
+gen_cox_sig > cox.sig 
+\layout Standard
+
+
+\family typewriter 
+\size small 
+for i in *.pgm 
+\layout Standard
+
+
+\family typewriter 
+\size small 
+do 
+\layout Standard
+
+
+\family typewriter 
+\size small 
+\SpecialChar ~
+\SpecialChar ~
+wm_cox_e -s cox.sig $i | 
+\backslash 
+
+\layout Standard
+
+
+\family typewriter 
+\size small 
+\SpecialChar ~
+\SpecialChar ~
+wm_cox_d -s cox.sig -i $i | 
+\backslash 
+
+\layout Standard
+
+
+\family typewriter 
+\size small 
+\SpecialChar ~
+\SpecialChar ~
+cmp_cox_sig -s cox.sig 
+\layout Standard
+
+
+\family typewriter 
+\size small 
+done
+\layout Section
+
+
+\begin_inset LatexCommand \label{sec:recompile}
+
+\end_inset 
+
+Recompiling
+\layout Standard
+
+Note, that most watermark embedding/extraction programs use the built-in
+ random number generator of the C library, i.e.
+ 
+\family typewriter 
+\size small 
+srandom()
+\family default 
+\size default 
+ and 
+\family typewriter 
+\size small 
+random().
+ 
+\family default 
+\size default 
+Therefore, if you recompile, chances are that you won't be able to use your
+ images watermarked with the previous version.
+\layout Standard
+
+The Makefile options for compiling on the different platforms can be found
+ in the 
+\family typewriter 
+\size small 
+make/
+\family default 
+\size default 
+ sub-directory of the archive.
+\layout Subsection
+
+
+\begin_inset LatexCommand \label{sec:prereq}
+
+\end_inset 
+
+Prerequisites
+\layout Subsubsection
+
+NetPBM
+\layout Standard
+
+NetPBM is responsible for image file I/O and provides a definition of a
+ simple image file format along with many image file format filters that
+ allow to convert images to and from NetPBM format.
+ 
+\layout Standard
+
+You need to get and install the NetPBM library at 
+\begin_inset LatexCommand \url{http://wuarchive.wustl.edu/graphics/graphics/packages/NetPBM/}
+
+\end_inset 
+
+ or 
+\begin_inset LatexCommand \url{http://netpbm.sourceforge.net}
+
+\end_inset 
+
+.
+ The library provides 
+\family typewriter 
+\size small 
+pgm.h
+\family default 
+\size default 
+ and the appropriate implementation.
+\layout Subsection
+
+Unix/Linux platform
+\layout Standard
+
+All programs were developed using Linux and GNU C.
+ The programs should compile and work with all recent versions of Linux
+ and GNU C.
+ 
+\layout Subsection
+
+
+\begin_inset LatexCommand \label{sec:win32_compile}
+
+\end_inset 
+
+Win32 platform
+\layout Standard
+
+The programs were ported to the Windows platform using the Cygwin
+\begin_float footnote 
+\layout Standard
+
+
+\begin_inset LatexCommand \url{http://www.cygwin.com}
+
+\end_inset 
+
+ 
+\end_float 
+and Mingw
+\begin_float footnote 
+\layout Standard
+
+
+\begin_inset LatexCommand \url{http://www.mingw.org}
+
+\end_inset 
+
+
+\end_float 
+ environment.
+ Most notable, the file mode for standard input and standard output has
+ to be set to binary mode.
+ This is accomplished with the 
+\family typewriter 
+\size small 
+setmode()
+\family default 
+\size default 
+ or 
+\family typewriter 
+\size small 
+_fsetmode()
+\family default 
+\size default 
+ commands.
+\layout Section
+
+FAQ
+\layout Standard
+
+Q: How can I report problems?
+\layout Standard
+
+A: See the contact information at the beginning of this document.
+\layout Standard
+
+Q: The compiler complains about 
+\family typewriter 
+\size small 
+pgm.h
+\family default 
+\size default 
+?
+\layout Standard
+
+A: You need to get and install the NetPBM library, see section 
+\begin_inset LatexCommand \ref{sec:prereq}
+
+\end_inset 
+
+.
+\layout Standard
+
+Q: What is the best algorithm? 
+\layout Standard
+
+A: Depends on your application.
+\layout Standard
+
+Q: What is the most robust algorithm?
+\layout Standard
+
+A: Depends on the attack.
+ See some results on 
+\begin_inset LatexCommand \url{http://www.cosy.sbg.ac.at/~pmeerw/Watermarking}
+
+\end_inset 
+
+.
+\layout Standard
+
+Q: I need code for a full-frame DCT?
+\layout Standard
+
+A: See the files Meerwald/dct.* in the archive.
+\layout Standard
+
+Q: I need code for a 8x8 block DCT?
+\layout Standard
+
+A: See the files 
+\family typewriter 
+\size small 
+Meerwald/dct.*
+\family default 
+\size default 
+ in the archive.
+\layout Standard
+
+Q: I need code for the wavelet transform (DWT)?
+\layout Standard
+
+A: See the files 
+\family typewriter 
+\size small 
+Meerwald/wavelet.*
+\family default 
+\size default 
+ in the archive.
+\layout Standard
+
+Q: I get the message 'unable to open filter.dat' - what to do?
+\layout Standard
+
+A: Make sure the file filter.dat is in the current directory or accessible
+ via path/filename specified in the signature file.
+ Use the signature generation command to specify an absolute path if necessary.
+\layout Standard
+
+Q: I can't compile the code using some Microsoft product?
+\layout Standard
+
+A: Make your life easier, install GNU software! See section 
+\begin_inset LatexCommand \ref{sec:recompile}
+
+\end_inset 
+
+.
+\layout Section
+
+Revision history
+\layout Standard
+
+version 0.4 (June 21, 2001)
+\layout Itemize
+
+bug fixes 
+\begin_deeper 
+\layout Itemize
+
+wm_xia_{e|d}.c variable level uninitialized 
+\layout Itemize
+
+wm_zhu_{e|d}.c variable level uninitialized
+\layout Itemize
+
+issue with random() vs.
+ rand() and RAND_MAX in frid2_common.c
+\end_deeper 
+\layout Itemize
+
+added option to bruyn algorithm to disable block skipping
+\layout Itemize
+
+added algorithm kim
+\layout Standard
+
+version 0.3 (June 18, 2001)
+\layout Itemize
+
+created a nice (?) manual/documentation
+\layout Itemize
+
+added algorithms by Dugad, Wang, Zhu, Fridrich
+\layout Itemize
+
+added Makefiles for Win32 platform (mingw32)
+\layout Standard
+
+version 0.2 (February 22, 2001)
+\layout Itemize
+
+added contribution by Vassilis Fotopoulos (Piva's algorithm,
+\layout Itemize
+
+DCT, Hartley and subband domain) - see Fotopoulos/ subdirectory
+\layout Itemize
+
+stuff moved to Meerwald/ subdirectory
+\layout Itemize
+
+added Bruyndonckx, Corvi, Koch, Xia, Xie algorithms
+\layout Standard
+
+version 0.1 (February 18, 2001)
+\layout Itemize
+
+initial release
+\layout Section
+
+Legal statement
+\layout Standard
+
+My license is called "I-don't-care" license: (1) You can do with the accompanyin
+g software whatever you want, but don't blame me if it doesn't work or it
+ causes damage.
+ (2) If you think my work is useful, tell me and tell others, but you are
+ not obliged to do so.
+ I suggest not to remove information contained in this other documentation
+ file.
+\layout Standard
+
+
+\begin_inset LatexCommand \BibTeX[plain]{watermarking}
+
+\end_inset 
+
+
+\the_end

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