mirror of https://github.com/ecmwf/eccodes.git
156 lines
4.1 KiB
Perl
Executable File
156 lines
4.1 KiB
Perl
Executable File
#!/usr/bin/perl
|
|
use strict;
|
|
|
|
# ----------------------------------------------------------------------
|
|
# Convert GRIB edition 2 multi-field (several fields per message) files
|
|
# to single-field (one field per message)
|
|
# ----------------------------------------------------------------------
|
|
|
|
my $debug = 0;
|
|
my $total = 0;
|
|
my $previous_bitmap;
|
|
|
|
if ($ARGV[0] eq "-d")
|
|
{
|
|
$debug = 1;
|
|
shift @ARGV;
|
|
}
|
|
|
|
my $out = pop @ARGV;
|
|
|
|
unless(@ARGV >= 1 && defined $out)
|
|
{
|
|
print STDERR "Usage: $0 [-d] in1 [in2 ...] out\n";
|
|
exit(1);
|
|
}
|
|
|
|
open(OUT,">$out") || die "$out: $!";
|
|
|
|
foreach my $in ( @ARGV )
|
|
{
|
|
my $gribs = 0;
|
|
my $cnt = 0;
|
|
open(IN,"<$in") || die "$in: $!";
|
|
|
|
while(1)
|
|
{
|
|
my @sections = ();
|
|
# Find header
|
|
|
|
print "Looking for GRIB\n" if ($debug);
|
|
my $grib;
|
|
while((read(IN,$grib,4) == 4) && ($grib ne "GRIB"))
|
|
{
|
|
seek(IN,-3,1);
|
|
}
|
|
|
|
unless($grib eq "GRIB")
|
|
{
|
|
print "No more GRIBs\n" if ($debug);
|
|
last;
|
|
}
|
|
|
|
my $here = tell(IN);
|
|
my $start = $here - 4;
|
|
$gribs++;
|
|
|
|
print "$grib found at offset $start\n" if ($debug);
|
|
|
|
my ($reserved,$discipline,$edition);
|
|
|
|
die "$in: $!" unless(read(IN,$reserved,2) == 2);
|
|
die "$in: $!" unless(read(IN,$discipline,1) == 1);
|
|
die "$in: $!" unless(read(IN,$edition,1) == 1);
|
|
|
|
my $grib_edition = ord($edition);
|
|
die "Un-supported edition $grib_edition" unless($grib_edition == 2);
|
|
|
|
my ($len1,$len2);
|
|
die "$in: $!" unless(read(IN,$len1,4) == 4);
|
|
die "$in: $!" unless(read(IN,$len2,4) == 4);
|
|
|
|
my $msglen1 = unpack("N",$len1); die "GRIB too large" if ($msglen1);
|
|
my $msglen2 = unpack("N",$len2);
|
|
my $msglen = $msglen2;
|
|
print "Message length $msglen\n" if ($debug);
|
|
|
|
while(1)
|
|
{
|
|
$here = tell(IN);
|
|
my ($seclen,$section);
|
|
|
|
die "$in: $!" unless(read(IN,$seclen,4) == 4);
|
|
|
|
if ($seclen eq "7777")
|
|
{
|
|
print "7777 found at offset $here\n" if ($debug);
|
|
die "Invalid message lenth $msglen"
|
|
unless($here+4-$start == $msglen);
|
|
last;
|
|
}
|
|
|
|
$seclen = unpack("N",$seclen);
|
|
die "$in: $!" unless(read(IN,$section,1) == 1);
|
|
$section = ord($section);
|
|
die "Invalid section number $section" unless ($section >= 1 && $section <=7);
|
|
print "Section $section found at offset $here length $seclen\n" if ($debug);
|
|
seek(IN,-5,1) or die "$in: $!";
|
|
|
|
my $data;
|
|
die "$in: $!" unless(read(IN,$data,$seclen) == $seclen);
|
|
|
|
if ($section == 6)
|
|
{
|
|
# Special case for inherited bitmaps
|
|
if (unpack('C',substr($data,5,1)) == 254)
|
|
{
|
|
die "No previous bitmap" unless(defined $previous_bitmap);
|
|
$data = $previous_bitmap;
|
|
}
|
|
else
|
|
{
|
|
$previous_bitmap = $data;
|
|
}
|
|
}
|
|
|
|
splice(@sections,$section+1);
|
|
$sections[$section] = $data;
|
|
|
|
if ($section == 7)
|
|
{
|
|
print OUT "GRIB";
|
|
print OUT $reserved;
|
|
print OUT $discipline;
|
|
print OUT $edition;
|
|
print OUT $len1;
|
|
|
|
$len2 = 16 + 4;
|
|
for(my $i = 1; $i <= 7 ; $i++)
|
|
{
|
|
$len2 += length($sections[$i])
|
|
if (defined $sections[$i]);
|
|
}
|
|
|
|
$cnt++;
|
|
print "GRIB $cnt is $len2\n" if ($debug);
|
|
$len2 = pack("N",$len2);
|
|
print OUT $len2;
|
|
|
|
for(my $i = 1; $i <= 7 ; $i++)
|
|
{
|
|
next unless(defined $sections[$i]);
|
|
print OUT $sections[$i];
|
|
}
|
|
print OUT "7777";
|
|
}
|
|
}
|
|
}
|
|
|
|
print "$in: $cnt field(s) found in $gribs GRIB(s)\n";
|
|
$total += $cnt;
|
|
}
|
|
|
|
close(OUT) or die "$out: $!";
|
|
|
|
print "$out: $total field(s) written\n";
|