[Gdal-dev] ADF -> AAIGrid, "IReadBlock failed"

Patrick Min pmin00 at gmail.com
Wed May 30 09:39:53 EDT 2007


Hello,

I've come up with a hacky solution to be able to
access all the data when the dataset is multitiled.

In my case, the data files are:
w001001.adf
w001000.adf
z001001.adf
z001002.adf

Below this e-mail I've included a Perl script that reads hdr.adf,
dblbnd.adf, sta.adf, and w001001x.adf, and produces some more
info than gdalinfo. Especially useful, it gives the number of tiles
in the index file, which you can use to compute where the next file
starts.

In my case w001001x.adf has info for 506520 tiles. Divide this by
HTilesPerRow (201) to get 2520, multiply by HTileYSize (4) to get
10800 rows. My HPixelSizeY is 5, so now I know the w001001.adf
has data for 10800 x 5 = 50400 pixel rows.

>From the boundary file I know that the upper left Y is at 475000,
so now I know the next file (apparently w001000.adf, strange ordering)
starts at 475000 - 50400 = 424600.

The 2nd and 3rd file have the same number of tiles as the 1st, so this
means the 3rd file starts at Y = 424600 - 50400 = 374200, and the 4th
at 374200 - 50400 = 323800. The 4th file has 170448 tiles (number
obtained by running the Perl script below as:
read_adf_info.pl z001002x.adf). All the math checks out with the
boundaries of the dataset.

To get data out of the 4th file, for example, I did the following:
- create a subdirectory "data" in the dataset directory
- move the w001* files in there
- create symbolic links:
  ln -s ./data/z001002.adf w001001.adf
  ln -s ./data/z001002x.adf w001001x.adf
  (this to make sure gdal_translate uses the 4th file)
- compute the -srcwin coordinates, taking into account the origin of
  the 4th file, which is down 3 x 50400 = 151200 from the dataset origin
- run gdal_translate

This example, more specifically: my dataset upper left is at
(13565, 475000). I wanted to extract a grid at upper left
(194990, 317925). The upper left of the 4th file is at
(13565, 323800), which, as far as gdal_translate is now concerned,
is the upper left of the whole dataset.

So the delta Y  = 323800 - 317925 = 5875, divide by cell size 5 =
5875 / 5 = row 1175.
The delta X = 194990 - 13565 = 180925 / 5 = column 36285.

The grid to extract is 600 by 600 cells, so the command becomes:

gdal_translate -oi AAIGrid -srcwin 36285 1175 600 600 hdr.adf mygrid.agr

This is a grid cell for which I had a known other height field, and
they corresponded :-)

I hope this helps people with larger datasets,
let me know if anything is not clear,

Patrick

--------------
Perl script: read_adf_info.pl
--------------
#!/usr/bin/perl

print "\nread_adf_info.pl\nwritten by Patrick Min, May 2007, v1\n\n";

$adfx_filespec = $ARGV[0];

if ($adfx_filespec eq "") {
    print "Usage: read_adf_info.pl [<adfx filespec>]\n";
    print "  if no filename is given, a default [w001001x.adf] is assumed\n\n";
    $adfx_filespec = "w001001x.adf";
}

&read_bounds_info;

&read_stats_info;

&read_header;

&read_index_info;

print "done\n\n";








sub convert_msb_int32
{
    my(@values) = @_;

    my $int_value = $values[0] * 256 * 256 * 256 + $values[1] * 256 *
256 + $values[2] * 256 + $values[3];

    return $int_value;

}  # convert_msb_int32




sub read_msb_int32
{
    my($handle) = @_;
    my $buf;

    read($handle, $buf, 4);
    my @b = unpack("CCCC", $buf);
    my $int32 = &convert_msb_int32(@b);

    return $int32;

}  # read_msb_int32



sub read_index_info
{
    #
    # construct index filename
    #
    open($index_handle, $adfx_filespec) || die "Could not open
[$adfx_filespec]\n";
    binmode $index_handle;

    #
    # read magic number
    #
    print "[$adfx_filespec] magic number [";
    read($index_handle, $magic, 8);
    @b = unpack("CCCCCCCC", $magic);
    for($i=0; $i < 8; $i++) {
	$hex = sprintf("%x", $b[$i]);
	print $hex;
	
    }
    print "]\n";

    read($index_handle, $dummy, 16);

    $filesize = 2 * &read_msb_int32($index_handle);
    print "Filesize [$filesize], ";
    $in_mb = $filesize / 1048576;
    print "  or [$in_mb MB]\n";

    read($index_handle, $dummy, 72);

    $nr_tiles = 0;
    open(LOG, "> tiles_index.log");
    while(!(eof($index_handle))) {
	
#    for($i=0; $i < $NR_TILES; $i++) {
	$tile_offset[$nr_tiles] = 2 * &read_msb_int32($index_handle);
	print LOG "Tile $nr_tiles offset [$tile_offset[$nr_tiles]]\n";

	$tile_sizes[$nr_tiles] = 2 * &read_msb_int32($index_handle);
	print LOG "Tile size [$tile_sizes[$nr_tiles]]\n";

	$nr_tiles++;
    }  # for
    close LOG;
    print "read index info for $nr_tiles tiles\n";

    close $index_handle;

}  # read_index_info




sub read_bounds_info
{
    $bounds_filespec = "dblbnd.adf";
    print "read_bounds_info($bounds_filespec)\n";

    open(BOUNDS, $bounds_filespec) || die "Could not open [$bounds_filespec]\n";
    binmode BOUNDS;

    @vars = ("LLX", "LLY", "URX", "URY");

    for($i=0; $i < 4; $i++) {

	read(BOUNDS, $buf, 8);
	@b = unpack("CCCCCCCC", $buf);

	for($j=0; $j < 8; $j++) {
	    $b2[$j] = $b[7 - $j];
	}

	$buf2 = pack("CCCCCCCC", @b2);

	$value = unpack("d", $buf2);

	print "  $vars[$i]: [$value]\n";

    }  # for

    close BOUNDS;
    print "\n";

}  # read_bounds_info



sub read_msb_double64
{
    my($handle) = @_;
    my $buf;
    my $j;
    my @b2;
    my $buf2;

    read($handle, $buf, 8);
    my @b = unpack("CCCCCCCC", $buf);

    for($j=0; $j < 8; $j++) {
	$b2[$j] = $b[7 - $j];
    }

    $buf2 = pack("CCCCCCCC", @b2);

    my $value = unpack("d", $buf2);

    return $value;

}  # read_msb_double64



sub read_stats_info
{
    $stats_filespec = "sta.adf";
    print "read_stats_info($stats_filespec)\n";

    open($stats_handle, $stats_filespec) || die "Could not open
[$stats_filespec]\n";
    binmode $stats_handle;

    @vars = ("SMin", "SMax", "SMean", "SStdDev");

    for($i=0; $i < 4; $i++) {

	$value = &read_msb_double64($stats_handle);
	print "  $vars[$i]: [$value]\n";

    }  # for

    close $stats_handle;
    print "\n";

}  # read_stats_info



sub read_header
{
    $header_filespec = "hdr.adf";
    print "read_header($header_filespec)\n";

    open($hdr_handle, $header_filespec) || die "Could not open
[$header_filespec]\n";
    binmode $hdr_handle;

    print "  HMagic [";
    for($i=0; $i < 8; $i++) {
	read($hdr_handle, $buf, 1);
	($id) = unpack("a", $buf);
	print $id;
    }
    print "]\n";

    read($hdr_handle, $dummy, 8);

    $celltype = &read_msb_int32($hdr_handle);
    print "  HCellType [$celltype]\n";

    read($hdr_handle, $dummy, 236);

    $pixel_size_x = &read_msb_double64($hdr_handle);
    print "  HPixelSizeX [$pixel_size_x]\n";
    $pixel_size_y = &read_msb_double64($hdr_handle);
    print "  HPixelSizeY [$pixel_size_y]\n";

    $unknown = &read_msb_double64($hdr_handle);
    print "  unknown1 [$unknown]\n";
    $unknown = &read_msb_double64($hdr_handle);
    print "  unknown2 [$unknown]\n";

    $tiles_per_row = &read_msb_int32($hdr_handle);
    print "  HTilesPerRow [$tiles_per_row]\n";

    $tiles_per_column = &read_msb_int32($hdr_handle);
    print "  HTilesPerColumn [$tiles_per_column]\n";

    $tile_x_size = &read_msb_int32($hdr_handle);
    print "  HTileXSize [$tile_x_size]\n";

    $unknown = &read_msb_int32($hdr_handle);
    print "  unknown [$unknown]\n";

    $tile_y_size = &read_msb_int32($hdr_handle);
    print "  HTileYSize [$tile_y_size]\n";

    close($hdr_handle);

}  # read_header



More information about the Gdal-dev mailing list