void NitfWriter::doneFile() { finishOutput(); std::streambuf *buf = m_oss.rdbuf(); long size = buf->pubseekoff(0, m_oss.end); buf->pubseekoff(0, m_oss.beg); std::vector<char> bytes(size); buf->sgetn(bytes.data(), size); m_oss.clear(); m_nitf.wrapData(bytes.data(), size); m_nitf.setBounds(reprojectBoxToDD(m_srs, m_bounds)); try { m_nitf.write(); } catch (except::Throwable & t) { std::ostringstream oss; // std::cout << t.getTrace(); throw pdal_error(t.getMessage()); } }
void NitfWriter::doneFile() { finishOutput(); try { ::nitf::Record record(NITF_VER_21); ::nitf::FileHeader header = record.getHeader(); header.getFileHeader().set("NITF"); header.getComplianceLevel().set(m_cLevel); header.getSystemType().set(m_sType); header.getOriginStationID().set(m_oStationId); if (m_fileTitle.empty()) m_fileTitle = FileUtils::getFilename(m_nitfFilename); header.getFileTitle().set(m_fileTitle); header.getClassification().set(m_fileClass); header.getMessageCopyNum().set("00000"); header.getMessageNumCopies().set("00000"); header.getEncrypted().set("0"); header.getBackgroundColor().setRawData(const_cast<char*>("000"), 3); header.getOriginatorName().set(m_origName); header.getOriginatorPhone().set(m_origPhone); header.getSecurityGroup().getClassificationSystem().set( m_securityClassificationSystem); header.getSecurityGroup().getControlAndHandling().set( m_securityControlAndHandling); header.getSecurityGroup().getClassificationText().set(m_sic); ::nitf::DESegment des = record.newDataExtensionSegment(); des.getSubheader().getFilePartType().set("DE"); des.getSubheader().getTypeID().set("LIDARA DES"); des.getSubheader().getVersion().set("01"); des.getSubheader().getSecurityClass().set(m_securityClass); ::nitf::FileSecurity security = record.getHeader().getSecurityGroup(); des.getSubheader().setSecurityGroup(security.clone()); ::nitf::TRE usrHdr("LIDARA DES", "raw_data"); usrHdr.setField("raw_data", "not"); ::nitf::Field fld = usrHdr.getField("raw_data"); fld.setType(::nitf::Field::BINARY); std::streambuf *buf = m_oss.rdbuf(); long size = buf->pubseekoff(0, m_oss.end); buf->pubseekoff(0, m_oss.beg); std::vector<char> bytes(size); buf->sgetn(bytes.data(), size); m_oss.clear(); des.getSubheader().setSubheaderFields(usrHdr); ::nitf::ImageSegment image = record.newImageSegment(); ::nitf::ImageSubheader subheader = image.getSubheader(); BOX3D bounds = reprojectBoxToDD(m_srs, m_bounds); //NITF decimal degree values for corner coordinates only has a // precision of 3 after the decimal. This may cause an invalid // polygon due to rounding errors with a small tile. Therefore // instead of rounding min values will use the floor value and // max values will use the ceiling values. bounds.minx = (floor(bounds.minx * 1000)) / 1000.0; bounds.miny = (floor(bounds.miny * 1000)) / 1000.0; bounds.maxx = (ceil(bounds.maxx * 1000)) / 1000.0; bounds.maxy = (ceil(bounds.maxy * 1000)) / 1000.0; double corners[4][2]; corners[0][0] = bounds.maxy; corners[0][1] = bounds.minx; corners[1][0] = bounds.maxy; corners[1][1] = bounds.maxx; corners[2][0] = bounds.miny; corners[2][1] = bounds.maxx; corners[3][0] = bounds.miny; corners[3][1] = bounds.minx; subheader.setCornersFromLatLons(NRT_CORNERS_DECIMAL, corners); subheader.getImageSecurityClass().set(m_imgSecurityClass); subheader.setSecurityGroup(security.clone()); if (m_imgDate.size()) subheader.getImageDateAndTime().set(m_imgDate); ::nitf::BandInfo info; ::nitf::LookupTable lt(0,0); info.init(" ", /* The band representation, Nth band */ " ", /* The band subcategory */ "N", /* The band filter condition */ " ", /* The band standard image filter code */ 0, /* The number of look-up tables */ 0, /* The number of entries/LUT */ lt); /* The look-up tables */ std::vector< ::nitf::BandInfo> bands; bands.push_back(info); subheader.setPixelInformation( "INT", /* Pixel value type */ 8, /* Number of bits/pixel */ 8, /* Actual number of bits/pixel */ "R", /* Pixel justification */ "NODISPLY", /* Image representation */ "VIS", /* Image category */ 1, /* Number of bands */ bands); subheader.setBlocking( 8, /*!< The number of rows */ 8, /*!< The number of columns */ 8, /*!< The number of rows/block */ 8, /*!< The number of columns/block */ "B"); /*!< Image mode */ //Image Header fields to set subheader.getImageId().set("None"); subheader.getImageTitle().set(m_imgIdentifier2); // 64 char string std::string zeros(64, '0'); std::unique_ptr< ::nitf::BandSource> band(new ::nitf::MemorySource( const_cast<char*>(zeros.c_str()), zeros.size() /* memory size */, 0 /* starting offset */, 1 /* bytes per pixel */, 0 /*skip*/)); ::nitf::ImageSource iSource; iSource.addBand(*band); //AIMIDB ::nitf::TRE aimidbTre("AIMIDB"); //LIDAR defaults if (m_imgDate.size()) aimidbTre.setField("ACQUISITION_DATE", m_imgDate); aimidbTre.setField("MISSION_NO", "UNKN"); aimidbTre.setField("MISSION_IDENTIFICATION", "NOT AVAIL."); aimidbTre.setField("FLIGHT_NO", "00"); aimidbTre.setField("CURRENT_SEGMENT", "AA"); aimidbTre.setField("START_TILE_COLUMN", "001"); aimidbTre.setField("START_TILE_ROW", "00001"); aimidbTre.setField("END_SEGMENT", "00"); aimidbTre.setField("END_TILE_COLUMN", "001"); aimidbTre.setField("END_TILE_ROW", "00001"); for (auto& s : m_aimidb) { StringList v = Utils::split2(s, ':'); if (v.size() != 2) { std::ostringstream oss; oss << "Invalid name/value for AIMIDB '" << s << "'. Format: <name>:<value>."; throw oss.str(); } Utils::trim(v[0]); Utils::trim(v[1]); aimidbTre.setField(v[0], v[1]); } subheader.getExtendedSection().appendTRE(aimidbTre); //if IDATIM is empty set it equal to AIMIDB.ACQUISITION_DATE if(!m_imgDate.size()) { m_imgDate=aimidbTre.getField("ACQUISITION_DATE").toString(); if (m_imgDate.size()) subheader.getImageDateAndTime().set(m_imgDate); } //ACFTB ::nitf::TRE acftbTre("ACFTB"); //LIDAR defaults acftbTre.setField("AC_MSN_ID", "NOT AVAILABLE"); acftbTre.setField("SCENE_SOURCE", " "); if (m_imgDate.size()>7) acftbTre.setField("PDATE", m_imgDate.substr(0,8)); acftbTre.setField("MPLAN", "999"); acftbTre.setField("LOC_ACCY", "000.00"); acftbTre.setField("ROW_SPACING", "0000000"); acftbTre.setField("ROW_SPACING_UNITS", "u"); acftbTre.setField("COL_SPACING", "0000000"); acftbTre.setField("COL_SPACING_UNITS", "u"); acftbTre.setField("FOCAL_LENGTH", "999.99"); for (auto& s : m_acftb) { StringList v = Utils::split2(s, ':'); if (v.size() != 2) { std::ostringstream oss; oss << "Invalid name/value for ACFTB '" << s << "'. Format: <name>:<value>."; throw oss.str(); } Utils::trim(v[0]); Utils::trim(v[1]); acftbTre.setField(v[0], v[1]); } subheader.getExtendedSection().appendTRE(acftbTre); ::nitf::Writer writer; ::nitf::IOHandle output_io(m_nitfFilename.c_str(), NITF_ACCESS_WRITEONLY, NITF_CREATE); writer.prepare(output_io, record); ::nitf::SegmentWriter sWriter = writer.newDEWriter(0); ::nitf::SegmentMemorySource sSource(bytes.data(), size, 0, 0, false); sWriter.attachSource(sSource); ::nitf::ImageWriter iWriter = writer.newImageWriter(0); iWriter.attachSource(iSource); writer.write(); output_io.close(); } catch (except::Throwable & t) { std::ostringstream oss; // std::cout << t.getTrace(); throw pdal_error(t.getMessage()); } }
void NitfWriter::done(PointTableRef table) { LasWriter::done(table); try { ::nitf::Record record(NITF_VER_21); ::nitf::FileHeader header = record.getHeader(); header.getFileHeader().set("NITF"); header.getComplianceLevel().set(m_cLevel); header.getSystemType().set(m_sType); header.getOriginStationID().set(m_oStationId); header.getFileTitle().set(m_fileTitle); header.getClassification().set(m_fileClass); header.getMessageCopyNum().set("00000"); header.getMessageNumCopies().set("00000"); header.getEncrypted().set("0"); header.getBackgroundColor().setRawData(const_cast<char*>("000"), 3); header.getOriginatorName().set(m_origName); header.getOriginatorPhone().set(m_origPhone); header.getSecurityGroup().getClassificationSystem().set(m_securityClassificationSystem); header.getSecurityGroup().getControlAndHandling().set(m_securityControlAndHandling); header.getSecurityGroup().getClassificationText().set(m_sic); ::nitf::DESegment des = record.newDataExtensionSegment(); des.getSubheader().getFilePartType().set("DE"); des.getSubheader().getTypeID().set("LIDARA DES"); des.getSubheader().getVersion().set("01"); des.getSubheader().getSecurityClass().set(m_securityClass); ::nitf::FileSecurity security = record.getHeader().getSecurityGroup(); des.getSubheader().setSecurityGroup(security.clone()); ::nitf::TRE usrHdr("LIDARA DES", "raw_data"); usrHdr.setField("raw_data", "not"); ::nitf::Field fld = usrHdr.getField("raw_data"); fld.setType(::nitf::Field::BINARY); flush(); m_oss.flush(); std::streambuf *buf = m_oss.rdbuf(); long size = buf->pubseekoff(0, m_oss.end); buf->pubseekoff(0, m_oss.beg); std::vector<char> bytes(size); buf->sgetn(bytes.data(), size); des.getSubheader().setSubheaderFields(usrHdr); ::nitf::ImageSegment image = record.newImageSegment(); ::nitf::ImageSubheader subheader = image.getSubheader(); BOX3D bounds = reprojectBoxToDD(table.spatialRef(), m_bounds); //NITF decimal degree values for corner coordinates only has a // precision of 3 after the decimal. This may cause an invalid // polygon due to rounding errors with a small tile. Therefore // instead of rounding min values will use the floor value and // max values will use the ceiling values. bounds.minx = (floor(bounds.minx * 1000)) / 1000.0; bounds.miny = (floor(bounds.miny * 1000)) / 1000.0; bounds.maxx = (ceil(bounds.maxx * 1000)) / 1000.0; bounds.maxy = (ceil(bounds.maxy * 1000)) / 1000.0; double corners[4][2]; corners[0][0] = bounds.maxy; corners[0][1] = bounds.minx; corners[1][0] = bounds.maxy; corners[1][1] = bounds.maxx; corners[2][0] = bounds.miny; corners[2][1] = bounds.maxx; corners[3][0] = bounds.miny; corners[3][1] = bounds.minx; subheader.setCornersFromLatLons(NRT_CORNERS_DECIMAL, corners); subheader.getImageSecurityClass().set(m_imgSecurityClass); subheader.setSecurityGroup(security.clone()); if (m_imgDate.size()) subheader.getImageDateAndTime().set(m_imgDate); ::nitf::BandInfo info; ::nitf::LookupTable lt(0,0); info.init("G", /* The band representation, Nth band */ " ", /* The band subcategory */ "N", /* The band filter condition */ " ", /* The band standard image filter code */ 0, /* The number of look-up tables */ 0, /* The number of entries/LUT */ lt); /* The look-up tables */ std::vector< ::nitf::BandInfo> bands; bands.push_back(info); subheader.setPixelInformation( "INT", /* Pixel value type */ 8, /* Number of bits/pixel */ 8, /* Actual number of bits/pixel */ "R", /* Pixel justification */ "NODISPLY", /* Image representation */ "VIS", /* Image category */ 1, /* Number of bands */ bands); subheader.setBlocking( 8, /*!< The number of rows */ 8, /*!< The number of columns */ 8, /*!< The number of rows/block */ 8, /*!< The number of columns/block */ "P"); /*!< Image mode */ //Image Header fields to set subheader.getImageId().set("None"); subheader.getImageTitle().set(m_imgIdentifier2); // 64 char string std::string zeros(64, '0'); std::unique_ptr< ::nitf::BandSource> band(new ::nitf::MemorySource( const_cast<char*>(zeros.c_str()), zeros.size() /* memory size */, 0 /* starting offset */, 1 /* bytes per pixel */, 0 /*skip*/)); ::nitf::ImageSource iSource; iSource.addBand(*band); //AIMIDB if (!m_aimidb.empty()) { boost::optional<const Options&> options = m_aimidb.getOptions(); if (options) { ::nitf::TRE tre("AIMIDB"); std::vector<Option> opts = options->getOptions(); for (auto i = opts.begin(); i != opts.end(); ++i) { tre.setField(i->getName(), i->getValue<std::string>()); } subheader.getExtendedSection().appendTRE(tre); } } //ACFTB if (!m_acftb.empty()) { boost::optional<const Options&> options = m_acftb.getOptions(); if (options) { ::nitf::TRE tre("ACFTB"); std::vector<Option> opts = options->getOptions(); for (auto i = opts.begin(); i != opts.end(); ++i) { tre.setField(i->getName(), i->getValue<std::string>()); } subheader.getExtendedSection().appendTRE(tre); } } ::nitf::Writer writer; ::nitf::IOHandle output_io(m_filename.c_str(), NITF_ACCESS_WRITEONLY, NITF_CREATE); writer.prepare(output_io, record); ::nitf::SegmentWriter sWriter = writer.newDEWriter(0); ::nitf::SegmentMemorySource sSource(bytes.data(), size, 0, 0, false); sWriter.attachSource(sSource); ::nitf::ImageWriter iWriter = writer.newImageWriter(0); iWriter.attachSource(iSource); writer.write(); output_io.close(); } catch (except::Throwable & t) { std::ostringstream oss; // std::cout << t.getTrace(); throw pdal_error(t.getMessage()); } }