git » fp-git.git » commit 87b0564

tested and benchmarked

author ecalot
2005-03-24 15:17:42 UTC
committer ecalot
2005-03-24 15:17:42 UTC
parent fc806a0ae2e1c34ac9d33bc3abaa4ac475e6fa06

tested and benchmarked

PR/doc/readme.txt +26 -2
PR/src/console/main.c +5 -0
PR/src/include/common.h +3 -2
PR/src/include/compress.h +7 -0
PR/src/include/en.lang.pr.h +9 -2
PR/src/include/image.h +7 -0
PR/src/include/pr.h +3 -2
PR/src/lib/compression/lzg_compress.c +12 -11
PR/src/lib/compression/lzg_decompress.c +2 -0
PR/src/lib/compression/rle_decompress.c +8 -5
PR/src/lib/compression/rlev_decompress.c +8 -5
PR/src/lib/object/image/image16.c +114 -32
PR/src/lib/object/image/image2.c +114 -32
PR/src/lib/object/image/image256.c +114 -32
PR/src/lib/object/image/image_common.c +114 -32

diff --git a/PR/doc/readme.txt b/PR/doc/readme.txt
index feff37d..e0b1f51 100644
--- a/PR/doc/readme.txt
+++ b/PR/doc/readme.txt
@@ -1,5 +1,5 @@
-Princed Resources v1.0-dev1
-(c) Copyright 2003, 2004 - Princed Development Team
+Princed Resources v1.0-dev2
+(c) Copyright 2003 - 2005 - Princed Development Team
 http://www.princed.com.ar
 This program is open source under the GNU General Public License terms
 
@@ -120,6 +120,28 @@ Binary:
   Recomended:
    AMD K6-II at 350Mhz or higher
    32 Mb RAM
+	
+	Benchmark results:
+   Performed on an AMD Athlon(tm) XP 2000+ with 1667.022 MHz
+	 The file tested was the original vdungeon.dat, sized 14220 bytes
+
+	 Normal benchmark results:
+	  Compression level 1. Size 38031 bytes. Time 0.028137 seconds.
+	  Compression level 2. Size 23756 bytes. Time 0.031273 seconds.
+	  Compression level 3. Size 15912 bytes. Time 0.031836 seconds.
+	  Compression level 4. Size 12519 bytes. Time 0.066246 seconds.
+	  Compression level 5. Size 11347 bytes. Time 0.087975 seconds.
+	  Compression level 6. Size 11218 bytes. Time 1.506183 seconds.
+	  Compression level 7. Size 10932 bytes. Time 2.916612 seconds.
+
+	 Benchamrk using valgrind 
+	  Compression level 1. Size 38031 bytes. Time 1.239898 seconds.
+	  Compression level 2. Size 23756 bytes. Time 1.244662 seconds.
+	  Compression level 3. Size 15912 bytes. Time 1.305006 seconds.
+	  Compression level 4. Size 12519 bytes. Time 2.251174 seconds.
+	  Compression level 5. Size 11347 bytes. Time 2.908357 seconds.
+	  Compression level 6. Size 11218 bytes. Time 73.004200 seconds.
+	  Compression level 7. Size 10932 bytes. Time 144.786515 seconds.
 
 6) Credits
 
@@ -132,6 +154,7 @@ Binary:
  Graphic compression algorithms
   Tammo Jan Dijkema
   Enrique Calot
+	Diego Essaya
 
  Graphic format development
   Tammo Jan Dijkema
@@ -152,6 +175,7 @@ Special thanks to:
  - the authors of GCC and LCC for making excelent free compilers.
  - SourceForge.net for the home page hosting and the development
    enviornment provided.
+ - Lugfi for all the support. 
 
 Please enjoy using Princed Resource Editor!
 
diff --git a/PR/src/console/main.c b/PR/src/console/main.c
index 194ce54..a50062d 100644
--- a/PR/src/console/main.c
+++ b/PR/src/console/main.c
@@ -39,6 +39,7 @@ main.c: PR console program parsing routine
 #include <string.h>
 #include "memory.h"
 #include "filedir.h"
+#include "compress.h" /* setCompressionLevel */
 #include "xmlparse.h" /* free parsed cache */
 
 FILE* outputStream;
@@ -48,6 +49,7 @@ void syntax() {
 	fprintf(outputStream,PARSING_HELP_PART1);
 	fprintf(outputStream,PARSING_HELP_PART2);
 	fprintf(outputStream,PARSING_HELP_PART3);
+	fprintf(outputStream,PARSING_HELP_PART4);
 }
 
 /***************************************************************\
@@ -106,6 +108,9 @@ int main (int argc, char **argv) {
 					freeAllocation(resFile);
 					resFile=strallocandcopy(optarg);
 					break;
+				case 'z':
+					if (optarg) setCompressionLevel(atoi(optarg));
+					break;
 				case 'r':
 #ifndef PR_IGNORE_RAW_OPTION
 					setFlag(raw_flag);
diff --git a/PR/src/include/common.h b/PR/src/include/common.h
index c204a9c..0306adb 100644
--- a/PR/src/include/common.h
+++ b/PR/src/include/common.h
@@ -188,7 +188,8 @@ int prMain(int option, const char* extension,const char* dirName,const char* res
 {"force",       no_argument,       0,'f'},\
 {"cgi",         no_argument,       0,'g'},\
 {"help",        no_argument,       0,'?'},\
-{"resource",    required_argument, 0,'s'}\
+{"resource",    required_argument, 0,'s'},\
+{"compression-level",    required_argument, 0,'z'}\
 PARSING_OPTRAW\
 {"recursive",   no_argument,       0,'R'},\
 {"datfile",     required_argument, 0,'t'},\
@@ -198,7 +199,7 @@ PARSING_OPTRAW\
 {0, 0, 0, 0}\
 }
 
-#define PARSING_CHARS    "i::c::dx::e::b::a::fgs::t::Rvh?"PARSING_CHRRAW
+#define PARSING_CHARS    "z::i::c::dx::e::b::a::fgs::t::Rvh?"PARSING_CHRRAW
 
 /* Flags */
 #define import_flag      0x0001
diff --git a/PR/src/include/compress.h b/PR/src/include/compress.h
index 9ca9b06..5aab730 100644
--- a/PR/src/include/compress.h
+++ b/PR/src/include/compress.h
@@ -85,6 +85,13 @@ typedef struct {
 int mCompressGraphic(unsigned char** a,tImage* i, int* size);
 int mExpandGraphic(const unsigned char* array,tImage *image, int size);
 
+void setCompressionLevel(int cl);
+
+#define cLevel(a) if (compressionLevel>=a)
+#define cHigh if (compressionHigher)
+#define setHigh compressionHigher=1
+#define unsetHigh compressionHigher=0
+
 #define getCarry(a) ((a)>>6)
 #define getAlgor(a) a&0x4F
 
diff --git a/PR/src/include/en.lang.pr.h b/PR/src/include/en.lang.pr.h
index 7fa4523..6090b2e 100644
--- a/PR/src/include/en.lang.pr.h
+++ b/PR/src/include/en.lang.pr.h
@@ -118,8 +118,9 @@ NULL,NULL,NULL,\
 #define PARSING_RAW ""
 #endif
 #define PARSING_HELP_BEGIN "Usage: \n\
-  pr [-x[EXPORTDIR]|-i[IMPORTDIR]|-d] [DATFILEPATH]\n\
-  pr [OPTIONS] [DATFILEPATH]\n\
+  pr [OPTIONS] [-x[EXPORTDIR]|-i[IMPORTDIR]|-d] [DATFILEPATH]...\n\
+  pr --help\n\
+  pr --version\n\
 \n\
   Mandatory arguments to long options are mandatory for short options too.\n\
 \n"
@@ -142,6 +143,12 @@ NULL,NULL,NULL,\
                               is not a dat file)\n\
    -t, --datfile=DATFILE      specifies a dat file to read resources\n\
                               different than the original file\n\
+   -z, --compression-level=n  a number from 1 to 7 specifying how hard has PR\n\
+                              to try to reduce the generated dat files.\n"
+
+#define PARSING_HELP_PART4 "\
+                              1 is high speed, low compression, 7 is high\n\
+                              compression but low speed.\n\
        --unknown              generate the unknown file without performing\n\
                               any extraction\n\
    -v, --verbose              explain what is being done\n\
diff --git a/PR/src/include/image.h b/PR/src/include/image.h
index 9ca9b06..5aab730 100644
--- a/PR/src/include/image.h
+++ b/PR/src/include/image.h
@@ -85,6 +85,13 @@ typedef struct {
 int mCompressGraphic(unsigned char** a,tImage* i, int* size);
 int mExpandGraphic(const unsigned char* array,tImage *image, int size);
 
+void setCompressionLevel(int cl);
+
+#define cLevel(a) if (compressionLevel>=a)
+#define cHigh if (compressionHigher)
+#define setHigh compressionHigher=1
+#define unsetHigh compressionHigher=0
+
 #define getCarry(a) ((a)>>6)
 #define getAlgor(a) a&0x4F
 
diff --git a/PR/src/include/pr.h b/PR/src/include/pr.h
index c204a9c..0306adb 100644
--- a/PR/src/include/pr.h
+++ b/PR/src/include/pr.h
@@ -188,7 +188,8 @@ int prMain(int option, const char* extension,const char* dirName,const char* res
 {"force",       no_argument,       0,'f'},\
 {"cgi",         no_argument,       0,'g'},\
 {"help",        no_argument,       0,'?'},\
-{"resource",    required_argument, 0,'s'}\
+{"resource",    required_argument, 0,'s'},\
+{"compression-level",    required_argument, 0,'z'}\
 PARSING_OPTRAW\
 {"recursive",   no_argument,       0,'R'},\
 {"datfile",     required_argument, 0,'t'},\
@@ -198,7 +199,7 @@ PARSING_OPTRAW\
 {0, 0, 0, 0}\
 }
 
-#define PARSING_CHARS    "i::c::dx::e::b::a::fgs::t::Rvh?"PARSING_CHRRAW
+#define PARSING_CHARS    "z::i::c::dx::e::b::a::fgs::t::Rvh?"PARSING_CHRRAW
 
 /* Flags */
 #define import_flag      0x0001
diff --git a/PR/src/lib/compression/lzg_compress.c b/PR/src/lib/compression/lzg_compress.c
index fdd4461..86b9175 100644
--- a/PR/src/lib/compression/lzg_compress.c
+++ b/PR/src/lib/compression/lzg_compress.c
@@ -66,9 +66,10 @@
 
 #include <stdio.h>
 #include <stdlib.h>
+#include "compress.h"
 
 /*#define LZG_REVERSE*/
-/*#define LZG_FASTER*/
+extern int compressionHigher;
 
 #ifdef LZG_REVERSE
 void *memrchr2(unsigned char *s, int c, size_t n) {
@@ -126,16 +127,16 @@ void search_best_pattern(unsigned char *input, int inputSize,
 
 		if (pattern_len == MAX_PATTERN_SIZE) break;
 
-		/* if LZG_FASTER is defined compression rate will be 5% worst
-		 * and compression time will be 80% faster */
-#ifdef LZG_FASTER
-		window_len -= wc - window;
-		if (window_len <= 0) break;
-		window = wc;
-#else
-		window_len--;
-		window++;
-#endif
+		/* if cLevel is 9 compression rate will be 5% better
+		 * and compression time will be 400% slower */
+		cHigh {
+			window_len--;
+			window++;
+		} else {
+			window_len -= wc - window;
+			if (window_len <= 0) break;
+			window = wc;
+		}
 	}
 }
 
diff --git a/PR/src/lib/compression/lzg_decompress.c b/PR/src/lib/compression/lzg_decompress.c
index 64f1347..077e6ef 100644
--- a/PR/src/lib/compression/lzg_decompress.c
+++ b/PR/src/lib/compression/lzg_decompress.c
@@ -31,6 +31,7 @@
 
 #include <stdio.h>
 #include <stdlib.h>
+#include "compress.h"
 
 /* modulus to be used in the 10 bits of the algorithm */
 #define LZG_WINDOW_SIZE    0x400 /* =1024=1<<10 */
@@ -90,5 +91,6 @@ int expandLzg(const unsigned char* input, int inputSize,
 		(*output2)[iCursor-LZG_WINDOW_SIZE]=output[iCursor];
 
 	return (!maskbyte)-1;
+	/*return rep?COMPRESS_RESULT_WARNING:COMPRESS_RESULT_SUCCESS;*/
 }
 
diff --git a/PR/src/lib/compression/rle_decompress.c b/PR/src/lib/compression/rle_decompress.c
index 73d27e3..1fe0dde 100644
--- a/PR/src/lib/compression/rle_decompress.c
+++ b/PR/src/lib/compression/rle_decompress.c
@@ -40,13 +40,14 @@ compress.c: Princed Resources : Image Compression Library
 int expandRle(const unsigned char* input, int inputSize, 
                unsigned char** output, int *outputSize) {
 	int cursor=0;
-	register signed char rep;
+	register signed char rep=1;
 	int pos=0;
 
-	if ((*output=malloc(*outputSize+128))==NULL) return COMPRESS_RESULT_FATAL; /* reserve memory */
+	/* reserve memory */
+	if ((*output=malloc(40000))==NULL) return COMPRESS_RESULT_FATAL; 
 
 	/* main loop */
-	while (cursor<*outputSize) {
+	while (pos<inputSize) {
 		rep=(signed char)(input[pos++]);
 		if (rep<0) {
 			/* Negative */
@@ -55,9 +56,11 @@ int expandRle(const unsigned char* input, int inputSize,
 		} else {
 			/* Positive */
 			rep=~rep;
-			while (rep++) (*output)[cursor++]=input[pos++];
+			while ((rep++)&&(pos<inputSize)) (*output)[cursor++]=input[pos++];
 		}
 	}
-	return ((pos==inputSize)&(cursor==*outputSize))-1; /* WARNING or SUCCESS */
+
+	*outputSize=cursor;
+	return (rep==1)?COMPRESS_RESULT_SUCCESS:COMPRESS_RESULT_WARNING;
 }
 
diff --git a/PR/src/lib/compression/rlev_decompress.c b/PR/src/lib/compression/rlev_decompress.c
index 73d27e3..1fe0dde 100644
--- a/PR/src/lib/compression/rlev_decompress.c
+++ b/PR/src/lib/compression/rlev_decompress.c
@@ -40,13 +40,14 @@ compress.c: Princed Resources : Image Compression Library
 int expandRle(const unsigned char* input, int inputSize, 
                unsigned char** output, int *outputSize) {
 	int cursor=0;
-	register signed char rep;
+	register signed char rep=1;
 	int pos=0;
 
-	if ((*output=malloc(*outputSize+128))==NULL) return COMPRESS_RESULT_FATAL; /* reserve memory */
+	/* reserve memory */
+	if ((*output=malloc(40000))==NULL) return COMPRESS_RESULT_FATAL; 
 
 	/* main loop */
-	while (cursor<*outputSize) {
+	while (pos<inputSize) {
 		rep=(signed char)(input[pos++]);
 		if (rep<0) {
 			/* Negative */
@@ -55,9 +56,11 @@ int expandRle(const unsigned char* input, int inputSize,
 		} else {
 			/* Positive */
 			rep=~rep;
-			while (rep++) (*output)[cursor++]=input[pos++];
+			while ((rep++)&&(pos<inputSize)) (*output)[cursor++]=input[pos++];
 		}
 	}
-	return ((pos==inputSize)&(cursor==*outputSize))-1; /* WARNING or SUCCESS */
+
+	*outputSize=cursor;
+	return (rep==1)?COMPRESS_RESULT_SUCCESS:COMPRESS_RESULT_WARNING;
 }
 
diff --git a/PR/src/lib/object/image/image16.c b/PR/src/lib/object/image/image16.c
index 74c09fb..6ae190b 100644
--- a/PR/src/lib/object/image/image16.c
+++ b/PR/src/lib/object/image/image16.c
@@ -39,6 +39,50 @@ compress.c: Princed Resources : Image Compression Library
 #include "pr.h"
 #include "disk.h" /* array2short */
 
+/* Compression level explanation:
+ *
+ * Definitions:
+ *  no compression is called RAW
+ *  there are 2 algorithms types: RLE and LZG
+ *  we can use the modifier: transpose and not transpose (t)
+ *  we can use the LZG modifier: Faster (checks faster the LZG window ignoring
+ *   less probable pattern) (+)
+ *
+ *  So the possible compression algorithms are:
+ *   RAW, RLE, RLEt, LZG, LZGt, LZG+, LZGt+
+ *  
+ *  It is known that LZG+ allways compresses better or equal than LZG
+ *
+ * Depending on the compression level, the compressor will compress with
+ * all the algorithms specified and keep only the smaller result using
+ * the following table
+ * 
+ * Level  Algorithms
+ *   1    RAW
+ *   2    RAW, RLE
+ *   3    RAW, RLE, RLEt
+ *   4    RAW, RLE, RLEt, LZG
+ *   5    RAW, RLE, RLEt, LZG, LZGt
+ *   6    RAW, RLE, RLEt, LZG+, LZGt
+ *   7    RAW, RLE, RLEt, LZG+, LZGt+
+ *
+ * The default level used in PR will be 3.
+ *
+ * In images with big enthropy that generates DAT files bigger than 64kb, using
+ * a better compression is a must. The POP1 DAT file format has this limitation
+ * and the only way to get through with it is improving the compression.
+ *
+ * For testing DAT files that are not for distribution compression 3 is highly
+ * recomended because is much faster and you perform compressions more often.
+ * 
+ * When you release a DAT file a compression level 7 is the best you can use.
+ * You'll have to wait some time to get the importing, but the decompression
+ * is as faster as the decompression in other levels. The game supports it and
+ * decompresses the files very fast. Another advantage is that it is better to
+ * distribute smaller dat files.
+ *
+ */
+
 /***************************************************************\
 |                  I M P L E M E N T A T I O N                  |
 \***************************************************************/
@@ -59,6 +103,17 @@ int expandLzg(const unsigned char* input, int inputSize,
 int expandRle(const unsigned char* input, int inputSize, 
                unsigned char** output, int *outputSize);
 
+/***************************************************************\
+|                   Compression Level Manager                   |
+\***************************************************************/
+
+int compressionLevel=3;
+int compressionHigher;
+
+void setCompressionLevel(int cl) {
+	compressionLevel=cl;
+}
+
 /***************************************************************\
 |                        Image transpose                        |
 \***************************************************************/
@@ -125,29 +180,37 @@ int mExpandGraphic(const unsigned char* data,tImage *image, int dataSizeInBytes)
 	} else {
 		image->widthInBytes=(image->width+7)/8;
 	}
-	imageSizeInBytes=image->widthInBytes*image->height;
 
+#define checkSize if (imageSizeInBytes!=(image->widthInBytes*image->height))\
+	return COMPRESS_RESULT_FATAL
+#define checkResult if (result==COMPRESS_RESULT_FATAL)\
+	return COMPRESS_RESULT_FATAL
+	
 	switch (getAlgor(image->type)) {
 		case COMPRESS_RAW: /* No Compression Algorithm */
-						/* TODO: use dataSize */
-			if ((image->pix=getMemory(imageSizeInBytes))==NULL) return COMPRESS_RESULT_FATAL;
-			memcpy(image->pix,data,imageSizeInBytes);
+			if ((image->pix=getMemory(dataSizeInBytes))==NULL) return COMPRESS_RESULT_FATAL;
+			memcpy(image->pix,data,dataSizeInBytes);
+			imageSizeInBytes=image->widthInBytes*image->height;
 			result=COMPRESS_RESULT_SUCCESS;
 			break;
 		case COMPRESS_RLE_LR: /* RLE Left to Right Compression Algorithm */
 			result=expandRle(data,dataSizeInBytes,&(image->pix),&imageSizeInBytes);
+			checkSize;
 			break;
 		case COMPRESS_RLE_UD: /* RLE Up to Down Compression Algorithm */
 			result=expandRle(data,dataSizeInBytes,&(image->pix),&imageSizeInBytes);
-			if (result==COMPRESS_RESULT_FATAL) return COMPRESS_RESULT_FATAL;
+			checkResult;
+			checkSize;
 			transposeImage(image,imageSizeInBytes);
 			break;
 		case COMPRESS_LZG_LR: /* LZ Groody Left to Right Compression Algorithm */
 			result=expandLzg(data,dataSizeInBytes,&(image->pix),&imageSizeInBytes);
+			checkSize;
 			break;
 		case COMPRESS_LZG_UD: /* LZ Groody Up to Down Compression Algorithm */
 			result=expandLzg(data,dataSizeInBytes,&(image->pix),&imageSizeInBytes);
-			if (result==COMPRESS_RESULT_FATAL) return COMPRESS_RESULT_FATAL;
+			checkResult;
+			checkSize;
 			transposeImage(image,imageSizeInBytes);
 			break;
 		default:
@@ -165,6 +228,7 @@ int mCompressGraphic(unsigned char* *data,tImage* image, int* dataSizeInBytes) {
 	int            algorithm;
 	int            i;
 	int            imageSizeInBytes;
+	int            max_alg=1;
 
 	/* Initialize variables */
 	imageSizeInBytes=image->widthInBytes*image->height;
@@ -194,12 +258,14 @@ int mCompressGraphic(unsigned char* *data,tImage* image, int* dataSizeInBytes) {
 	 * size plus a byte each 127 bytes.
 	 * This is accoted by 2*n+50
 	 */
-	compressed[COMPRESS_RLE_LR]=getMemory((2*imageSizeInBytes+50)); 
-	compressRle(
-		image->pix,imageSizeInBytes,
-		compressed[COMPRESS_RLE_LR],&(compressedSize[COMPRESS_RLE_LR])
-	);
-
+	cLevel(2) {
+		compressed[COMPRESS_RLE_LR]=getMemory((2*imageSizeInBytes+50)); 
+		compressRle(
+			image->pix,imageSizeInBytes,
+			compressed[COMPRESS_RLE_LR],&(compressedSize[COMPRESS_RLE_LR])
+		);
+		max_alg++;
+	}
 	/* COMPRESS_LZG_LR 
 	 * If all the uncompressed data has a big enthropy, there
 	 * will be a maskbyte for a block of 8 bytes.
@@ -209,12 +275,18 @@ int mCompressGraphic(unsigned char* *data,tImage* image, int* dataSizeInBytes) {
 	 * allocated.
 	 * This is accoted by 2*n+1050
 	 */
-	compressed[COMPRESS_LZG_LR]=getMemory((2*imageSizeInBytes+1050));
-	compressLzg(
-		image->pix,imageSizeInBytes,
-		compressed[COMPRESS_LZG_LR],&(compressedSize[COMPRESS_LZG_LR])
-	);
-	
+	cLevel(4) {
+		cLevel(6)
+			setHigh;
+		else
+			unsetHigh;
+		compressed[COMPRESS_LZG_LR]=getMemory((2*imageSizeInBytes+1050));
+		compressLzg(
+			image->pix,imageSizeInBytes,
+			compressed[COMPRESS_LZG_LR],&(compressedSize[COMPRESS_LZG_LR])
+		);
+		max_alg++;
+	}
 
 	/* Transposed compression
 	 * Transposition is used to test the same compression
@@ -223,22 +295,32 @@ int mCompressGraphic(unsigned char* *data,tImage* image, int* dataSizeInBytes) {
 	 * The following algorithms will be the same as above, but
 	 * using the image matrix transposed.
 	 */
-	antiTransposeImage(image,imageSizeInBytes);
+	cLevel(3) 
+		antiTransposeImage(image,imageSizeInBytes);
 
 	/* COMPRESS_RLE_UD */
-	compressed[COMPRESS_RLE_UD]=getMemory(2*imageSizeInBytes+50);
-	compressRle(
-		image->pix,imageSizeInBytes,
-		compressed[COMPRESS_RLE_UD],&(compressedSize[COMPRESS_RLE_UD])
-	);
+	cLevel(3) {
+		compressed[COMPRESS_RLE_UD]=getMemory(2*imageSizeInBytes+50);
+		compressRle(
+			image->pix,imageSizeInBytes,
+			compressed[COMPRESS_RLE_UD],&(compressedSize[COMPRESS_RLE_UD])
+		);
+		max_alg++;
+	}
 
 	/* COMPRESS_LZG_UD */
-	compressed[COMPRESS_LZG_UD]=getMemory(2*imageSizeInBytes+1050);
-	compressLzg(
-		image->pix,imageSizeInBytes,
-		compressed[COMPRESS_LZG_UD],&(compressedSize[COMPRESS_LZG_UD])
-	);
-
+	cLevel(5) {
+		cLevel(7)
+			setHigh;
+		else
+			unsetHigh;
+		compressed[COMPRESS_LZG_UD]=getMemory(2*imageSizeInBytes+1050);
+		compressLzg(
+			image->pix,imageSizeInBytes,
+			compressed[COMPRESS_LZG_UD],&(compressedSize[COMPRESS_LZG_UD])
+		);
+		max_alg++;
+	}
 	/*
 		Process results
 	*/
@@ -246,7 +328,7 @@ int mCompressGraphic(unsigned char* *data,tImage* image, int* dataSizeInBytes) {
 	/* Select the best compression (find minimum) */
 	*dataSizeInBytes=compressedSize[COMPRESS_RAW];
 	algorithm=COMPRESS_RAW;
-	for (i=COMPRESS_RLE_LR;i<COMPRESS_WORKING_ALGORITHMS;i++) {
+	for (i=COMPRESS_RLE_LR;i<max_alg;i++) {
 		if ((*dataSizeInBytes)>compressedSize[i]) {
 			(*dataSizeInBytes)=compressedSize[i];
 			algorithm=i;
@@ -273,7 +355,7 @@ int mCompressGraphic(unsigned char* *data,tImage* image, int* dataSizeInBytes) {
 	(*data)[5]=image->type|algorithm;
 
 	/* Free all compression attempts */
-	for (i=COMPRESS_RAW;i<COMPRESS_WORKING_ALGORITHMS;i++) free(compressed[i]);
+	for (i=COMPRESS_RAW;i<max_alg;i++) free(compressed[i]);
 	return 1;
 }
 
diff --git a/PR/src/lib/object/image/image2.c b/PR/src/lib/object/image/image2.c
index 74c09fb..6ae190b 100644
--- a/PR/src/lib/object/image/image2.c
+++ b/PR/src/lib/object/image/image2.c
@@ -39,6 +39,50 @@ compress.c: Princed Resources : Image Compression Library
 #include "pr.h"
 #include "disk.h" /* array2short */
 
+/* Compression level explanation:
+ *
+ * Definitions:
+ *  no compression is called RAW
+ *  there are 2 algorithms types: RLE and LZG
+ *  we can use the modifier: transpose and not transpose (t)
+ *  we can use the LZG modifier: Faster (checks faster the LZG window ignoring
+ *   less probable pattern) (+)
+ *
+ *  So the possible compression algorithms are:
+ *   RAW, RLE, RLEt, LZG, LZGt, LZG+, LZGt+
+ *  
+ *  It is known that LZG+ allways compresses better or equal than LZG
+ *
+ * Depending on the compression level, the compressor will compress with
+ * all the algorithms specified and keep only the smaller result using
+ * the following table
+ * 
+ * Level  Algorithms
+ *   1    RAW
+ *   2    RAW, RLE
+ *   3    RAW, RLE, RLEt
+ *   4    RAW, RLE, RLEt, LZG
+ *   5    RAW, RLE, RLEt, LZG, LZGt
+ *   6    RAW, RLE, RLEt, LZG+, LZGt
+ *   7    RAW, RLE, RLEt, LZG+, LZGt+
+ *
+ * The default level used in PR will be 3.
+ *
+ * In images with big enthropy that generates DAT files bigger than 64kb, using
+ * a better compression is a must. The POP1 DAT file format has this limitation
+ * and the only way to get through with it is improving the compression.
+ *
+ * For testing DAT files that are not for distribution compression 3 is highly
+ * recomended because is much faster and you perform compressions more often.
+ * 
+ * When you release a DAT file a compression level 7 is the best you can use.
+ * You'll have to wait some time to get the importing, but the decompression
+ * is as faster as the decompression in other levels. The game supports it and
+ * decompresses the files very fast. Another advantage is that it is better to
+ * distribute smaller dat files.
+ *
+ */
+
 /***************************************************************\
 |                  I M P L E M E N T A T I O N                  |
 \***************************************************************/
@@ -59,6 +103,17 @@ int expandLzg(const unsigned char* input, int inputSize,
 int expandRle(const unsigned char* input, int inputSize, 
                unsigned char** output, int *outputSize);
 
+/***************************************************************\
+|                   Compression Level Manager                   |
+\***************************************************************/
+
+int compressionLevel=3;
+int compressionHigher;
+
+void setCompressionLevel(int cl) {
+	compressionLevel=cl;
+}
+
 /***************************************************************\
 |                        Image transpose                        |
 \***************************************************************/
@@ -125,29 +180,37 @@ int mExpandGraphic(const unsigned char* data,tImage *image, int dataSizeInBytes)
 	} else {
 		image->widthInBytes=(image->width+7)/8;
 	}
-	imageSizeInBytes=image->widthInBytes*image->height;
 
+#define checkSize if (imageSizeInBytes!=(image->widthInBytes*image->height))\
+	return COMPRESS_RESULT_FATAL
+#define checkResult if (result==COMPRESS_RESULT_FATAL)\
+	return COMPRESS_RESULT_FATAL
+	
 	switch (getAlgor(image->type)) {
 		case COMPRESS_RAW: /* No Compression Algorithm */
-						/* TODO: use dataSize */
-			if ((image->pix=getMemory(imageSizeInBytes))==NULL) return COMPRESS_RESULT_FATAL;
-			memcpy(image->pix,data,imageSizeInBytes);
+			if ((image->pix=getMemory(dataSizeInBytes))==NULL) return COMPRESS_RESULT_FATAL;
+			memcpy(image->pix,data,dataSizeInBytes);
+			imageSizeInBytes=image->widthInBytes*image->height;
 			result=COMPRESS_RESULT_SUCCESS;
 			break;
 		case COMPRESS_RLE_LR: /* RLE Left to Right Compression Algorithm */
 			result=expandRle(data,dataSizeInBytes,&(image->pix),&imageSizeInBytes);
+			checkSize;
 			break;
 		case COMPRESS_RLE_UD: /* RLE Up to Down Compression Algorithm */
 			result=expandRle(data,dataSizeInBytes,&(image->pix),&imageSizeInBytes);
-			if (result==COMPRESS_RESULT_FATAL) return COMPRESS_RESULT_FATAL;
+			checkResult;
+			checkSize;
 			transposeImage(image,imageSizeInBytes);
 			break;
 		case COMPRESS_LZG_LR: /* LZ Groody Left to Right Compression Algorithm */
 			result=expandLzg(data,dataSizeInBytes,&(image->pix),&imageSizeInBytes);
+			checkSize;
 			break;
 		case COMPRESS_LZG_UD: /* LZ Groody Up to Down Compression Algorithm */
 			result=expandLzg(data,dataSizeInBytes,&(image->pix),&imageSizeInBytes);
-			if (result==COMPRESS_RESULT_FATAL) return COMPRESS_RESULT_FATAL;
+			checkResult;
+			checkSize;
 			transposeImage(image,imageSizeInBytes);
 			break;
 		default:
@@ -165,6 +228,7 @@ int mCompressGraphic(unsigned char* *data,tImage* image, int* dataSizeInBytes) {
 	int            algorithm;
 	int            i;
 	int            imageSizeInBytes;
+	int            max_alg=1;
 
 	/* Initialize variables */
 	imageSizeInBytes=image->widthInBytes*image->height;
@@ -194,12 +258,14 @@ int mCompressGraphic(unsigned char* *data,tImage* image, int* dataSizeInBytes) {
 	 * size plus a byte each 127 bytes.
 	 * This is accoted by 2*n+50
 	 */
-	compressed[COMPRESS_RLE_LR]=getMemory((2*imageSizeInBytes+50)); 
-	compressRle(
-		image->pix,imageSizeInBytes,
-		compressed[COMPRESS_RLE_LR],&(compressedSize[COMPRESS_RLE_LR])
-	);
-
+	cLevel(2) {
+		compressed[COMPRESS_RLE_LR]=getMemory((2*imageSizeInBytes+50)); 
+		compressRle(
+			image->pix,imageSizeInBytes,
+			compressed[COMPRESS_RLE_LR],&(compressedSize[COMPRESS_RLE_LR])
+		);
+		max_alg++;
+	}
 	/* COMPRESS_LZG_LR 
 	 * If all the uncompressed data has a big enthropy, there
 	 * will be a maskbyte for a block of 8 bytes.
@@ -209,12 +275,18 @@ int mCompressGraphic(unsigned char* *data,tImage* image, int* dataSizeInBytes) {
 	 * allocated.
 	 * This is accoted by 2*n+1050
 	 */
-	compressed[COMPRESS_LZG_LR]=getMemory((2*imageSizeInBytes+1050));
-	compressLzg(
-		image->pix,imageSizeInBytes,
-		compressed[COMPRESS_LZG_LR],&(compressedSize[COMPRESS_LZG_LR])
-	);
-	
+	cLevel(4) {
+		cLevel(6)
+			setHigh;
+		else
+			unsetHigh;
+		compressed[COMPRESS_LZG_LR]=getMemory((2*imageSizeInBytes+1050));
+		compressLzg(
+			image->pix,imageSizeInBytes,
+			compressed[COMPRESS_LZG_LR],&(compressedSize[COMPRESS_LZG_LR])
+		);
+		max_alg++;
+	}
 
 	/* Transposed compression
 	 * Transposition is used to test the same compression
@@ -223,22 +295,32 @@ int mCompressGraphic(unsigned char* *data,tImage* image, int* dataSizeInBytes) {
 	 * The following algorithms will be the same as above, but
 	 * using the image matrix transposed.
 	 */
-	antiTransposeImage(image,imageSizeInBytes);
+	cLevel(3) 
+		antiTransposeImage(image,imageSizeInBytes);
 
 	/* COMPRESS_RLE_UD */
-	compressed[COMPRESS_RLE_UD]=getMemory(2*imageSizeInBytes+50);
-	compressRle(
-		image->pix,imageSizeInBytes,
-		compressed[COMPRESS_RLE_UD],&(compressedSize[COMPRESS_RLE_UD])
-	);
+	cLevel(3) {
+		compressed[COMPRESS_RLE_UD]=getMemory(2*imageSizeInBytes+50);
+		compressRle(
+			image->pix,imageSizeInBytes,
+			compressed[COMPRESS_RLE_UD],&(compressedSize[COMPRESS_RLE_UD])
+		);
+		max_alg++;
+	}
 
 	/* COMPRESS_LZG_UD */
-	compressed[COMPRESS_LZG_UD]=getMemory(2*imageSizeInBytes+1050);
-	compressLzg(
-		image->pix,imageSizeInBytes,
-		compressed[COMPRESS_LZG_UD],&(compressedSize[COMPRESS_LZG_UD])
-	);
-
+	cLevel(5) {
+		cLevel(7)
+			setHigh;
+		else
+			unsetHigh;
+		compressed[COMPRESS_LZG_UD]=getMemory(2*imageSizeInBytes+1050);
+		compressLzg(
+			image->pix,imageSizeInBytes,
+			compressed[COMPRESS_LZG_UD],&(compressedSize[COMPRESS_LZG_UD])
+		);
+		max_alg++;
+	}
 	/*
 		Process results
 	*/
@@ -246,7 +328,7 @@ int mCompressGraphic(unsigned char* *data,tImage* image, int* dataSizeInBytes) {
 	/* Select the best compression (find minimum) */
 	*dataSizeInBytes=compressedSize[COMPRESS_RAW];
 	algorithm=COMPRESS_RAW;
-	for (i=COMPRESS_RLE_LR;i<COMPRESS_WORKING_ALGORITHMS;i++) {
+	for (i=COMPRESS_RLE_LR;i<max_alg;i++) {
 		if ((*dataSizeInBytes)>compressedSize[i]) {
 			(*dataSizeInBytes)=compressedSize[i];
 			algorithm=i;
@@ -273,7 +355,7 @@ int mCompressGraphic(unsigned char* *data,tImage* image, int* dataSizeInBytes) {
 	(*data)[5]=image->type|algorithm;
 
 	/* Free all compression attempts */
-	for (i=COMPRESS_RAW;i<COMPRESS_WORKING_ALGORITHMS;i++) free(compressed[i]);
+	for (i=COMPRESS_RAW;i<max_alg;i++) free(compressed[i]);
 	return 1;
 }
 
diff --git a/PR/src/lib/object/image/image256.c b/PR/src/lib/object/image/image256.c
index 74c09fb..6ae190b 100644
--- a/PR/src/lib/object/image/image256.c
+++ b/PR/src/lib/object/image/image256.c
@@ -39,6 +39,50 @@ compress.c: Princed Resources : Image Compression Library
 #include "pr.h"
 #include "disk.h" /* array2short */
 
+/* Compression level explanation:
+ *
+ * Definitions:
+ *  no compression is called RAW
+ *  there are 2 algorithms types: RLE and LZG
+ *  we can use the modifier: transpose and not transpose (t)
+ *  we can use the LZG modifier: Faster (checks faster the LZG window ignoring
+ *   less probable pattern) (+)
+ *
+ *  So the possible compression algorithms are:
+ *   RAW, RLE, RLEt, LZG, LZGt, LZG+, LZGt+
+ *  
+ *  It is known that LZG+ allways compresses better or equal than LZG
+ *
+ * Depending on the compression level, the compressor will compress with
+ * all the algorithms specified and keep only the smaller result using
+ * the following table
+ * 
+ * Level  Algorithms
+ *   1    RAW
+ *   2    RAW, RLE
+ *   3    RAW, RLE, RLEt
+ *   4    RAW, RLE, RLEt, LZG
+ *   5    RAW, RLE, RLEt, LZG, LZGt
+ *   6    RAW, RLE, RLEt, LZG+, LZGt
+ *   7    RAW, RLE, RLEt, LZG+, LZGt+
+ *
+ * The default level used in PR will be 3.
+ *
+ * In images with big enthropy that generates DAT files bigger than 64kb, using
+ * a better compression is a must. The POP1 DAT file format has this limitation
+ * and the only way to get through with it is improving the compression.
+ *
+ * For testing DAT files that are not for distribution compression 3 is highly
+ * recomended because is much faster and you perform compressions more often.
+ * 
+ * When you release a DAT file a compression level 7 is the best you can use.
+ * You'll have to wait some time to get the importing, but the decompression
+ * is as faster as the decompression in other levels. The game supports it and
+ * decompresses the files very fast. Another advantage is that it is better to
+ * distribute smaller dat files.
+ *
+ */
+
 /***************************************************************\
 |                  I M P L E M E N T A T I O N                  |
 \***************************************************************/
@@ -59,6 +103,17 @@ int expandLzg(const unsigned char* input, int inputSize,
 int expandRle(const unsigned char* input, int inputSize, 
                unsigned char** output, int *outputSize);
 
+/***************************************************************\
+|                   Compression Level Manager                   |
+\***************************************************************/
+
+int compressionLevel=3;
+int compressionHigher;
+
+void setCompressionLevel(int cl) {
+	compressionLevel=cl;
+}
+
 /***************************************************************\
 |                        Image transpose                        |
 \***************************************************************/
@@ -125,29 +180,37 @@ int mExpandGraphic(const unsigned char* data,tImage *image, int dataSizeInBytes)
 	} else {
 		image->widthInBytes=(image->width+7)/8;
 	}
-	imageSizeInBytes=image->widthInBytes*image->height;
 
+#define checkSize if (imageSizeInBytes!=(image->widthInBytes*image->height))\
+	return COMPRESS_RESULT_FATAL
+#define checkResult if (result==COMPRESS_RESULT_FATAL)\
+	return COMPRESS_RESULT_FATAL
+	
 	switch (getAlgor(image->type)) {
 		case COMPRESS_RAW: /* No Compression Algorithm */
-						/* TODO: use dataSize */
-			if ((image->pix=getMemory(imageSizeInBytes))==NULL) return COMPRESS_RESULT_FATAL;
-			memcpy(image->pix,data,imageSizeInBytes);
+			if ((image->pix=getMemory(dataSizeInBytes))==NULL) return COMPRESS_RESULT_FATAL;
+			memcpy(image->pix,data,dataSizeInBytes);
+			imageSizeInBytes=image->widthInBytes*image->height;
 			result=COMPRESS_RESULT_SUCCESS;
 			break;
 		case COMPRESS_RLE_LR: /* RLE Left to Right Compression Algorithm */
 			result=expandRle(data,dataSizeInBytes,&(image->pix),&imageSizeInBytes);
+			checkSize;
 			break;
 		case COMPRESS_RLE_UD: /* RLE Up to Down Compression Algorithm */
 			result=expandRle(data,dataSizeInBytes,&(image->pix),&imageSizeInBytes);
-			if (result==COMPRESS_RESULT_FATAL) return COMPRESS_RESULT_FATAL;
+			checkResult;
+			checkSize;
 			transposeImage(image,imageSizeInBytes);
 			break;
 		case COMPRESS_LZG_LR: /* LZ Groody Left to Right Compression Algorithm */
 			result=expandLzg(data,dataSizeInBytes,&(image->pix),&imageSizeInBytes);
+			checkSize;
 			break;
 		case COMPRESS_LZG_UD: /* LZ Groody Up to Down Compression Algorithm */
 			result=expandLzg(data,dataSizeInBytes,&(image->pix),&imageSizeInBytes);
-			if (result==COMPRESS_RESULT_FATAL) return COMPRESS_RESULT_FATAL;
+			checkResult;
+			checkSize;
 			transposeImage(image,imageSizeInBytes);
 			break;
 		default:
@@ -165,6 +228,7 @@ int mCompressGraphic(unsigned char* *data,tImage* image, int* dataSizeInBytes) {
 	int            algorithm;
 	int            i;
 	int            imageSizeInBytes;
+	int            max_alg=1;
 
 	/* Initialize variables */
 	imageSizeInBytes=image->widthInBytes*image->height;
@@ -194,12 +258,14 @@ int mCompressGraphic(unsigned char* *data,tImage* image, int* dataSizeInBytes) {
 	 * size plus a byte each 127 bytes.
 	 * This is accoted by 2*n+50
 	 */
-	compressed[COMPRESS_RLE_LR]=getMemory((2*imageSizeInBytes+50)); 
-	compressRle(
-		image->pix,imageSizeInBytes,
-		compressed[COMPRESS_RLE_LR],&(compressedSize[COMPRESS_RLE_LR])
-	);
-
+	cLevel(2) {
+		compressed[COMPRESS_RLE_LR]=getMemory((2*imageSizeInBytes+50)); 
+		compressRle(
+			image->pix,imageSizeInBytes,
+			compressed[COMPRESS_RLE_LR],&(compressedSize[COMPRESS_RLE_LR])
+		);
+		max_alg++;
+	}
 	/* COMPRESS_LZG_LR 
 	 * If all the uncompressed data has a big enthropy, there
 	 * will be a maskbyte for a block of 8 bytes.
@@ -209,12 +275,18 @@ int mCompressGraphic(unsigned char* *data,tImage* image, int* dataSizeInBytes) {
 	 * allocated.
 	 * This is accoted by 2*n+1050
 	 */
-	compressed[COMPRESS_LZG_LR]=getMemory((2*imageSizeInBytes+1050));
-	compressLzg(
-		image->pix,imageSizeInBytes,
-		compressed[COMPRESS_LZG_LR],&(compressedSize[COMPRESS_LZG_LR])
-	);
-	
+	cLevel(4) {
+		cLevel(6)
+			setHigh;
+		else
+			unsetHigh;
+		compressed[COMPRESS_LZG_LR]=getMemory((2*imageSizeInBytes+1050));
+		compressLzg(
+			image->pix,imageSizeInBytes,
+			compressed[COMPRESS_LZG_LR],&(compressedSize[COMPRESS_LZG_LR])
+		);
+		max_alg++;
+	}
 
 	/* Transposed compression
 	 * Transposition is used to test the same compression
@@ -223,22 +295,32 @@ int mCompressGraphic(unsigned char* *data,tImage* image, int* dataSizeInBytes) {
 	 * The following algorithms will be the same as above, but
 	 * using the image matrix transposed.
 	 */
-	antiTransposeImage(image,imageSizeInBytes);
+	cLevel(3) 
+		antiTransposeImage(image,imageSizeInBytes);
 
 	/* COMPRESS_RLE_UD */
-	compressed[COMPRESS_RLE_UD]=getMemory(2*imageSizeInBytes+50);
-	compressRle(
-		image->pix,imageSizeInBytes,
-		compressed[COMPRESS_RLE_UD],&(compressedSize[COMPRESS_RLE_UD])
-	);
+	cLevel(3) {
+		compressed[COMPRESS_RLE_UD]=getMemory(2*imageSizeInBytes+50);
+		compressRle(
+			image->pix,imageSizeInBytes,
+			compressed[COMPRESS_RLE_UD],&(compressedSize[COMPRESS_RLE_UD])
+		);
+		max_alg++;
+	}
 
 	/* COMPRESS_LZG_UD */
-	compressed[COMPRESS_LZG_UD]=getMemory(2*imageSizeInBytes+1050);
-	compressLzg(
-		image->pix,imageSizeInBytes,
-		compressed[COMPRESS_LZG_UD],&(compressedSize[COMPRESS_LZG_UD])
-	);
-
+	cLevel(5) {
+		cLevel(7)
+			setHigh;
+		else
+			unsetHigh;
+		compressed[COMPRESS_LZG_UD]=getMemory(2*imageSizeInBytes+1050);
+		compressLzg(
+			image->pix,imageSizeInBytes,
+			compressed[COMPRESS_LZG_UD],&(compressedSize[COMPRESS_LZG_UD])
+		);
+		max_alg++;
+	}
 	/*
 		Process results
 	*/
@@ -246,7 +328,7 @@ int mCompressGraphic(unsigned char* *data,tImage* image, int* dataSizeInBytes) {
 	/* Select the best compression (find minimum) */
 	*dataSizeInBytes=compressedSize[COMPRESS_RAW];
 	algorithm=COMPRESS_RAW;
-	for (i=COMPRESS_RLE_LR;i<COMPRESS_WORKING_ALGORITHMS;i++) {
+	for (i=COMPRESS_RLE_LR;i<max_alg;i++) {
 		if ((*dataSizeInBytes)>compressedSize[i]) {
 			(*dataSizeInBytes)=compressedSize[i];
 			algorithm=i;
@@ -273,7 +355,7 @@ int mCompressGraphic(unsigned char* *data,tImage* image, int* dataSizeInBytes) {
 	(*data)[5]=image->type|algorithm;
 
 	/* Free all compression attempts */
-	for (i=COMPRESS_RAW;i<COMPRESS_WORKING_ALGORITHMS;i++) free(compressed[i]);
+	for (i=COMPRESS_RAW;i<max_alg;i++) free(compressed[i]);
 	return 1;
 }
 
diff --git a/PR/src/lib/object/image/image_common.c b/PR/src/lib/object/image/image_common.c
index 74c09fb..6ae190b 100644
--- a/PR/src/lib/object/image/image_common.c
+++ b/PR/src/lib/object/image/image_common.c
@@ -39,6 +39,50 @@ compress.c: Princed Resources : Image Compression Library
 #include "pr.h"
 #include "disk.h" /* array2short */
 
+/* Compression level explanation:
+ *
+ * Definitions:
+ *  no compression is called RAW
+ *  there are 2 algorithms types: RLE and LZG
+ *  we can use the modifier: transpose and not transpose (t)
+ *  we can use the LZG modifier: Faster (checks faster the LZG window ignoring
+ *   less probable pattern) (+)
+ *
+ *  So the possible compression algorithms are:
+ *   RAW, RLE, RLEt, LZG, LZGt, LZG+, LZGt+
+ *  
+ *  It is known that LZG+ allways compresses better or equal than LZG
+ *
+ * Depending on the compression level, the compressor will compress with
+ * all the algorithms specified and keep only the smaller result using
+ * the following table
+ * 
+ * Level  Algorithms
+ *   1    RAW
+ *   2    RAW, RLE
+ *   3    RAW, RLE, RLEt
+ *   4    RAW, RLE, RLEt, LZG
+ *   5    RAW, RLE, RLEt, LZG, LZGt
+ *   6    RAW, RLE, RLEt, LZG+, LZGt
+ *   7    RAW, RLE, RLEt, LZG+, LZGt+
+ *
+ * The default level used in PR will be 3.
+ *
+ * In images with big enthropy that generates DAT files bigger than 64kb, using
+ * a better compression is a must. The POP1 DAT file format has this limitation
+ * and the only way to get through with it is improving the compression.
+ *
+ * For testing DAT files that are not for distribution compression 3 is highly
+ * recomended because is much faster and you perform compressions more often.
+ * 
+ * When you release a DAT file a compression level 7 is the best you can use.
+ * You'll have to wait some time to get the importing, but the decompression
+ * is as faster as the decompression in other levels. The game supports it and
+ * decompresses the files very fast. Another advantage is that it is better to
+ * distribute smaller dat files.
+ *
+ */
+
 /***************************************************************\
 |                  I M P L E M E N T A T I O N                  |
 \***************************************************************/
@@ -59,6 +103,17 @@ int expandLzg(const unsigned char* input, int inputSize,
 int expandRle(const unsigned char* input, int inputSize, 
                unsigned char** output, int *outputSize);
 
+/***************************************************************\
+|                   Compression Level Manager                   |
+\***************************************************************/
+
+int compressionLevel=3;
+int compressionHigher;
+
+void setCompressionLevel(int cl) {
+	compressionLevel=cl;
+}
+
 /***************************************************************\
 |                        Image transpose                        |
 \***************************************************************/
@@ -125,29 +180,37 @@ int mExpandGraphic(const unsigned char* data,tImage *image, int dataSizeInBytes)
 	} else {
 		image->widthInBytes=(image->width+7)/8;
 	}
-	imageSizeInBytes=image->widthInBytes*image->height;
 
+#define checkSize if (imageSizeInBytes!=(image->widthInBytes*image->height))\
+	return COMPRESS_RESULT_FATAL
+#define checkResult if (result==COMPRESS_RESULT_FATAL)\
+	return COMPRESS_RESULT_FATAL
+	
 	switch (getAlgor(image->type)) {
 		case COMPRESS_RAW: /* No Compression Algorithm */
-						/* TODO: use dataSize */
-			if ((image->pix=getMemory(imageSizeInBytes))==NULL) return COMPRESS_RESULT_FATAL;
-			memcpy(image->pix,data,imageSizeInBytes);
+			if ((image->pix=getMemory(dataSizeInBytes))==NULL) return COMPRESS_RESULT_FATAL;
+			memcpy(image->pix,data,dataSizeInBytes);
+			imageSizeInBytes=image->widthInBytes*image->height;
 			result=COMPRESS_RESULT_SUCCESS;
 			break;
 		case COMPRESS_RLE_LR: /* RLE Left to Right Compression Algorithm */
 			result=expandRle(data,dataSizeInBytes,&(image->pix),&imageSizeInBytes);
+			checkSize;
 			break;
 		case COMPRESS_RLE_UD: /* RLE Up to Down Compression Algorithm */
 			result=expandRle(data,dataSizeInBytes,&(image->pix),&imageSizeInBytes);
-			if (result==COMPRESS_RESULT_FATAL) return COMPRESS_RESULT_FATAL;
+			checkResult;
+			checkSize;
 			transposeImage(image,imageSizeInBytes);
 			break;
 		case COMPRESS_LZG_LR: /* LZ Groody Left to Right Compression Algorithm */
 			result=expandLzg(data,dataSizeInBytes,&(image->pix),&imageSizeInBytes);
+			checkSize;
 			break;
 		case COMPRESS_LZG_UD: /* LZ Groody Up to Down Compression Algorithm */
 			result=expandLzg(data,dataSizeInBytes,&(image->pix),&imageSizeInBytes);
-			if (result==COMPRESS_RESULT_FATAL) return COMPRESS_RESULT_FATAL;
+			checkResult;
+			checkSize;
 			transposeImage(image,imageSizeInBytes);
 			break;
 		default:
@@ -165,6 +228,7 @@ int mCompressGraphic(unsigned char* *data,tImage* image, int* dataSizeInBytes) {
 	int            algorithm;
 	int            i;
 	int            imageSizeInBytes;
+	int            max_alg=1;
 
 	/* Initialize variables */
 	imageSizeInBytes=image->widthInBytes*image->height;
@@ -194,12 +258,14 @@ int mCompressGraphic(unsigned char* *data,tImage* image, int* dataSizeInBytes) {
 	 * size plus a byte each 127 bytes.
 	 * This is accoted by 2*n+50
 	 */
-	compressed[COMPRESS_RLE_LR]=getMemory((2*imageSizeInBytes+50)); 
-	compressRle(
-		image->pix,imageSizeInBytes,
-		compressed[COMPRESS_RLE_LR],&(compressedSize[COMPRESS_RLE_LR])
-	);
-
+	cLevel(2) {
+		compressed[COMPRESS_RLE_LR]=getMemory((2*imageSizeInBytes+50)); 
+		compressRle(
+			image->pix,imageSizeInBytes,
+			compressed[COMPRESS_RLE_LR],&(compressedSize[COMPRESS_RLE_LR])
+		);
+		max_alg++;
+	}
 	/* COMPRESS_LZG_LR 
 	 * If all the uncompressed data has a big enthropy, there
 	 * will be a maskbyte for a block of 8 bytes.
@@ -209,12 +275,18 @@ int mCompressGraphic(unsigned char* *data,tImage* image, int* dataSizeInBytes) {
 	 * allocated.
 	 * This is accoted by 2*n+1050
 	 */
-	compressed[COMPRESS_LZG_LR]=getMemory((2*imageSizeInBytes+1050));
-	compressLzg(
-		image->pix,imageSizeInBytes,
-		compressed[COMPRESS_LZG_LR],&(compressedSize[COMPRESS_LZG_LR])
-	);
-	
+	cLevel(4) {
+		cLevel(6)
+			setHigh;
+		else
+			unsetHigh;
+		compressed[COMPRESS_LZG_LR]=getMemory((2*imageSizeInBytes+1050));
+		compressLzg(
+			image->pix,imageSizeInBytes,
+			compressed[COMPRESS_LZG_LR],&(compressedSize[COMPRESS_LZG_LR])
+		);
+		max_alg++;
+	}
 
 	/* Transposed compression
 	 * Transposition is used to test the same compression
@@ -223,22 +295,32 @@ int mCompressGraphic(unsigned char* *data,tImage* image, int* dataSizeInBytes) {
 	 * The following algorithms will be the same as above, but
 	 * using the image matrix transposed.
 	 */
-	antiTransposeImage(image,imageSizeInBytes);
+	cLevel(3) 
+		antiTransposeImage(image,imageSizeInBytes);
 
 	/* COMPRESS_RLE_UD */
-	compressed[COMPRESS_RLE_UD]=getMemory(2*imageSizeInBytes+50);
-	compressRle(
-		image->pix,imageSizeInBytes,
-		compressed[COMPRESS_RLE_UD],&(compressedSize[COMPRESS_RLE_UD])
-	);
+	cLevel(3) {
+		compressed[COMPRESS_RLE_UD]=getMemory(2*imageSizeInBytes+50);
+		compressRle(
+			image->pix,imageSizeInBytes,
+			compressed[COMPRESS_RLE_UD],&(compressedSize[COMPRESS_RLE_UD])
+		);
+		max_alg++;
+	}
 
 	/* COMPRESS_LZG_UD */
-	compressed[COMPRESS_LZG_UD]=getMemory(2*imageSizeInBytes+1050);
-	compressLzg(
-		image->pix,imageSizeInBytes,
-		compressed[COMPRESS_LZG_UD],&(compressedSize[COMPRESS_LZG_UD])
-	);
-
+	cLevel(5) {
+		cLevel(7)
+			setHigh;
+		else
+			unsetHigh;
+		compressed[COMPRESS_LZG_UD]=getMemory(2*imageSizeInBytes+1050);
+		compressLzg(
+			image->pix,imageSizeInBytes,
+			compressed[COMPRESS_LZG_UD],&(compressedSize[COMPRESS_LZG_UD])
+		);
+		max_alg++;
+	}
 	/*
 		Process results
 	*/
@@ -246,7 +328,7 @@ int mCompressGraphic(unsigned char* *data,tImage* image, int* dataSizeInBytes) {
 	/* Select the best compression (find minimum) */
 	*dataSizeInBytes=compressedSize[COMPRESS_RAW];
 	algorithm=COMPRESS_RAW;
-	for (i=COMPRESS_RLE_LR;i<COMPRESS_WORKING_ALGORITHMS;i++) {
+	for (i=COMPRESS_RLE_LR;i<max_alg;i++) {
 		if ((*dataSizeInBytes)>compressedSize[i]) {
 			(*dataSizeInBytes)=compressedSize[i];
 			algorithm=i;
@@ -273,7 +355,7 @@ int mCompressGraphic(unsigned char* *data,tImage* image, int* dataSizeInBytes) {
 	(*data)[5]=image->type|algorithm;
 
 	/* Free all compression attempts */
-	for (i=COMPRESS_RAW;i<COMPRESS_WORKING_ALGORITHMS;i++) free(compressed[i]);
+	for (i=COMPRESS_RAW;i<max_alg;i++) free(compressed[i]);
 	return 1;
 }