BrianP has asked for the wisdom of the Perl Monks concerning the following question:
I have been trying for an hour to pack a simple number into a type 'S' I have a small number < 10 and need to smash it into a unit16. I think the Perl "pack()" should take a number < 64k and PACK it into 16 contiguous bits resembling a uint16_t in C. All 5000 attempts to figure out this simple function have failed. What am I doing wrong? In C: unit16_t count; // Tiny, 1 digit integer uint48_t rgb; // Full 48 binary bits from 3, uint16s, r, g and b uint64_t rgbc; // The final data, just like RGBA memcpy(rgbc+0, rgb, 3*sizeof(uint16_t)); memcpy(rgbc+3, count, 1*sizeof(uint16_t)); // Voila! 4 ushort numbers in a row in RGBC "PACKED" into 64 adjoining + bits Conceptually this is what I want to do: Take 6 bytes of RGB and 2 bytes of count into a PACK them into a 'Q' 6 +4 $rgbc = pack('Q', $rgb, $count); "Pack a quad from 2 variables and store in RGBC" I have a test number, 0x4567 = decimal 17757 I have a 48 bit RGB dragged from a binary .RAW file in a hash key The tiny count is the data value for an RGB key. I want to write an RGBC file with the count appended to the end of the + RGB value so I will have 4, unit16_t values to make a uint64_t RGBC How does one "Pack" a small number into a 16 bit unsigned integer?? ------------------------------ Attempts: Perl: http://perldoc.perl.org/functions/pack.html pack TEMPLATE,LIST The TEMPLATE is a sequence of characters that give the order and type +of values, as follows: S An unsigned short value. $count=17767; # C=0x4567=Dec17757 $c16 = pack("S", $count); # Pack COUNT to @c = pack("S*", $count); # == 0000 printf("Count= dec %d, hex 0x%04hx, c16=0x%04hx, \@c[%d]=%s\n", $count, $count, $c16, scalar @c, join(", ", @c)); printf("c[0]=%d=0x%08x, c[1]=%d=0x%08x\n", $c[0], $c[0],$c[1],$c[1 +]); -> Count= dec 17767, hex 0x4567, c16=0x0000, @c[1]=gE c[0]=0=0x00000000, c[1]=0=0x00000000 and many error/warning messages Unpack? Count= dec 17767, hex 0x4567, c16=0x0000, @c[2]=14129, 13879 c[0]=14129=0x00003731, c[1]=13879=0x00003637 17767 dec = 0b100010101100111 14129 dec = 0b11011100110001 <<< totally random? 13879 dec = 0b11011000110111 The number packs into a single 'S' with a value of 0x0000 But, it also packs into an array of unsigned shorts with weird values c[0]=14129=0x3731, c[1]=13879=0x3637 None of these integers or hex values bears any resemblance to my numbe +r ------------------------------------------ Obviously the wrong approach: Try putting the number in as a text literal, "17757": @c = unpack("S*", "17757"); # == 0000 printf("\@c[%d]=%s\n", scalar @c, join(", ", @c)); printf("c[0]=%d=0x%08x, c[1]=%d=0x%08x\n", $c[0], $c[0],$c[1],$c[1 +]); @c[2]=14129, 13623 c[0]=14129=0x00003731, c[1]=13623=0x00003537 Same -------------------------------------- Try using hex, 0x4567 @c = pack("S*", 0x4567); # == 0000 printf("\@c[%d]=%s\n", scalar @c, join(", ", @c)); printf("c[0]=%d=0x%08x, c[1]=%d=0x%08x\n", $c[0], $c[0],$c[1],$c[1 +]); return(); @c[1]=gE One array value "gE" c[0]=0=0x00000000 Prints as 0 -------------------------------------- Try doing some math on it so it knows its a number @c = pack("S*", $c16=17757*1); # == 0000 printf("\@c[%d]=%s\n", scalar @c, join(", ", @c)); printf("c[0]=%d=0x%08x, c[1]=%d=0x%08x\n", $c[0], $c[0], $c[1], $c +[1]); return(); @c[1]=]E Weird text and zero for decimal and hex c[0]=0=0x00000000 ------------------------------------------ Confusing pack with unpack? I just used unpack to read a binary RAW fi +le. It worked exactly as expected. @c = unpack("S*", "17757"); # == 0000 printf("\@c[%d]=%s\n", scalar @c, join(", ", @c)); printf("c[0]=%d=0x%08x, c[1]=%d=0x%08x\n", $c[0], $c[0], $c[1], $c +[1]); @c[2]=14129, 13623 c[0]=14129=0x00003731, c[1]=13623=0x00003537 ---------------------------------------------- @c = pack("S*", "17757"); # == 0000 printf("\@c[%d]=%s\n", scalar @c, join(", ", @c)); printf("c[0]=%d=0x%08x, c[1]=%d=0x%08x\n", $c[0], $c[0], $c[1], $c +[1]); @c[1]=]E Argument "]E" isn't numeric in printf at C:\bin\bb.pl line 347. Use of uninitialized value in printf at C:\bin\bb.pl line 347. Use of uninitialized value in printf at C:\bin\bb.pl line 347. c[0]=0=0x00000000, c[1]=0=0x00000000 ==================================================== ==================================================== open(IN, "<$file") or die("CCS: ERROR! <Opening '$file': $!\n"); for($ii = 0; $ii < $sr_num; $ii++) { $sr_len = sysread(IN, $buf, $bsize); # SysRead Length $tr_len += $sr_len; # Total Read Length $tr_num++; # Total Read Number while($buf) { $rgb=substr($buf, 0, 6, ''); # Nibble 6 bytes $rgb2c{$rgb}++; } } # End For II loop foreach $rgb (keys %rgb2c) { $count = $rgb2c{$rgb}; # Attempt to take known 6 byte RGB, some psychotic # perl number and smash them together into a QUAD # a uint64 RGBC value just like a standard RGBA $rgbc = pack('Q', $rgb, $count);
|
|---|
| Replies are listed 'Best First'. | |
|---|---|
|
Re: Pack number to unsigned short (printf)
by tye (Sage) on Aug 15, 2015 at 05:39 UTC | |
| |
|
Re: Pack number to unsigned short
by AnomalousMonk (Archbishop) on Aug 15, 2015 at 14:34 UTC | |
|
Re: Pack number to unsigned short
by Tux (Canon) on Aug 15, 2015 at 15:42 UTC | |
by AnomalousMonk (Archbishop) on Aug 15, 2015 at 19:44 UTC | |
|