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);

In reply to Pack number to unsigned short by BrianP

Title:
Use:  <p> text here (a paragraph) </p>
and:  <code> code here </code>
to format your post, it's "PerlMonks-approved HTML":



  • Posts are HTML formatted. Put <p> </p> tags around your paragraphs. Put <code> </code> tags around your code and data!
  • Titles consisting of a single word are discouraged, and in most cases are disallowed outright.
  • Read Where should I post X? if you're not absolutely sure you're posting in the right place.
  • Please read these before you post! —
  • Posts may use any of the Perl Monks Approved HTML tags:
    a, abbr, b, big, blockquote, br, caption, center, col, colgroup, dd, del, details, div, dl, dt, em, font, h1, h2, h3, h4, h5, h6, hr, i, ins, li, ol, p, pre, readmore, small, span, spoiler, strike, strong, sub, summary, sup, table, tbody, td, tfoot, th, thead, tr, tt, u, ul, wbr
  • You may need to use entities for some characters, as follows. (Exception: Within code tags, you can put the characters literally.)
            For:     Use:
    & &amp;
    < &lt;
    > &gt;
    [ &#91;
    ] &#93;
  • Link using PerlMonks shortcuts! What shortcuts can I use for linking?
  • See Writeup Formatting Tips and other pages linked from there for more info.