chevron_left chevron_right
Login Register invert_colors photo_library


Stay updated and chat with others! - Join the Discord!
Thread Rating:
  • 0 Vote(s) - 0 Average


Dysfunctional Run Length Encoder filter_list
Author
Message
Run Length Encoder #1
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);
}

Reply

RE: Run Length Encoder #2
I'm going to try to port this over to Python. It'll be nice practice.

Reply

RE: Run Length Encoder #3
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");
- You should use the 'argc' parameter to confirm that those indexes is a valid index in 'argv', and check the string length of the first argument at index [1] to validate that enough characters exist to index up to [1].

I may see more things after I look at this some more.

Reply

RE: Run Length Encoder #4
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.

Reply






Users browsing this thread: 1 Guest(s)