A run-length compression method used in MacPaint and TIFF image files. To decode a PackBits bitstream:

  1. Read a byte `runlen' from in.
  2. If runlen is in 0 to 127, copy runlen + 1 bytes verbatim from in to out.
  3. Else if runlen is in -127 to -1, read a byte runtext from in and write runtext to out runlen times.
  4. Otherwise, b is -128; this is considered a no-op.
  5. Rinse and repeat until the whole bitstream is decoded.

C code to pack and unpack


/* fpack() *****************************
 * Write PackBits encoded data to a file.
 * buf, fp: as fwrite()
 * size: size of source (unpacked) buffer
 * returns: number of packed bytes written
 */
size_t fpack(const unsigned char *buf, size_t size, FILE *fp)
{
  char b[127];
  unsigned int bdex = 0, i = 0, j = 0, t = 0;

  do {
    /* zero the line index */
    i = 0;

    /* check for a run of at least three bytes */
    while((buf[t + i] == buf[t + i + 1]) &&
          (buf[t + i] == buf[t + i + 2]) &&
          (t + i + 3 < size) && (i < 126))
      i++;

    /* if there's a run... */
    if((i > 0 && bdex > 0) || (bdex >= 127))
    {
      /* if there's a literal string... */
      fputc(bdex - 1, fp);
      j++;
      /* write it to the file. */
      j += fwrite(b, 1, bdex, fp);
      bdex = 0;
    }
    if(i > 0)
    {
      /* and then write the run. */
      i += 2;
      fputc(257 - i, fp);
      fputc(buf[t], fp);
      t += i;
      j += 2;
    }
    else
    {
      b[bdex++] = buf[t++];
    }
  } while(t < size);
  if(bdex)
  {
    /* if there's a literal string... */
    fputc(bdex - 1, fp);
    j++;
    /* write it to the file. */
    j += fwrite(b, 1, bdex, fp);
    bdex = 0;
  }

  return j;
}


/* funpack() ***************************
 * Read PackBits() encoded data from a file.
 * buf, fp: as fread()
 * size: size of destination (unpacked) buffer
 * returns: number of bytes unpacked
 */
int funpack(unsigned char *buffer, size_t size, FILE *file)
{
  unsigned char mode;
  size_t nread = 0;
  int i;

  while(nread < size)
  {
    mode = fgetc(file);
    if(feof(file))
      return nread;
    if(mode > 128)
    {
      i = 257 - mode;
      mode = fgetc(file);
      if(feof(file))
        return nread;
      while(i--)
        buffer[nread++] = mode;
    }
    else if(mode < 128)
      nread += fread(buffer + nread, 1, mode + 1, file);
  }
  return nread;
}

Log in or register to write something here or to contact authors.