![]() |
|
Run Length Encoder - Printable Version +- Sinisterly (https://sinister.li) +-- Forum: Coding (https://sinister.li/Forum-Coding) +--- Forum: C, C++, & Obj-C (https://sinister.li/Forum-C-C-Obj-C) +--- Thread: Run Length Encoder (/Thread-Run-Length-Encoder) |
Run Length Encoder - phyrrus9 - 06-25-2015 For those of you who read my tutorial on RLE (link), here is some sample C code to accomplish it. Code: /* Run Length Encoder/Decoder
* by Ethan Laur (phyrrus9)
*/
#include <stdio.h>
int readuntilnext(FILE *in, unsigned char last, unsigned char *oops, unsigned char *n)
{
int nread;
*n = 1;
while ((nread = fread(oops, 1, 1, in)) > 0) //read
{
if (*oops != last || *n > 254)
return 1; //return count if different
++*n; //add 1 to count
}
return 0;
}
void rleEncode(FILE *in, FILE *out, unsigned char flag)
{
unsigned char old = 0, buf, num;
int i;
readuntilnext(in, old, &buf, &num); //first time reads nothing...
old = buf;
while (readuntilnext(in, old, &buf, &num)) //read
{
if (num > 3) //then RLE that shit
{
fputc(flag, out); //place the flag
fwrite(&num, 1, 1, out); //place the count
fwrite(&old, 1, 1, out); //place the character
}
else
fwrite(&old, 1, 1, out); //place the character
old = buf; //do swap
}
fflush(out); //write caches
}
void rleDecode(FILE *in, FILE *out, unsigned char flag)
{
unsigned char buf, num;
int i;
while (fread(&buf, 1, 1, in) > 0) //while we read something
{
if (buf == flag) //if the character was the RLE flag
{
fread(&num, 1, 1, in); //get the number
fread(&buf, 1, 1, in); //get the character
for (i = 0; i < num; i++) //loop num times
fwrite(&buf, 1, 1, out); //output character
}
else
fwrite(&buf, 1, 1, out); //output character
}
fflush(out); //write any caches to disk
}
int main(int argc, char ** argv)
{
FILE *in = fopen(argv[2], "rb");
FILE *out = fopen(argv[3], "wb");
if (argv[1][0] == 'e')
rleEncode(in, out, argv[1][1]);
else if (argv[1][0] == 'd')
rleDecode(in, out, argv[1][1]);
fclose(in);
fclose(out);
}RE: Run Length Encoder - Eclipse - 06-25-2015 I'm going to try to port this over to Python. It'll be nice practice. RE: Run Length Encoder - 0xDEAD10CC - 06-28-2015 Not bad, but a few things I noticed: - You assign to a local variable 'nread' but never use it in any codebranch in the readuntilnext function. - 'i' is an unused variable in your rleEncode function. - You should check that the files returned from fopen() are successfully opened and that the function doesn't return a null pointer, especially if you use the pointers right away and call fclose() Code: FILE *in = fopen(argv[2], "rb");
FILE *out = fopen(argv[3], "wb");I may see more things after I look at this some more. RE: Run Length Encoder - 0xDEAD10CC - 06-28-2015 Here's my version: Code: #include <stdio.h>
#include <stdlib.h>
/* DESCRIPTION: Compresses input file to specified output file using
* standard RLE encoding for compression.
* (Useful for data with frequent runs.)
* RETURNS: 0 on failure, 1 on success.
* ------------------------------------------------------- */
int rle_compress(FILE *in, FILE *out)
{
int ch = fgetc(in), tmp, count = 1;
while (!feof(in))
{
while ((tmp = fgetc(in)) == ch)
++count;
if (ferror(out)) return 0;
fprintf(out, "%d", count);
putc(ch, out);
ch = tmp;
count = 1;
}
return 1;
}
/* DESCRIPTION: Decompresses input file with RLE encoded data to specified
* output file. (Ex format: 1Z3D2Y = ZDDDYY)
* RETURNS: 0 on failure, 1 on success.
* ------------------------------------------------------- */
int rle_decompress(FILE *in, FILE *out)
{
int i, ch, count;
while (!feof(in))
{
if (!fscanf(in, " %d", &count)
|| (ch = fgetc(in)) == EOF) return 0;
for (i = 0; i < count; ++i) putc(ch, out);
}
return 1;
}
int main(void)
{
FILE *in = fopen("input.txt", "rb");
FILE *out = fopen("output.txt", "wb");
if (!(in && out))
{
perror("fopen");
exit(1);
}
/* depending on whether input.txt is encoded, or not encoded... */
rle_decompress(in, out);
/* or... */
rle_compress(in, out);
fclose(in);
fclose(out);
return 0;
}NOTE: Works only with non-numeric characters. Some adjustments would need to be made to differentiate between the # and the data in the case of digit characters. |