Search code examples
perlpdfbit-manipulationlzwbitstream

Use Perl to Modify a Bitstream


How can I re-pack bits into a bitstream after modifying them in Perl?

I'm currently using the following to unpack:

my $bits = 5;
my $code = '';

foreach my $i (reverse 0..$bits-1) {
    $code <<= 1;
    $code  |= vec($data,$i,1);
}

For example, the output might be 16.

EDIT:

This question relates to the data block of a GIF image.

What I'm trying to do is to pad the LZW codes to match the length required by PDF's LZWDecode method.

LZWDecode expects 8-bit images in which the <Clear> code is 256 and the <End> code is 257 (PDF Reference, page 44.)

For 5-bit images, codes 0-31 map to colors in the image's global color table, <Clear> is 32 and <End> is 33.

So I need to re-pack the bitstream so that codes 0-31 remain the same, but 32+ are offset by 256-32.

I'm using ActiveState Perl for Windows.


Solution

  • # Unpack from 8 bit fields.
    my @vals = unpack('C*', $bytes);
    
    ... transform @vals into 5 bit values here ...
    
    # Pack to 5 bit fields.
    my $bits = join '', map substr(pack('B*', $val), -5), @vals;
    $bits .= '0' x (-length($bits) % 8);  # Pad with zeros to byte boundary
    $bytes = pack('B*', $bits);