BrianP has asked for the wisdom of the Perl Monks concerning the following question:
SPEC: Read 1376 byte binary file into uint16_t array overwrite item[16] with dec<7360> = 0X1cc0 overwrite item[22] with dec<4912> = 0X1330 Write file to disk sub prefix_hdr() { $hsize=1376; # Size of 16-bit grayscale tif header $hfn='d:/pic/misc/gray.3689x2462.hdr'; # Md5 ~29992 $brfn='6s-254550.7360x4912.blue.raw'; # photoshops $rsize=-s $brfn; $mutant='blue.7360x4912.tif'; open(H, "<$hfn"); binmode H; $bread=read(H, $hdr, $hsize); close H; printf("Read $bread B from $hfn\n"); @rgb=unpack("S*", $hdr); # RAW RGB UShort array printf("RGB[16]=%hu, [22]=%hu\n", $rgb[16], $rgb[22]); $rgb[16]=pack("S", 7360); # Overwrite 3689 with 7360 $rgb[22]=pack("S", 4912); # 2462 -> 4912 printf("FIXED? RGB[16]=0X%04hu, [22]=%hu\n", $rgb[16], $rgb[22]); } Read 1376 B from d:/pic/misc/gray.1376b.3689x2462.hdr RGB[16]=3689, [22]=2462 << PERFECT! Argument "└^\" isn't numeric in printf Argument "0^S" isn't numeric in printf FIXED? RGB[16]=0X0000, [22]=0 <<<<<<WRONG ----------------------------------------------------
File reads fine. Unpacks perfectly and the numbers print
Pack is not packing the unsigned short:
pack(TEMPLATE,LIST) S An unsigned short value. Template="S" List = one value, DECIMAL 7360
How does one do this in Perl
============================================================int xres=7360; uint16_t my_ui16[688]; ... my_ui16[16] = (uint16_t)xres; printf("Xres=%hu\n"); >> Xres=7360
>> open my($outfh),'>:raw', 'stuff';
Opening the file, put it in BINMODE and reading into a blob worked.
Unpacking the binary blob into an intelligible unsigned int array also works.
But, writing does NOT work in BINmode? Reading didn't need ':raw<~!%_'
>> print $outfh pack 'S<*', @rgb; We skipped the part about overwriting the default values.
How is it possible to take a proven correct UINT16 array
read in Perl and overwrite 2 values? Generating a real, uint16 from scratch was the
obstacle. The PACK and UNPACK do not appear to do inverse operations.
Applying PACK() as documented with an 'S' produced unprintable junk.
The original array values printed perfectly as %uh, unsigned shorts.
How does one translate this C into perl?: </p
my_uint_16_var = (uint16_t) 7360;
It has to be a drop in replacement for the default value, the >>3689<< stock value, not ["└^\"] << ??
:RAW???
Those layers will also be ignored if you specifying a colon with no na +me following it. In that case the default layer for the operating sys +tem (:raw on Unix, :crlf on Windows) is used.
Binmode does away with any cr/lf funkiness.
I am on Windoz, not *nix. Do I need :CRLF??? This is an OBSCURE Caveat!regardless of platform, use binmode() on binary data, like images, for + example.
|
|---|