Binary files, substrings and (un)packing.

Discussion in 'Perl' started by Leandro Pardini, Oct 25, 2003.

  1. Hello there,

    I'm trying to process a binary file and I really don't know how. The
    story: gPhoto2 downloads the images from my camera just fine, but
    small areas of 10x3 pixels are screwed up. I found exactly where the
    problem happens and wrote a simple interpolation filter that works
    like a charm... under DOS, using the old QuickBasic. I've used Perl
    for a while, but never to handle binary data, so I'm at a loss; and I
    really want to get this working under Linux, so I can stop switching
    OSs every time I download photos from my camera.

    Basically, I need to extract two substrings from a binary string,
    average them and then reinsert them in the string. I gather I must use
    unpack() with the substrings to return two integer arrays with the
    byte values, create a third array with the averages and then use
    pack() to convert them to binary again and then reinsert them into the
    bigger string. Problem is, I have no clue how to do it.

    I'll put an example and see if someone can help me do this: let's say
    the input buffer is '000121888565000' (those are the ascii values
    represented by numbers, not the actual numbers in ascii form). I want
    to use unpack to get the substring '121' (location 4, 3 bytes long) in
    an array {1,2,1} and the substring '565' (location 10, 3 bytes long)
    in an array {5,6,5}, then average the two arrays to get a {3,4,3}
    array, then use pack to reinsert them in the buffer so it contains
    '000121343565000'. How on earth can I do that?

    Thanks in advance,
    Leandro Pardini, Oct 25, 2003
    1. Advertisements

  2. Leandro Pardini

    Jim Gibson Guest

    I am not sure from your description what exactly is the input of your
    data. You show 15 digits from 0 - 8, so I will assume that they are
    4-bit integers packed into a 60-bit binary string. Here is a way to do
    what you want (I first use pack to generate the 60-bit string, then use
    unpack to get the 15 4-bit nybbles, do the averaging and replacing,
    then use pack again to generate the 60-bit result:


    use strict;
    use warnings;

    # create binary value for testing
    my $input = pack("h" x 15, split(//,'000121888565000'));

    # unpack bytes in input
    my @bytes = unpack("h" x 15, $input );
    print "input: ", @bytes, "\n";

    # average and replace
    for my $i ( 0..2 ) {
    $bytes[6+$i] = int(($bytes[3+$i] + $bytes[9+$i])/2);

    # pack into binary string
    my $output = pack("h" x 15, @bytes);

    # unpack and print result
    my @result = unpack("h" x 15, $output);
    print "result: ", @result, "\n";

    FYI: this newsgroup is defunct. Try comp.lang.perl.misc in the future
    for better responses.
    Jim Gibson, Oct 27, 2003
    1. Advertisements

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments (here). After that, you can post your question and our members will help you out.