* Frame index record length
* (was 37)
*/
int Frame_sec_len; /* Frame section length */
RandomAccessFile fout = null;
int groupCount = groups.size();
int nFrames = frames.size();
/* cumulative pathname positions */
int[] pathname_pos = new int[nFrames];
/* List of pathnames: directories */
String[] direct = new String[nFrames];
/* Allocations for uniq directories */
int[] uniq_dir_ptr = new int[nFrames]; /*
* index from filename
* to uniq direct.
*/
int[] uniq_dir_pos = new int[nFrames]; /*
* position of direct.
* name in file
*/
/* list of direct. names */
String[] uniq_dir = new String[nFrames];
String georef = "AAAAAA"; /* GEOREF # */
Frame frame;
Group group;
// Right now, just write the new file locally.
try {
fout = new RandomAccessFile(filename, "rw");
/* WRITE TOC : */
if (Debug.debugging("maketoc")) {
Debug.output("MakeToc: *** writing TOC ***\n at: " + filename);
}
/* HEADER SECTION */
if (Debug.debugging("maketoc")) {
Debug.output("MakeToc: *** writing header section ***");
}
String charString;
char[] nt = new char[1];
nt[0] = '\0';
/* DKS. Can't write structure because of pad bytes */
/* fwrite(&head, sizeof(head), 1, fout); */
fout.writeBoolean(head.endian); // Big Endian - should
// match head.endian
fout.writeShort(RpfHeader.HEADER_SECTION_LENGTH);
fout.writeBytes(" A.TOC"); // has to be padded.
fout.writeByte(head.neww);
fout.writeBytes(head.standardNumber);
if (head.standardNumber.length() < 15) {
fout.writeBytes(createPadding(15 - head.standardNumber.length(),
false));
}
fout.writeBytes(head.standardDate);
if (head.standardDate.length() < 8) {
fout.writeBytes(createPadding(8 - head.standardDate.length(),
false));
}
// All this trouble just for a silly character.
char[] charArray = new char[1];
charArray[0] = head.classification;
charString = new String(charArray);
fout.writeBytes(charString);
Debug.message("maketoc", "MakeToc: writing country(" + head.country
+ ") and release(" + head.release + ")");
fout.writeBytes(head.country);
fout.writeBytes(head.release);
/*
* New, DKS. no longer head.loc_sec_phys_loc. Always write
* 48.
*/
/*
* DFD - This isn't true, but since we don't care about
* NITF formatting, it may be. Just write out where we
* are.
*/
int location_section_location = (int) fout.getFilePointer() + 4;
fout.writeInt(location_section_location);
if (Debug.debugging("maketoc")) {
Debug.output("MakeToc: location section location is : "
+ location_section_location);
}
if (Debug.debugging("maketoc")) {
Debug.output("MakeToc: *** writing location section ***");
}
/* LOCATION SECTION */
int Loc_hdr_len = 14; /* Location section header length */
int Loc_sec_comp_len = 10; /*
* Location section component
* length
*/
/* 14 + 4 * 10 = 54 */
Loc_sec_len = Loc_hdr_len
+ (RpfFileSections.TOC_LOCATION_KEY * Loc_sec_comp_len);
fout.writeShort(Loc_sec_len);
/* compon. loc tbl offset: location section hdr length */
fout.writeInt(Loc_hdr_len);
/* # records in location section: 4 */
fout.writeShort(RpfFileSections.TOC_LOCATION_KEY);
/* component location record length: 10 */
fout.writeShort(Loc_sec_comp_len);
if (Debug.debugging("maketoc")) {
Debug.output("MakeToc:\n location section length: "
+ Loc_sec_len + "\n location header length: "
+ Loc_hdr_len + "\n number of location records: "
+ RpfFileSections.TOC_LOCATION_KEY
+ "\n location section comp length: "
+ Loc_sec_comp_len);
}
/*
* compon. aggregate len: unknown here. Fill in after
* doing all else.
*/
/* location component aggregate length file location */
long agg_loc = fout.getFilePointer(); /* save for later */
fout.writeInt(0); // place holder.
/* Begin: location section, component location table */
int Bound_hdr_len = 8; /* Boundary section header length */
int Bound_rec_len = 132; /* Boundary record length */
/* Boundary section length */
int Bound_sec_len = Bound_hdr_len + (groupCount * Bound_rec_len);
/* Compute frame section length, for later */
pathname_pos[0] = 0; /* cum. offset */
int uniq_dir_cnt = 0; /* # of unique directory paths. */
// Looking for the directory name for each file.
for (i = 0; i < nFrames; i++) { /* for each frame file */
/*
* set tail to ptr to last occurrence of '/' in
* filename
*/
/* frames[i].filename is full pathname */
frame = (Frame) frames.elementAt(i);
tail = frame.filename.lastIndexOf(File.separatorChar);
if (tail == -1) {
direct[i] = frame.filename;
} else {
// Java-cise the name, so it meets spec.
direct[i] = frame.filename.substring(0, ++tail)
.replace('\\', '/');
}
if (Debug.debugging("maketocdetail"))
Debug.output("MakeToc: Matching directory: " + direct[i]);
/* Match direct. names with list of uniq direct. names */
/* flag for found name in list */
boolean uniq_dir_match = false;
String tmpDir = null;
if (relativeFramePaths) {
int rpfIndex = direct[i].lastIndexOf("RPF");
if (rpfIndex == -1) {
rpfIndex = direct[i].lastIndexOf("rpf");
}
if (rpfIndex != -1) {
rpfIndex += 3;
if (direct[i].length() > rpfIndex
&& direct[i].charAt(rpfIndex) == '/') {
rpfIndex++;
}
tmpDir = "./" + direct[i].substring(rpfIndex);
} else {
if (Debug.debugging("maketoc")) {
Debug.output("RPF directory not found in directory path "
+ direct[i] + ", using absolute path");
}
tmpDir = direct[i];
}
} else {
tmpDir = direct[i];
}
for (j = 0; j < uniq_dir_cnt; j++) {
if (tmpDir.equals(uniq_dir[j])) {
uniq_dir_ptr[i] = j;
uniq_dir_match = true;
if (Debug.debugging("maketocdetail"))
Debug.output("Found match with: " + uniq_dir[j]);
break;
}
}
if (!uniq_dir_match) {
uniq_dir[uniq_dir_cnt] = tmpDir;
uniq_dir_ptr[i] = uniq_dir_cnt;
if (Debug.debugging("maketoc"))
Debug.output("Adding Unique directory: "
+ uniq_dir[uniq_dir_cnt]);
uniq_dir_cnt++;
} /* if */
} /* for i */
if (Debug.debugging("maketoc"))
Debug.output("Uniq_dir_cnt: " + uniq_dir_cnt);
/* compute uniq dir pathname table length */
int path_table_len = 0;
for (j = 0; j < uniq_dir_cnt; j++) {
/* 2 for path length var. in hdr */
path_table_len += 2 + uniq_dir[j].length();
} /* for j */
/* compute directory name positions in file */
uniq_dir_pos[0] = 0;
for (j = 1; j < uniq_dir_cnt; j++) {
uniq_dir_pos[j] = uniq_dir_pos[j - 1] + 2
+ uniq_dir[j - 1].length();
} /* for j */
for (j = 0; j < uniq_dir_cnt; j++) {
if (Debug.debugging("maketocdetail"))
Debug.output("j: " + j + ", uniq_dir_pos[j]: "
+ uniq_dir_pos[j]);
} /* for j */
/* compute direct. positions for each input file pathname */
for (i = 0; i < nFrames; i++) {
pathname_pos[i] = uniq_dir_pos[uniq_dir_ptr[i]];
if (Debug.debugging("maketocdetail"))
Debug.output("i: " + i + ", pathname_pos[i]:"
+ pathname_pos[i]);
} /* for i */
/*
* frame file index record length: 9 + nFrames * 33 +
* path_table_len
*/
Frame_sec_len = Frame_hdr_len + nFrames * Frame_index_rec_len
+ path_table_len;
/* START LOCATION RECORD 1 */
/* ID #: */
fout.writeShort((short) RpfFileSections.LOC_BOUNDARY_SECTION_SUBHEADER);
// The boundary section subheader is the first part of the
// bounfary rectangle section. The boundary section comes
// right after the header (in this program - the spec will
// allow it to be anywhere).
/* Boundary section subheader length */
fout.writeInt(Bound_hdr_len);
/* DKS. Physical location */
/* 0 + 48 + 54 */
fout.writeInt(TOC_Nitf_hdr_size + RpfHeader.HEADER_SECTION_LENGTH
+ Loc_sec_len);
/* START LOCATION RECORD 2 */
/* ID #: */
fout.writeShort((short) RpfFileSections.LOC_BOUNDARY_RECTANGLE_TABLE);
/* Boundary rectangle table length */
Bound_tbl_len = groupCount * Bound_rec_len;
fout.writeInt(Bound_tbl_len);
/* DKS. Physical location */
/* 0 + 48 + 54 + 8 */
fout.writeInt(TOC_Nitf_hdr_size + RpfHeader.HEADER_SECTION_LENGTH
+ Loc_sec_len + Bound_hdr_len);
Bound_sec_len = Bound_hdr_len + Bound_tbl_len;
/* START LOCATION RECORD 3 */
/* ID #: */
fout.writeShort((short) RpfFileSections.LOC_FRAME_FILE_INDEX_SUBHEADER);
/* length */
fout.writeInt(Frame_hdr_len);
/* physical index (offset) */
fout.writeInt(TOC_Nitf_hdr_size + RpfHeader.HEADER_SECTION_LENGTH
+ Loc_sec_len + Bound_sec_len);
/* START LOCATION RECORD 4 */
/* ID #: */
fout.writeShort((short) RpfFileSections.LOC_FRAME_FILE_INDEX_SUBSECTION);
/* length */
/* Frame_sec_len computed above */
fout.writeInt(Frame_sec_len - Frame_hdr_len);
/* physical index (offset) */
fout.writeInt(TOC_Nitf_hdr_size + RpfHeader.HEADER_SECTION_LENGTH
+ Loc_sec_len + Bound_sec_len + Frame_hdr_len);
if (Debug.debugging("maketoc")) {
Debug.output("MakeToc: boundary section at : "
+ fout.getFilePointer());
}
/* START BOUNDARY RECTANGLE SECTION */
if (Debug.debugging("maketoc")) {
Debug.output("MakeToc: *** writing boundary rectangles ***");
}
/* Subheader */
/* boundary rectangle table offset */
fout.writeInt(0);
/* # of boundary rectangle records */
fout.writeShort((short) groupCount);
/* boundary rectangle record length */
fout.writeShort((short) Bound_rec_len);
/* For each boundary rectangle record */
for (i = 0; i < groupCount; i++) {
group = (Group) groups.elementAt(i);
/*
* Key off flag to write proper data to A.TOC for
* browse menu later
*/
if (group.cib) {
fout.writeBytes("CIB ");
fout.writeBytes("8:1 "); /* Compr. ratio */
} else if (group.cdted) {
fout.writeBytes("CDTED");
fout.writeBytes("6.5:1"); /*
* Compr. ratio:
* VARIABLE
*/
} else {
fout.writeBytes("CADRG");
fout.writeBytes("55:1 ");
} /* else */
// Should be 12 padded chars, check just in case...
if (group.scale.length() < 12) {
fout.writeBytes(group.scale);
fout.writeBytes(createPadding(12 - group.scale.length(),
false));
} else {
fout.writeBytes(group.scale.substring(0, 12)); // Already
// 12
// padded
// chars
}
// All this trouble just for a silly character.
charArray[0] = group.zone;
charString = new String(charArray);
fout.writeBytes(charString);
/* DKS changed from AFESC to DMAAC 8/2/94 */
/* Producer: */
// Should be OpenMap BBN, I guess.
fout.writeBytes(producer);
/*
* PBF - If group is polar, change boundaries from
* rect coordinates to lat-lon -- 6-19-94
*/
if (group.zone == '9' || group.zone == 'J') { /*
* polar
* zone
*/
/*
* DKS: switched x,y to match spec: x increases
* right, y up.
*/
ytop = group.horiz_pos[group.top];
ybottom = group.horiz_pos[group.bottom];
xleft = group.vert_pos[group.left];
xright = group.vert_pos[group.right];
if (Debug.debugging("maketoc")) {
Debug.output("POLAR ZONE. ytop: " + ytop
+ ", ybottom: " + ybottom + ", xleft: " + xleft
+ ", xright:" + xright);
}
/* see CADRG SPEC 89038, p. 50 */
/*
* FIND LATITUDES from x,y. x increases right, y
* up.
*/
/* DKS new 1/95 to handle South pole separately. */
/* h_interval converts from pix to deg. */
if (group.zone == '9') { /* "9": NORTH POLE */
top = 90 - (Math.sqrt((ytop * ytop) + (xleft * xleft)) * (group.h_interval));
bottom = 90 - (Math.sqrt((ybottom * ybottom)
+ (xright * xright)) * (group.h_interval));
} /* North pole */
else { /* "J": South Pole */
top = -90
+ (Math.sqrt((ytop * ytop) + (xleft * xleft)) * (group.h_interval));
bottom = -90
+ (Math.sqrt((ybottom * ybottom)
+ (xright * xright)) * (group.h_interval));
} /* South pole */
if (Debug.debugging("maketoc"))
Debug.output("LATS. top: " + top + ", bottom: "
+ bottom);
/*
* Cvt from x,y to LONGITUDE; from radians to
* degrees
*/
/* DKS added South pole case 1/95 */
if (group.zone == '9') { /* "9": NORTH POLE */
left_t = 180.0
/ Math.PI
* Math.acos(-ytop
/ Math.sqrt((ytop * ytop)
+ (xleft * xleft)));
/* DKS fixed bug 1/95: from ytop to ybottom */
left_b = 180.0
/ Math.PI
* Math.acos(-ybottom
/ Math.sqrt((ybottom * ybottom)
+ (xleft * xleft)));
right_t = 180.0
/ Math.PI
* Math.acos(-ytop
/ Math.sqrt((ytop * ytop)
+ (xright * xright)));
/* DKS fixed bug 1/95: from ytop to ybottom */
right_b = 180.0
/ Math.PI
* Math.acos(-ybottom
/ Math.sqrt((ybottom * ybottom)
+ (xright * xright)));
} /* if North pole */
else { /* South Pole */
left_t = 180.0
/ Math.PI
* Math.acos(ytop
/ Math.sqrt((ytop * ytop)
+ (xleft * xleft)));
/* DKS fixed bug 1/95: from ytop to ybottom */
left_b = 180.0
/ Math.PI
* Math.acos(ybottom
/ Math.sqrt((ybottom * ybottom)
+ (xleft * xleft)));
right_t = 180.0
/ Math.PI
* Math.acos(ytop
/ Math.sqrt((ytop * ytop)
+ (xright * xright)));
/* DKS fixed bug 1/95: from ytop to ybottom */
right_b = 180.0
/ Math.PI
* Math.acos(ybottom
/ Math.sqrt((ybottom * ybottom)
+ (xright * xright)));
} /* if South pole */
/* For both poles: */
if (xleft < 0) { /*
* left half of earth has
* negative longits
*/
left_t = -left_t;
left_b = -left_b;
}
/* This will hardly ever happen: */
if (xright < 0) { /*
* left half of earth has
* negative longs
*/
right_t = -right_t;
right_b = -right_b;
}
if (Debug.debugging("maketoc"))
Debug.output("LONGS. left_t: " + left_t + ", right_t: "
+ right_t);
if (Debug.debugging("maketoc"))
Debug.output("LONGS. left_b: " + left_b + ", right_b: "
+ right_b);
// #if 0
// /* !!!!!!!!!!!!!!!!!!! Fix to getlat [80,90],
// longit. [-180,180] */
// bottom = 80.0 ;
// top = 90.0 ;
// left = -180.0 ;
// right = 180.0 ;
// #endif
} /* if polar zone */
/* end DKS portion */
/* end PBF cvt from xy to lat-long */
else { /* non-polar zone */
left_t = group.vert_pos[group.left];
left_b = left_t;
right_t = group.vert_pos[group.right];
right_b = right_t;
top = group.horiz_pos[group.top];
bottom = group.horiz_pos[group.bottom];
} /* else */
// Debug.output("For RpfTocEntry, writing: \n top = "
// + top +
// "\n bottom = " + bottom + "\n left = " + left_t +
// "\n right = " + right_t + "\n---------");
// Writing all doubles
fout.writeDouble(top);
fout.writeDouble(left_t);
fout.writeDouble(bottom);
fout.writeDouble(left_b);
fout.writeDouble(top);
fout.writeDouble(right_t);
fout.writeDouble(bottom);
fout.writeDouble(right_b);
fout.writeDouble(group.v_resolution);
fout.writeDouble(group.h_resolution);
fout.writeDouble(group.v_interval);
fout.writeDouble(group.h_interval);
/* # frames */
fout.writeInt((int) (group.bottom - group.top));
fout.writeInt((int) (group.right - group.left));
}
if (Debug.debugging("maketoc")) {
Debug.output("MakeToc: *** writing frame section ***");
Debug.output("MakeToc: started with a 'U'");
}
/* START FRAME SECTION */
/* Now write frames */
/* security classif */
charArray[0] = 'U';
charString = new String(charArray);
fout.writeBytes(charString);
/* frame file index tbl offset */
fout.writeInt(0);
/* # of frame file index records */
fout.writeInt(nFrames);
/* # of pathname (directory) records */
/* DKS NEW: was nFrames: */
fout.writeShort(uniq_dir_cnt);
/* frame file index record length : 33 */
fout.writeShort(Frame_index_rec_len);
/* Frame file index subsection */
for (i = 0; i < nFrames; i++) { /* for each frame file */
frame = (Frame) frames.elementAt(i);
group = (Group) groups.elementAt(frame.group);
if (!frame.marked) {
Debug.error(frame.filename + ": not in a boundary rect??");
// continue;
}
/* NEW, DKS: +1 removed so range is [0,n]: */
fout.writeShort(frame.group); /* Boundary rect. rec. # */
/* Frame location ROW number */
/*
* DKS. Changed from top to bottom to fix bug in
* Theron's frame numbering
*/
/*
* Should start numbering at BOTTOM (southern-most
* part) of group
*/
/* !!! Changed back so row num is never <= 0 */
/* Alternative is bottom-y, not y-bottom. Try later */
/*
* us = frames[i].y - groups[frames[i].group].bottom +
* 1;
*/
/* NEW, DKS: START AT 0, NOT 1: REMOVE "+ 1": */
/* us = frames[i].y - groups[frames[i].group].top; */
/*
* SMN The frames number are from the bottom left not
* top left
*/
us = (short) (group.bottom - frame.y - 1);
if (Debug.debugging("maketocframedetail")) {
Debug.output("iframe: " + i + ", frame.y: " + frame.y);
Debug.output("frame.group: " + frame.group);
Debug.output("group.bottom:" + group.bottom);
Debug.output("group.top:" + group.top);
Debug.output("frame row #:" + us);
}
fout.writeShort(us);
/* Frame location Column number */
/* NEW, DKS: START AT 0, NOT 1: REMOVE "+ 1": */
fout.writeShort((short) (frame.x - group.left));
/* pathname record offset: */
/*
* DKS 11/10: Now w.r.t. frame file index table
* subsection
*/
/*
* ui = head.HEADER_SECTION_LENGTH + Loc_sec_len +
* Bound_sec_len + Frame_hdr_len +
* nFrames*Frame_index_rec_len + pathname_pos[i] ;
*/
fout.writeInt((int) (nFrames * Frame_index_rec_len + pathname_pos[i]));
String framename;
tail = frame.filename.lastIndexOf(File.separatorChar);
if (tail == -1) {
framename = frame.filename;
} else {
framename = frame.filename.substring(++tail);
}
if (framename.length() > 12) {
Debug.error("MakeToc: encountered a frame name that's too long!\n"
+ framename);
framename = framename.substring(0, 12);
}
/* frame file name */
fout.writeBytes(framename);
String seriesCode = framename.substring(9, 11);
/* Check for Overview image: affects GEOREF */
if (!seriesCode.equalsIgnoreCase("OV")
&& !seriesCode.equalsIgnoreCase("LG")
&& !seriesCode.equalsIgnoreCase("OI")) {
/* Not Overview or Lengend img */
/* DKS 8/1/94: handle polar zone separately */
if (frame.zone != '9' || frame.zone != 'J') { /*
* polar
* zone
*/
georef = latlong2GEOREF(frame.swlat, frame.swlon);
} else { /* not polar */
georef = latlong2GEOREF(frame.bottom, frame.left);
} /* else */
} else { /* Overview image has no GEOREF */
if (Debug.debugging("maketoc"))
Debug.output("Overview image has no GEOREF");
georef = "000000";
} /* else */
fout.writeBytes(georef);
/* classification */
// HACK - assumes unclassified data.
fout.writeBytes(charString);
fout.writeBytes(head.country);
fout.writeBytes(head.release);
} /* for i (each frame file) */
Debug.message("maketoc",
"MakeToc: *** writing directory section ***");
/* Pathname table */
/*
* Write UNIQUE pathnames: really Directory name, e.g.
* "./CENTRAL.USA/"
*/
for (j = 0; j < uniq_dir_cnt; j++) {
/* DKS new */
/*
* write pathname length. !!?? may be padded in front
* to align on word bndary!!??
*/
fout.writeShort((short) (uniq_dir[j].length()));
/* pathname */
fout.writeBytes(uniq_dir[j]);
} /* for j (each uniq directory) */
/* No color table index section */
/*
* Go back and fill in component aggregate length in
* location section
*/
fout.seek(agg_loc);
fout.writeInt((int) (Bound_sec_len + Frame_sec_len));
fout.close();
Debug.message("maketoc", "MakeToc: *** Normal end of make-toc ***");
} catch (IOException ioe) {
throw new MakeTocException(ioe.getMessage());
}