fout.writeBytes(group.scale);
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)); }
    public void writeTOCFile(String filename, RpfHeader head,                              Vector frames, Vector groups)         throws MakeTocException {                short us;        int ui;        int i, j, tail;                /* DKS changed from left, right for polar zone: new left_bottom longit. */        double left_b, left_t, right_b, right_t, top, bottom;        double xleft, xright, ytop, ybottom;                /* !! To be filled in later */        int TOC_Nitf_hdr_size = 0;       /* ?? Nitf header size for output TOC */        int Loc_sec_len;               /* Location section length */        int Bound_tbl_len;             /* Boundary rectangle table length */        int Frame_hdr_len = 13;         /* Frame index header length */        int Frame_index_rec_len = 33;  /* 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 {                    direct[i] = frame.filename.substring(0, ++tail);                }                                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].indexOf("RPF");                    if (rpfIndex == -1) {                        rpfIndex = direct[i].indexOf("rpf");                    }                     if (rpfIndex != -1) {                        rpfIndex += 3;                        if (direct[i].length() > rpfIndex &&                             direct[i].charAt(rpfIndex) == File.separatorChar) {                                                        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 + head.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 + head.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 + head.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 + head.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 */                                fout.writeBytes(group.scale);  // 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());        }            }   /* main */