A simple RLE implementation (cont)


 

I managed to get the RLE implementation working quite well. The original code is adding an index information for EVERY pixel, which on a noisy image can double the size of the image instead of compressing it. This is pretty much a functional version:

	
...
for (i = 1; i< lineLen; i++){
  if (seq == 0){
    seq++;
  }
  if (val>>CRANGE == curLine[i]>>CRANGE){
    seq++;
  } else if (val>>CRANGE == curLine[i+1]>>CRANGE){
    seq++;
    curLine[i] = val;
  } else {
    if (seq > 1){
      comLine[indx] = seq | (0x80);
      comLine[indx+1] = val;
      indx +=2;
    } else {
      comLine[indx] = val;
      indx +=1;
    }
    seq=0;
  }

  if ((i == (lineLen - 1)) & (seq > 0)){
    comLine[indx] = seq | (0x80);
    comLine[indx+1] = val;
    seq=0;
    indx +=2;
  }
  val = curLine[i];
 }

comLine[0] = indx >> 8;
comLine[1] = indx & 0xff;
...

And the receiver:

  ...
  index = 0;
  for (y = 0; y < h; y++) {
    x=0;
    sz = ((imgRLEBuffer[index] << 8) | (imgRLEBuffer[index+1]));
     if ((sz > 0) & (sz < w)){
      for (z = 2; z < sz; z++){
         if (imgRLEBuffer[index+z] > 0x7f){
          seq = (imgRLEBuffer[index+z] & 0x7f);
          z++;
          y1  = ((imgRLEBuffer[index+z] << 1) & 0xff);
          for (s = 0; s < seq; s++){	
            imgRaw.setRGB(x, y, (int)((y1 << 16) | (y1 << 8) | y1));
            x++;
          }
        } else {
          y1 = ((imgRLEBuffer[index+z] << 1) & 0xff);
          imgRaw.setRGB(x, y, (int)((y1 << 16) | (y1 << 8) | y1));							
          x++;
        }
      }
    }
    index += sz;
  }
  canvasZoom.setImage(imgRaw, 1);
  canvasZoom.repaint();
  imgRaw.flush();
  ...

The new version is a bit smarter: will only add the index if is more than one adjacent pixel duplicated. Worse case: the final image is the same (and same size) with the original one, not bad huh?

The trick is to send 7 bits per pixel, and use the 8th pixel to identify the index byte.

Doing further filtering the result will be quite decent considering that I am using a simple MCU to do everything and will work on any camera. For a “clean” image I can get a 160 x 120 frame down to 2 Kbytes+ from the original 19 Kbytes. For a “noisy” one will go up to 15 Kbytes. In the capture below, the 5956 is the image size in bytes.

Screen Shot 2015-02-11 at 01.08.01

Next is to write simple implementation of LZW to run on the compressed image. I am really curious how “low” I can go…

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