in reply to Re: Write 2 uint16_t numbers to file in Perl
in thread Write 2 uint16_t numbers to file in Perl

What does this mean?
Also don't use printf as a replacement for print

With the rise and rise of 'Social' network sites: 'Computers are making people easier to use everyday'
Examine what is said, not who speaks -- Silence betokens consent -- Love the truth but pardon error.
"Science is about questioning the status quo. Questioning authority". I knew I was on the right track :)
In the absence of evidence, opinion is indistinguishable from prejudice.
  • Comment on Re^2: Write 2 uint16_t numbers to file in Perl

Replies are listed 'Best First'.
Re^3: Write 2 uint16_t numbers to file in Perl
by Athanasius (Archbishop) on Jan 05, 2016 at 10:23 UTC

    Possibly an allusion to the closing sentence in the documentation of the printf function?

    Don't fall into the trap of using a printf when a simple print would do. The print is more efficient and less error prone.

    Athanasius <°(((><contra mundum Iustus alius egestas vitae, eros Piratica,

      UPDATE:
      Root cause of problem found:
          Perl misprints a ushort with %hu format as %c%c
      
      Does Perl have a PrintC function which prints C datatypes
      EXACTLY as C would print the same BINARY DIGITS without
      dismembering multi-byte integers and misprinting as
      single-byte character data?  %hu means %hu, !%c%c!
      	
      This behavior contradicts sprintf documentation:
      Size:  h interpret integer as C type "short"
      It contradicts C behavior; same data, same printf, wrong result
      It fails the intelligent assistant test:
          What is the value of $Xres?  "+^\" is !correct
      
      Working with uint16 image data without a printf which
      understands the difference between characters and ushorts
      is a problem. Does one keep 2, parallel sets of data,
      1 real set for Photoshop and a second, "doctored" set
      to print correctly in the log files? 
      

      --------------------------------------------
      Test case:
      1) pack number into 'S', unsigned short, store in $pxres
      2) write $pxres to disk in binary mode
      3) dump this file in C to verify contents
      4) Include misprint of uint16 as 2 uint8s in C output
      5) print $pxres variable in Perl with explicit %d, %hu, %s...
      
      Results:
      Perl does pack and dump uint16 containing number 7360 correctly.
      Contents verified via C program
      Perl prints the known good uint16 as 2 uint8 chars
      Perl printf of 7360 with explicit "%hu" format is
      identical to C printf of uint16 buffer with %c%c
      
      I asked a "2 foot section of rope". 
      Assistant delivered 2, "1 foot sections of rope".
      
      --------------------------------------------------------
      RTFM background: http://perldoc.perl.org/functions/sprintf.html Size: h interpret integer as C type "short" or "unsigned short" %u an unsigned integer, in decimal %hu -> unsigned C type "short" This is Exactly the contents of the Perl variable as verified by C

      --------------------------------------------------------
      Test program ouput: Running C:\bin\bb.pl Wed Jan 6 13:26:28 2016 Perl: Pack number 7360 into uint16 and dump to file pack.test.dat hex_dec_bin_dump.exe File pack.test.dat is 2 bytes long Read 2 Bytes from pack.test.dat Int 7360, uint16 7360, hex 0X1CC0, float 7360.0000, binary 11100110000 +00 BAD_PRINT, Show uint16 as chars: 7360 != +? Argument "+^\" isn't numeric in printf at C:\bin\bb.pl line 179, <FOO> + line 168. Number 7360 Packed into 'S': h 0, d 0, hu 0, b 0, s +?

      --------------------------------------------------------
      Perl Code: sub perl_pack_print() { $ofn='pack.test.dat'; # Output file Name $xres=7360; # X Resolution $pxres=pack("S", $xres); # Xres Packed into USHORT open(O, ">$ofn"); binmode O; print(O "$pxres"); close O; print("Perl: Pack number $xres into uint16 and dump to file $ofn\n +"); # Verify that Perl wrote the correct data to disk system("hex_dec_bin_dump.exe $ofn"); # See if Perl can print the '%hu' it just wrote to disk printf("Number $xres Packed into 'S': h %x, d %d, hu %hu, b %b, s +%s\n", $pxres, $pxres, $pxres, $pxres, $pxres); }
      ------------------------------------------------
      C dump verification code: // Dump given file as hex, dec, float, string... // // gcc -Ofast -ffast-math -m64 -march=sandybridge -funroll-loops -fop +enmp -flto -lm c:/bin/hex_dec_bin_dump.c -o c:/bin/hex_dec_bin_dump. +exe #include "bpbfct.c" void main(int argc, char *argv[]) { FILE *ifp; // FILE pointers to Output and Input file struct stat statbuf; // STAT function buffer long bread=-1; // Bytes Read int fsize=0; // File size from STAT() uint16_t usbuf[99]; // Unsigned Short BUFfer uint8_t *char_8_ptr; // Bytes to bisect/mutilate short char bitb[254]={ 0 }; // Bit Buffer. Should hold ANY integer char ifn[255]={ 0 }; strcpy(ifn, argv[1]); // Input File Name arg stat(ifn, &statbuf); // Stat the file to get its size fsize=statbuf.st_size; // File size in bytes for .raw (RGB?) file printf("\n%s\nFile %s is %d bytes long\n", argv[0], ifn, fsize); ifp=fopen(ifn, "rb"); // Open input file in bi +nary bread=fread((void *)usbuf, 1, 999, ifp); // Read argued file printf("Read %d Bytes from %s\n", bread, ifn); printf("Int %d, uint16 %hu, hex 0X%04X, float %.4f, binary %s\n", usbuf[0], usbuf[0], usbuf[0], (float)usbuf[0], itoa(usbuf[0], (char *)(&bitb), 2)); char_8_ptr=(uint8_t *) usbuf; // Cast ushort buf to uShortER printf("BAD_PRINT, Show uint16 as chars: %hu != %c%c\n\n", usbuf[0], char_8_ptr[0], char_8_ptr[1]); exit(0); } // End Main().
      =============================================================== =============================================================== Athanasius,

      I tried the print instead of printf (and changed my variable name from rgb->hdr)

      $hdr[16]=pack("S", 7360); $hdr[22]=pack("S", 4912); printf("FIXED? HDR[16]=$hdr[16], HDR[22]=$hdr[22]\n");
      Read 1376 B from d:/pic/misc/gray.1376b.3689x2462.hdr RGB[16]=3689, [22]=2462 FIXED? HDR[16]=&#9492;&#8735;, HDR[22]=0&#8252;

      This is NOT a print/f problem:

      @hdr=unpack("S*", $hdr); # RAW RGB Unsigned Short array printf("PrInTf:: RGB[16]=%hu, [22]=%d\n", $hdr[16], $hdr[22]); print ("pRInT :: RGB[16]=$hdr[16], [22]=$hdr[22]\n"); => PrInTf:: RGB[16]=3689, [22]=2462 pRInT :: RGB[16]=3689, [22]=2462

      It read, unpacked and printed raw, binary UINT16 data correctly

      All I have been trying to do is:
      1) document current value of uint16_t at some_uint16_array16
          Try to imagine square brackets around the "<16>" above.
      2) Convert ordinary integer <<7360>> to uint16_t
      3) Overwrite old, documented value (the 3689) with new 7360 value
      4) Confirm in log file that new value prints EXACTLY like old value
      5) Write binary blob back to disk with only 2 uint16s changed
      
      How does one PACK the "S"hort value "'7360'" into an array item created with:
      open(H, "<$hfn"); binmode H; printf("Read $bread B from $hfn\n"); @hdr=unpack("S*", $hdr); # RAW RGB Unsigned Short array

      A) It was asked to create an Unsigned SHORTfrom reasonable data:
      	$hdr[\16\]=pack("S", 7360);
      B) It was asked to print it as an Unsigned SHORT as "%hu"
      C) It was asked to print the Unsigned SHORT as it saw fit
      D) How can it print this as:
      

      printf("FIXED? HDR[16]=$hdr[16], HDR[22]=$hdr[22]\n"); => FIXED? HDR[16]=&#9492;&#8735;, HDR[22]=0&#8252;
      The EXTRACTION part of the Pathological Extraction Report Lang is working!
      The DATA CREATION seems to have fallen less on the PRACTICAL side :)
        How does one PACK the "S"hort value "'7360'" into an array item created with: ...

        Don't. Please see my reply below (update: and also see this more-complete explanation). Assign 7360 to the array element in question and then re-pack the whole array as an S-formatted string.


        Give a man a fish:  <%-{-{-{-<

Re^3: Write 2 uint16_t numbers to file in Perl
by BrianP (Acolyte) on Jan 05, 2016 at 10:12 UTC

    This solution works PERFECTLY as documented

    // Grab a standard TIF hdr // Update the ushort XY res values, X@[16] and Y@[22] // Slam it on top of a UINT16 RAW and call it a TIF!!! // What could POSSIBLY be easier??? // // gcc -Ofast -ffast-math -m64 -march=sandybridge -msse4.2 -mavx -fun +roll-loops -fopenmp -flto -lm c:/bin/merge.hdr.raw.c -o c:/bin/merge +.hdr.raw.exe #include "bpbfct.c" void main(int argc, char *argv[]) { FILE *hi, *ri, *to; // File pointers for 2 ins and 1 outs struct stat statbuf; // STAT function buffer char hdrfn[255] = { 0 }; char rawfn[255] = { 0 }; char tiffn[] = "hdr.raw.merge.tif"; int hsize=1376, rsize, bread, brote, tsize; // Header and RAW sizes uint16_t *hdra; // HDR data array uint16_t *rawa; // RAW data array strcpy(hdrfn, argv[1]); strcpy(rawfn, argv[2]); hdra=(uint16_t *)malloc(hsize); hi=fopen(hdrfn, "rb"); bread=fread((void *)hdra, 1, hsize, hi); printf("Read %d Bytes from %s\n", bread, hdrfn); fclose(hi); stat(rawfn, &statbuf); // Stat the file to get its size rsize=statbuf.st_size; // File size in bytes for .raw (RGB?) file rawa=(uint16_t *)malloc(rsize); ri=fopen(rawfn, "rb"); bread=fread((void *)rawa, 1, rsize, ri); printf("Read %.6lf MBytes from %s\n", bread*1E-6, rawfn); fclose(ri); // HERE's the HARD PART!!! printf("Xres @ Hdr[16]=%hu, Yres @ [22] = %hu\n", hdra[16], hdra[2 +2]); hdra[16]=(uint16_t) 7360; <<<< Is this POSSIBLE in PERL?????? hdra[22]=(uint16_t) 4912; // Did it float?? printf("FIXED?? Xres @ Raw[16]=%hu, Yres [22] = %hu\n", hdra[16], hdra[22]); to=fopen(tiffn, "wb"); // TIF output file brote = fwrite((void *)(hdra), 1, hsize, to); brote += fwrite((void *)(rawa), 1, rsize, to); fflush(to); fflush(to); fclose(to); stat(tiffn, &statbuf); // Stat the file to get its size tsize=statbuf.st_size; // File size in bytes for .raw (RGB?) file printf("Wrote %.6lf MBytes to TIF %s, Size: T-R-H=%d\n", tsize*1E-6, tiffn, brote - rsize - hsize); free(hdra); free(rawa); } // End Main().
    I:\exp\6s-254623> merge.hdr.raw.exe gray.1376b.3689x2462.hdr 6s-2015 +.1031-254550.7360x4912.blue.cv.t.raw Read 1376 Bytes from gray.1376b.3689x2462.hdr Read 72.304640 MBytes from 6s-2015.1031-254550.7360x4912.blue.cv.t.raw Xres @ Hdr[16]=3689, Yres @ [22] = 2462 FIXED?? Xres @ Raw[16]=7360, Yres [22] = 4912 Wrote 72.306016 MBytes to TIF hdr.raw.merge.tif, Size: T-R-H=0 I:\exp\6s-254623>identify hdr.raw.merge.tif hdr.raw.merge.tif TIFF 7360x4912 7360x4912+0+0 16-bit Grayscale Gray 7 +2.31MB ... <p> Note the original and overwritten values. </p> <code> Xres @ Hdr[16]=3689, Yres @ [22] = 2462 FIXED?? Xres @ Raw[16]=7360, Yres [22] = 4912 <<< WORKS!!!

    It's Alive!

    </code>
Re^3: Write 2 uint16_t numbers to file in Perl
by Anonymous Monk on Jan 05, 2016 at 10:25 UTC

    What does this mean?

    This part use print  printf("Read $bread B from $hfn\n");

      Right. I missed that.

      Then again, it wouldn't be that hard for printf to realise that it only had a single parameter and bypass inspecting the template and just print it. (Maybe that is already done.)


      With the rise and rise of 'Social' network sites: 'Computers are making people easier to use everyday'
      Examine what is said, not who speaks -- Silence betokens consent -- Love the truth but pardon error.
      "Science is about questioning the status quo. Questioning authority". I knew I was on the right track :)
      In the absence of evidence, opinion is indistinguishable from prejudice.