/******************************************************************************
* 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;
}
|