A simple RLE implementation


I was explaining in the previous post about the RLE algorithm (Run-Length Encoding) I am using as an alternative to jpeg compression. The good part about this is that will work with OV7670/OV7725 and will not require a lot of CPU cycles.

The code looks something like this:

// Capture and stream a frame in B&W (in YUV mode)
void fFrameYB(void) {
  uint16_t i;
  uint16_t len = 0;

  // send StartFrame header
  uSendByte(CTS_UART, 0x47);
  uSendByte(CTS_UART, 0x00);
  // add a byte with mask details (size, mode, etc)
  printFrameDetails('1');

  // send StartFrame sequence to FIFO
  STARTFRAME();

  // Run this for each line in the frame
  i = 0;
  while (i++ < frameheight) {
    // retrieve the luminance data from a line 
    getLineBW2(lineWidth, &curLine);

    // compress line, return length
    len = compressLine(lineWidth, curLine, &comLine);
    // stream line
    uSend(CTS_UART, comLine, len, BLOCKING);
  }
}

// compress current line, return new one and its size 
uint16_t compressLine(uint16_t lineLen, Line inLine, Line *outLine){
  uint16_t i=0, indx=0, seq;
  uint8_t val = 0;

  // save space for line length info
  indx = 2;

  seq = 0;

  // read value
  val = inLine[0];

  for (i = 1; i< lineLen; i++){
     // if new value
     if (seq == 0){
       // store value in output array, increment sequence
       *outLine[indx+1] = (val & 0xff);
       seq++;
     }
     // if current value == previous value (increase the range)
     if ((val>>comFactor) == (curLine[i]>>comFactor)){
      // increment sequence
      seq++;
    } 
    // if next value is the same as previous value, set current = previous 
    else if ((val>>comFactor) == (inLine[i+1]>>comFactor)){
      // increment sequence
      seq++;
      *outLine[i] = val;
    } 
    // if is the last item in the line, update sequence
    else if (i == (lineLen - 1)){
      // update sequence
      *outLine[indx] = seq;
      seq=0;
      // add the size bytes
      indx +=2;
    } 
    // else update sequence, reset sequence and update counter, 
    else {
      *outLine[indx] = seq;
      seq=0;
      indx +=2;
    }

    // previous value = current value
    val = inLine[i];
  }

  // add line size details to be used by the decoder
  *outLine[0] = indx >> 8;
  *outLine[1] = indx & 0xff;

  // return line size
  return indx;
}

 

This is pretty much the high level version. The comFactor value will improve the compression but will affect the quality of the output image.

Advertisements

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s