0

I'm new to coding in c. I want to decode RLE encoded binary files (vintage, rare pic format) with these conditions:

character, followed by number of characters

run count is valid for counts >=4

0 is encoded 00 00

1 is encoded 00 01

10 (hex ?) is LF

EOF is encoded as 00 03

bottom byte (after EOF is 0A)

there's a 2 byte count: , 4<=<=127 , >8> ! 128, &255, examples

0 1 2 3 4 5 encodes as 0 0 1 2 3 4 5 encode 0 as 0,0

5 6 7 8 9 10 encodes as 5 6 7 8 9 0 1 encode 10 as 0,1

5...(200 times) encodes as 5 0 128 200 long repeat count of 200

7...(515 times) encodes as 7 0 130 3 long repeat count of 16_203

The file format is complicated and includes:

variable header length (512/1024 bytes) different compressions, including different RLE compressions (horizontal, vertical) variable color maps (variable lengths) and none, stereo pics, CAD pics, fractals, geosat pics, etc, but for now I just want to decode headerless data.

I searched a lot for RLE here and elsewhere and tried for some days but there are mainly threads about strings and none about selected conditions like for character 0 etc. And especially for checking 3 Bytes.

I have documents and codes in 2 older languages including Assembler. I found here a similar code in c++ but I couldn't translate it properly. I managed to make some c programs without compiling errors, but the result is wrong.

The best code is below. It reads multiple bytes but missing some "00" bytes. Bytes 1+3 are correct. Byte 2 is 0, Byte 4 missing. The output to file is completely wrong and just 3 bytes. Even the 1st byte is wrong. (80)
I'm confused reading 3 bytes with 2 variables. Byte flipping? Can anybody help? Thanks!

while (!feof(fp1))
    {              //originally also have to check if 1st char=10 (LF) and overrides that 
         if(fread(buf,1,2,fp1)!=2) //Read two bytes: original code was number of characters + characters
                  // but I have characters + number of ch, and more conditions    
             
            continue; // was break;
        ch = buf[0]; //was num ch instead of ch, also swapped below at buf 1
        printf("%x\n", ch); //later added this to output to screen, reads more than output but bytes like 0 missing
          if(ch==0) {
                if(ch==1) {
                ch=10;        // code for LF    
                continue;         // is this correct?  continue or return (0) or -1? same below
           }else{    
                if(ch==0) {
                ch=0;         // 00 00 encoded as 0  
                continue;   
           }else{    
                if(ch==3);    //EOF, after that bottom byte 0A follows
                return (0);   
                }   
           }                  //else beep? return -1, break, but I rely on proper image not having 00 04...
          }
    }
        num = buf[1];
        char * chbuf = (char *)malloc(num);   
                                          //main code from_WRITE IMAGE, although read
            if(num==1) {        // no action               v----------v-----------v-------
            } else if (num<4) {   // run counts only when count =>4    
                
             for (int i =0;i < num;i++)   
                 chbuf[i] = ch;
             fwrite(&chbuf,1,num,fp2);        //num ? ,1? or 0    was fwrite(chbuf
             }else if (num<=127); {
             for (int i =0;i < num;i++)                     
                  chbuf[i] = num;               ////newest added is this right?
            if (num==10) {      
            fwrite(&chbuf,1,num,fp2); //num--;   //num ?, or is it ch or char or i?
           }else {
           if ((ch&255)==10) {                 // was num&, I tried all, num and ch , always wrong 
           num++;    
           fwrite(&chbuf,1,ch,fp2);  // was num--; at end
           num++;                   // is num++ right? but neverless always just 3 bytes
           fwrite(&chbuf,2,((unsigned) num>>8|0x80),fp2); // was chbuf 1, also checked unsigned char, 80, else 
           num++;
           fwrite(&chbuf,1,ch,fp2); // was 1
           } 
          }
             }
         free(chbuf);   

New code 3

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
//3rd code this time with internal string, code 2 worked (read 2 bytes from file, print to screen) 
int i, j;            //output should be 88 times 05, 4 times 06
int main()
{
        char string[] = "0500580604"; //hex test input to not have external file
                                       //for now no check for conditions like EOF, 00 at begin
        int number1 = atoi(string [0]); //convert string to byte was [1]
        int number2 = atoi(string [1]);
        int number3 = atoi(string [2]);
        if (number2 == 0){        //read byte 2 and check if it's a count, Byte 1 is a char
            if (number2 >=4){     //check byte 2 if valid count or char
            }else {printf("%x\n", number1, number2); //byte 2 is a char 
        } return (0);
            if (number3<127){ //check byte 3 if its a long run
                for (int i =0;i < number2;i++) // print byte2 times the char   
                printf("%x\n", number1);
            }else {
            for (int i =0;i <number3;i++) //print byte3 times the char
            printf("%x\n", number1);
           return (0); 
            }
           }
          }
  • [while (!feof(fp1))](https://stackoverflow.com/questions/5431941/why-is-while-feof-file-always-wrong) may be a problem. – ryyker Mar 01 '21 at 19:25
  • Thanks! I had trouble replacing that. while (fread(fp1, 1, 2) == 1); ->errors too few arguments. while (fscanf(fp1, 1, 2) == 1); -> warnings & errors ("continue") , return 0= segfault. while ((ret = fscanf(fp1, "%x", &num)) !=EOF) + getc(fp1);, warnings and puts out lots of "7f17". Now I made a new start, just for read. I found a code elsewhere via Google that works. First it reads too many bytes then none. Then I manage to read 2 bytes and go step by step printing all bytes and variables. Currently I don't use "while". I have "i" undeclared" although I have "for int i". Very time consuming. – rleencoder Mar 02 '21 at 18:13
  • LOL, is there another question there? It kind of sounds like you got something working, but not sure :) – ryyker Mar 02 '21 at 18:35
  • As said, I read 2 bytes and they are right. I think, I need a 3rd variable for reading byte 3. The original code just used 2. Not sure if I should use a loop with while or for or with ++ values. As said I'm a beginner. I even have problems with printf (string, value, string). I have some skills in BASIC long time ago. I can only do trial and error and search the web. Not sure how many days I will spend on this. – rleencoder Mar 02 '21 at 19:03
  • Okay, From the last two comments it appears you have done some work, but it is hard to understand. I would be happy, (or perhaps another) to help if you can re-factor the code in your post to conform to a [mcve]. So, create a simple `main(..){...}` including the new code you have created, but it must be compilable. If you do that and leave another comment I will take a look. – ryyker Mar 02 '21 at 20:41
  • I tried lots did research for weeks. I wonder what is so hard to understand about my clear description. My new code 2 could read + print 2 bytes and works. I considered to better first try it in BASIC or use the ASS code I've got. But I tried it once more. Code 3 above. I assumed you don't want external files, so I included a string (I had to learn about that before). So this is the result of ~4 hours. I haven't included the tests for the conditions, they don't appear at the beginning either. I made it simple to just read 3 bytes. Compiles with warnings. Result segfault. – rleencoder Mar 03 '21 at 10:10
  • Some notes on your 3rd attempt: 1) comment after `string` variable suggests it's hex, but `atoi` assumes decimal, 2) `atoi` parses a null-terminated string, not a single character (or two-character hex representation of a char), 3) array indexing starts at zero in `c`, 4) if your `number2 == 0` test is true, there's no point in testing `number2 >= 4` - wrong variable? – 500 - Internal Server Error Mar 03 '21 at 10:31
  • Thanks. 1)Hex or dec doesn't matter for now as values are <10. 127 is also dec. 2) I don't understand what's a null-terminated string. 3) String 0 is in char string [] but you mean number1 ?, 4) I think I have to check both if it's a byte (0) and if it's a valid count. If 00->test byte 3. If >3 it's a short run. Whats wrong? – rleencoder Mar 03 '21 at 10:43
  • As for 2), null-terminated means e.g. that `atoi(string [7])` evaluates `604`. As for 4), you're only do the test `number2 >= 4` when you already know it's zero, so that will never be true - I think you meant something else there. – 500 - Internal Server Error Mar 03 '21 at 12:00
  • If I am interpreting this correctly, in this code snippet you have provided `"0500580604"` to simulate a very short sample of what might be found in the non-header section of a _vintage, rare pic format RLE binary file_, and you want to decode this. For this sample input, please show the expected output. (Typically for a question like this it is useful to provide a given input, as you have, but then _also show the expected output_. then say something about where you believe the code is failing to provide what is expected. – ryyker Mar 03 '21 at 14:34
  • The expected output is in code3 just above the string (If I understood the short run correctly) and I also gave examples. For 4) It's the same byte 2 to be checked, but probably is my if term wrong. As I have a segfault, I don't have any output yet. I also had a closer look to my ASM code which is 68k and only the main code. I also found 2 codes on github about RLE including variable count length. But it's a large code, I haven't tried it yet. – rleencoder Mar 03 '21 at 18:46
  • Umbrella on git has a .js package. I installed it but didn't run in HTML. The ASM code in Easy68k produced errors. I managed to write a code in BASIC and it works. Not sure if I should post that. I can either convert it to C, or continue in BASIC. BASIC (C64) has limits for file size and maybe string length. But should work like printing out line by line. Or convert to bits or recompress to other format. Pics in small res and color depth can maybe even displayed. But it's mainly for conversion. In Congo (C64) it's possible to create an own image format but is limited. Maybe change other code – rleencoder Mar 04 '21 at 16:25

0 Answers0