This section of the archives stores flipcode's complete Developer Toolbox collection, featuring a variety of mini-articles and source code contributions from our readers.

| RLE Compression / Decompression Submitted by

Does your program contain data with long stretches where the same byte repeats over and over? If you do, you can use RLE compression to reduce the size of the data on the disk. These two functions implement RLE compression for loading and saving data from a file. RLE compression works by identifying blocks of repeating bytes, called runs, and replacing them with a token indicating the number of repetitions and single copy of the original repeating byte. To differentiate between run-length tokens and ordinary data, the routine inserts data-length tokens before blocks of nonrepeating data. Because of the overhead of these data-length tokens, RLE compression is only effective if your data contains at least one run longer than four bytes per every 128 nonrepeating bytes. Obviously, this form of compression is not for everyone. If you do decide to use it, though, feel free to copy this code and use it in your program. -SwansonTec

Download Associated File: RLE.c (2,064 bytes)

    /******************************************************************************
     * LoadRLE / SaveRLE - Load and save binary data using RLE compression.
     *	Run-length tokens have a set MSB, while data tokens have a cleared
     *	MSB. The value of the token's remaining bits plus one indicates the
     *	length of the block. The minimum run length is three bytes, while
     *	the maximum is 128.
     *
     *	data - Array holding data to load or save.
     *	size - Size of the data array.
     *	file - The file pointer to use.
     *	return - Total number of bytes read from or written to data[].
     */

    size_t LoadRLE (unsigned char data[], size_t size, FILE *file)
    {
    	unsigned char token;
    	unsigned int length;
    	size_t total = 0;

    	while(size && fread(&token, 1, 1, file)){
    		length = (token & ~0x80) + 1;
    		if (length > size)
    			return total;
    		if(token & 0x80){
    			if(!fread(&token, 1, 1, file))
    				return total;
    			memset(data, token, length);
    		}else{
    			if(fread(data, 1, length, file) != length)
    				return total;
    		}
    		data += length, size -= length, total += length;
    	}
    	return total;
    }

    /*************************************/

    size_t SaveRLE (unsigned char data[], size_t size, FILE *file)
    {
    	unsigned char token;
    	unsigned int i;
    	size_t total = 0;

    	while(size)
    	{
    		/*This loop identifies blocks of repeating data:*/
    		i = 2;
    		while(i < size && i < 128 &&
    			data[i] == data[i - 1] && data[i - 1] == data[i - 2])
    			i++;
    		/*If repeating data was found, save it:*/
    		if(i > 2){
    			token = i - 1 | 0x80;
    			if(!fwrite(&token, 1, 1, file))
    				return total;
    			if(!fwrite(data, 1, 1, file))
    				return total;
    			data += i, size -= i, total += i;
    		}

    		/*This loop identifies blocks of non-repeating data:*/
    		i = 0;
    		while(i < size && i < 128 && (i + 2 > size ? 1 :
    			data[i] != data[i + 1] || data[i + 1] != data[i + 2]))
    			i++;
    		/*If non-repeating data was found, save it:*/
    		if(i){
    			token = i - 1;
    			if(!fwrite(&token, 1, 1, file))
    				return total;
    			if(fwrite(data, 1, i, file) != i)
    				return total;
    			data += i, size -= i, total += i;
    		}
    	}

    	return total;
    }

The zip file viewer built into the Developer Toolbox made use of the zlib library, as well as the zlibdll source additions.

Copyright 1999-2008 (C) FLIPCODE.COM and/or the original content author(s). All rights reserved.
Please read our Terms, Conditions, and Privacy information.