// **********************************************************************
//
// <copyright>
//
// BBN Technologies
// 10 Moulton Street
// Cambridge, MA 02138
// (617) 873-8000
//
// Copyright (C) BBNT Solutions LLC. All rights reserved.
//
// </copyright>
// **********************************************************************
//
// $Source: /cvs/distapps/openmap/src/openmap/com/bbn/openmap/layer/rpf/RpfFileSections.java,v $
// $RCSfile: RpfFileSections.java,v $
// $Revision: 1.3 $
// $Date: 2004/10/14 18:06:03 $
// $Author: dietrick $
//
// **********************************************************************
/*
* The meat of this code is based on source code provided by
* The MITRE Corporation, through the browse application source
* code. Many thanks to Nancy Markuson who provided BBN with the
* software, and to Theron Tock, who wrote the software, and
* Daniel Scholten, who revised it - (c) 1994 The MITRE
* Corporation for those parts, and used with permission.
*/
package com.bbn.openmap.layer.rpf;
import java.awt.Color;
import java.io.IOException;
import com.bbn.openmap.io.BinaryFile;
import com.bbn.openmap.io.FormatException;
import com.bbn.openmap.util.Debug;
/**
* The class to use to get the locations of different sections of the
* RPF files. This class will find out the section locations, and then
* let you use it later to get to and read those sections.
*/
public class RpfFileSections {
/* DKS switched 3 and 4 to match handbook */
public static final int LOC_BOUNDARIES = 3;
public static final int LOC_FRAMES = 4;
public static final int LOC_COVERAGE = 6;
public static final int LOC_COMPRESSION = 8;
public static final int LOC_CLUT = 9;
public static final int LOC_IMAGE = 10;
/* DKS. New Location ID's for SUBsections */
public static final int LOC_HEADER_SECTION = 128;
public static final int LOC_LOCATION_SECTION = 129;
public static final int LOC_COVERAGE_SECTION = 130;
public static final int LOC_COMPRESSION_SECTION = 131;
public static final int LOC_COMPRESSION_LOOKUP_SUBSECTION = 132;
public static final int LOC_COMPRESSION_PARAMETER_SUBSECTION = 133;
public static final int LOC_COLORGRAY_SECTION_SUBHEADER = 134;
public static final int LOC_COLORMAP_SUBSECTION = 135;
public static final int LOC_IMAGE_DESCR_SUBHEADER = 136;
public static final int LOC_IMAGE_DISPLAY_PARAM_SUBHEADER = 137;
public static final int LOC_MASK_SUBSECTION = 138;
public static final int LOC_COLOR_CONVERTER_SUBSECTION = 139;
public static final int LOC_SPATIAL_DATA_SUBSECTION = 140;
public static final int LOC_ATTRIBUTE_SECTION_SUBHEADER = 141;
public static final int LOC_ATTRIBUTE_SUBSECTION = 142;
public static final int LOC_EXPLICIT_AREAL_TABLE = 143;
public static final int LOC_RELATED_IMAGE_SECTION_SUBHEADER = 144;
public static final int LOC_RELATED_IMAGE_SUBSECTION = 145;
public static final int LOC_REPLACE_UPDATE_SECTION_SUBHEADER = 146;
public static final int LOC_REPLACE_UPDATE_TABLE = 147;
public static final int LOC_BOUNDARY_SECTION_SUBHEADER = 148;
public static final int LOC_BOUNDARY_RECTANGLE_TABLE = 149;
public static final int LOC_FRAME_FILE_INDEX_SUBHEADER = 150;
public static final int LOC_FRAME_FILE_INDEX_SUBSECTION = 151;
public static final int LOC_COLOR_TABLE_SECTION_SUBHEADER = 152;
public static final int LOC_COLOR_TABLE_INDEX_RECORD = 153;
// the key represents the number of records for the key
public static final int TOC_LOCATION_KEY = 4;
public static final int FRAME_LOCATION_KEY = 8;
public static final int COLOR_LOCATION_KEY = 3;
RpfLocationSection locationSection; // created in init()
RpfLocationRecord[] locationRecords; // created as found in the
// file
protected boolean DEBUG_RPFDETAIL = false;
public RpfFileSections() {}
/**
* Create the file sections object, and then go ahead and parse
* the file section section of the RPF file. Assumes, the file
* pointer is in the right place, at the
* Rpfheader.locationSectionLocation.
*
* @param binFile the binaryFile of the RPF frame file.
*/
public RpfFileSections(BinaryFile binFile) {
parse(binFile);
}
public void parse(BinaryFile binFile) {
DEBUG_RPFDETAIL = Debug.debugging("rpfdetail");
// Location section
parseLocationSection(binFile);
}
public RpfLocationRecord[] getLocations(int key) {
if (locationRecords == null)
return null;
RpfLocationRecord[] locations = new RpfLocationRecord[key];
int[] ids = new int[key];
switch (key) {
case TOC_LOCATION_KEY:
ids[0] = LOC_BOUNDARY_SECTION_SUBHEADER; /* 148 */
ids[1] = LOC_BOUNDARY_RECTANGLE_TABLE; /* 149 */
ids[2] = LOC_FRAME_FILE_INDEX_SUBHEADER; /* 150 */
ids[3] = LOC_FRAME_FILE_INDEX_SUBSECTION; /* 151 */
break;
case FRAME_LOCATION_KEY:
ids[0] = LOC_COMPRESSION_SECTION; /* 131 */
ids[1] = LOC_IMAGE_DESCR_SUBHEADER; /* 136 */
ids[2] = LOC_COMPRESSION_LOOKUP_SUBSECTION; /* 132 */
ids[3] = LOC_SPATIAL_DATA_SUBSECTION; /* 140 */
ids[4] = LOC_IMAGE_DISPLAY_PARAM_SUBHEADER; /* 137 */
ids[5] = LOC_MASK_SUBSECTION; /* 138 */
ids[6] = LOC_ATTRIBUTE_SECTION_SUBHEADER; /* 141 */
ids[7] = LOC_ATTRIBUTE_SUBSECTION; /* 142 */
break;
case COLOR_LOCATION_KEY:
ids[0] = LOC_COLORGRAY_SECTION_SUBHEADER; /* 134 */
ids[1] = LOC_COLORMAP_SUBSECTION; /* 135 */
ids[2] = LOC_COLOR_CONVERTER_SUBSECTION; /* 139 */
break;
default:
}
for (int i = 0; i < key; i++)
locations[i] = getRpfLocationRecord(ids[i]);
return locations;
}
/**
* This function returns the location record, which provides the
* file location for a particular section. The LOC ids are in this
* file.
*/
public RpfLocationRecord getRpfLocationRecord(int locationRecordId) {
if (locationRecords != null) {
for (int i = 0; i < locationRecords.length; i++) {
if (locationRecordId == locationRecords[i].id) {
return locationRecords[i];
}
}
}
return null;
}
/**
* This function returns the RpfLocationSection for the file.
* Since we don't really know the location of the location section
* yet, we really have to have the file pointer set to the right
* place. This function should be called right after the RpfHeader
* has been read.
*/
protected boolean parseLocationSection(BinaryFile binFile) {
locationSection = new RpfLocationSection();
try {
locationSection.length = (int) binFile.readShort();
locationSection.tableOffset = (long) binFile.readInteger();
locationSection.numberRecords = (int) binFile.readShort();
locationSection.recordLength = (int) binFile.readShort();
locationSection.aggregateLength = (long) binFile.readInteger();
if (DEBUG_RPFDETAIL) {
Debug.output(locationSection.toString());
}
locationRecords = new RpfLocationRecord[locationSection.numberRecords];
// Now go find the ones we want
for (int i = 0; i < locationSection.numberRecords; i++) {
locationRecords[i] = new RpfLocationRecord();
locationRecords[i].id = binFile.readShort();
locationRecords[i].componentLength = (long) binFile.readInteger();
locationRecords[i].componentLocation = (long) (binFile.readInteger());
if (DEBUG_RPFDETAIL) {
Debug.output("** record " + i + ": "
+ locationRecords[i].toString());
}
}
} catch (IOException ioe) {
Debug.error("RpfFileSections: IO ERROR parsing locations!\n" + ioe);
return false;
} catch (FormatException fe) {
Debug.error("RpfFileSections: Format ERROR parsing locations!\n"
+ fe);
return false;
}
return true;
}
/**
* Read the location and information about the coverage section.
* The method will find out where to start reading from inside the
* file.
*/
public RpfCoverageSection parseCoverageSection(BinaryFile binFile) {
RpfLocationRecord lr = getRpfLocationRecord(LOC_COVERAGE_SECTION);
if (lr == null)
return null;
try {
binFile.seek(lr.componentLocation);
RpfCoverageSection coverage = new RpfCoverageSection();
if (coverage.read(binFile)) {
if (DEBUG_RPFDETAIL)
Debug.output(coverage.toString());
return coverage;
}
} catch (IOException ioe) {
Debug.error("RpfFileSections: IO ERROR parsing coverage!\n" + ioe);
}
return null;
}
/**
* Read the location and information about the attribute section.
* The method will find out where to start reading from inside the
* file.
*/
public RpfAttributes parseAttributes(BinaryFile binFile) {
RpfLocationRecord lr = getRpfLocationRecord(LOC_ATTRIBUTE_SECTION_SUBHEADER);
if (lr == null) {
if (DEBUG_RPFDETAIL) {
Debug.error("RpfFileSections: attribute section not found!");
}
return null;
}
RpfAttributes attributes = new RpfAttributes();
if (attributes.read(binFile, lr.componentLocation)) {
if (DEBUG_RPFDETAIL)
Debug.output(attributes.toString());
return attributes;
}
return null;
}
/**
* This kicks back an array of OMColors, representing the
* colortable. By going through the RpfFileSections function, the
* file locations for the color sections are taken care of, and
* the RpfColortable.parseColorLookUpTable function is called
* correctly.
*/
public Color[] parseColorSection(BinaryFile binFile,
RpfColortable colortable) {
if (locationRecords == null)
return null;
return colortable.parseColorLookUpTable(binFile,
getLocations(COLOR_LOCATION_KEY));
}
static public class RpfCoverageSection {
public double nwlat;
public double nwlon;
public double swlat;
public double swlon;
public double nelat;
public double nelon;
public double selat;
public double selon;
public double nsVertRes;
public double ewHorRes;
public double latInterval;
public double lonInterval;
public synchronized boolean read(BinaryFile binFile) {
try {
nwlat = binFile.readDouble();
nwlon = binFile.readDouble();
swlat = binFile.readDouble();
swlon = binFile.readDouble();
nelat = binFile.readDouble();
nelon = binFile.readDouble();
selat = binFile.readDouble();
selon = binFile.readDouble();
nsVertRes = binFile.readDouble();
ewHorRes = binFile.readDouble();
latInterval = binFile.readDouble();
lonInterval = binFile.readDouble();
} catch (IOException ioe) {
Debug.error("RpfFileSections: IO ERROR parsing coverage!\n"
+ ioe);
return false;
} catch (FormatException fe) {
Debug.error("RpfFileSections: Format ERROR parsing coverage!\n"
+ fe);
return false;
}
return true;
}
public String toString() {
StringBuffer s = new StringBuffer();
s.append("Coverage Section:\n");
s.append(" nwlat = ").append(nwlat).append("\n");
s.append(" nwlon = ").append(nwlon).append("\n");
s.append(" swlat = ").append(swlat).append("\n");
s.append(" swlon = ").append(swlon).append("\n");
s.append(" nelat = ").append(nelat).append("\n");
s.append(" nelon = ").append(nelon).append("\n");
s.append(" selat = ").append(selat).append("\n");
s.append(" selon = ").append(selon).append("\n");
s.append(" ns vertical resolution = ").append(nsVertRes).append("\n");
s.append(" ew horizontal resolution = ").append(ewHorRes).append("\n");
s.append(" lat interval = ").append(latInterval).append("\n");
s.append(" lon interval = ").append(lonInterval).append("\n");
return s.toString();
}
}
static public class RpfLocationSection {
public int length; // ushort
public long tableOffset; // ulong
public int numberRecords; //ushort
public int recordLength; //ushort
public long aggregateLength; //ulong
public String toString() {
StringBuffer s = new StringBuffer();
s.append("RpfLocationSection:\n");
s.append(" length = ").append(length).append("\n");
s.append(" table offset = ").append(tableOffset).append("\n");
s.append(" number of records = ").append(numberRecords).append("\n");
s.append(" record length = ").append(recordLength).append("\n");
s.append(" aggregate length = ").append(aggregateLength).append("\n");
return s.toString();
}
}
static public class RpfLocationRecord {
public short id;
public long componentLength;
public long componentLocation;
public String toString() {
StringBuffer s = new StringBuffer();
s.append("RpfLocationRecord:\n");
s.append(" id = ").append(id).append("\n");
s.append(" component length = ").append(componentLength).append("\n");
s.append(" component location = ").append(componentLocation).append("\n");
return s.toString();
}
}
}