bool ossimLasReader::getTile(ossimImageData* result, ossim_uint32 resLevel) { // static const char MODULE[] = "ossimLibLasReader::getTile(ossimImageData*, level)"; bool status = false; if ( m_hdr && result && (result->getScalarType() == OSSIM_FLOAT32) && (result->getDataObjectStatus() != OSSIM_NULL) && !m_ul.hasNans() && !m_scale.hasNans() ) { status = true; const ossimIrect TILE_RECT = result->getImageRectangle(); const ossim_int32 TILE_HEIGHT = static_cast<ossim_int32>(TILE_RECT.height()); const ossim_int32 TILE_WIDTH = static_cast<ossim_int32>(TILE_RECT.width()); const ossim_int32 TILE_SIZE = static_cast<ossim_int32>(TILE_RECT.area()); const ossim_uint16 ENTRY = m_entry+1; // Get the scale for this resLevel: ossimDpt scale; getScale(scale, resLevel); // Set the starting upper left of upper left pixel for this tile. const ossimDpt UL_PROG_PT( m_ul.x - scale.x / 2.0 + TILE_RECT.ul().x * scale.x, m_ul.y + scale.y / 2.0 - TILE_RECT.ul().y * scale.y); //--- // Set the lower right to the edge of the tile boundary. This looks like an // "off by one" error but it's not. We want the ossimDrect::pointWithin to // catch any points in the last line sample. //--- const ossimDpt LR_PROG_PT( UL_PROG_PT.x + TILE_WIDTH * scale.x, UL_PROG_PT.y - TILE_HEIGHT * scale.y); const ossimDrect PROJ_RECT(UL_PROG_PT, LR_PROG_PT, OSSIM_RIGHT_HANDED); #if 0 /* Please leave for debug. (drb) */ cout << "m_ul: " << m_ul << "\nm_scale: " << m_scale << "\nscale: " << scale << "\nresult->getScalarType(): " << result->getScalarType() << "\nresult->getDataObjectStatus(): " << result->getDataObjectStatus() << "\nPROJ_RECT: " << PROJ_RECT << "\nTILE_RECT: " << TILE_RECT << "\nUL_PROG_PT: " << UL_PROG_PT << endl; #endif const ossim_float64 SCALE_X = m_hdr->getScaleFactorX(); const ossim_float64 SCALE_Y = m_hdr->getScaleFactorY(); const ossim_float64 SCALE_Z = m_hdr->getScaleFactorZ(); const ossim_float64 OFFSET_X = m_hdr->getOffsetX(); const ossim_float64 OFFSET_Y = m_hdr->getOffsetY(); const ossim_float64 OFFSET_Z = m_hdr->getOffsetZ(); // Create array of buckets. std::vector<ossimLasReader::Bucket> bucket( TILE_SIZE ); // Loop through the point data. ossimLasPointRecordInterface* lasPtRec = getNewPointRecord(); ossimDpt lasPt; m_str.clear(); m_str.seekg(m_hdr->getOffsetToPointData()); while ( m_str.good() ) { // m_str.read((char*)lasPtRec, 28); lasPtRec->readStream( m_str ); if ( lasPtRec->getReturnNumber() == ENTRY ) { lasPt.x = lasPtRec->getX() * SCALE_X + OFFSET_X; lasPt.y = lasPtRec->getY() * SCALE_Y + OFFSET_Y; if ( m_unitConverter ) { convertToMeters(lasPt.x); convertToMeters(lasPt.y); } if ( PROJ_RECT.pointWithin( lasPt ) ) { // Compute the bucket index: ossim_int32 line = static_cast<ossim_int32>((UL_PROG_PT.y - lasPt.y) / scale.y); ossim_int32 samp = static_cast<ossim_int32>((lasPt.x - UL_PROG_PT.x) / scale.x ); ossim_int32 bucketIndex = line * TILE_WIDTH + samp; // Range check and add if in there. if ( ( bucketIndex >= 0 ) && ( bucketIndex < TILE_SIZE ) ) { ossim_float64 z = lasPtRec->getZ() * SCALE_Z + OFFSET_Z; if ( m_unitConverter ) convertToMeters(z); bucket[bucketIndex].add( z ); } } } if ( m_str.eof() ) break; } delete lasPtRec; lasPtRec = 0; //--- // We must always blank out the tile as we may not have a point for every // point. //--- result->makeBlank(); ossim_float32* buf = result->getFloatBuf(); // Tile buffer to fill. // Fill the tile. Currently no band loop: for (ossim_int32 i = 0; i < TILE_SIZE; ++i) { buf[i] = bucket[i].getValue(); } // Revalidate. result->validate(); } return status; } // End: bool ossimLibLasReader::getTile(ossimImageData* result, ossim_uint32 resLevel)
bool ossimPointCloudImageHandler::getTile(ossimImageData* result, ossim_uint32 resLevel) { // check for all systems go and valid args: if (!m_pch.valid() || !result || (result->getScalarType() != OSSIM_FLOAT32) || (result->getDataObjectStatus() == OSSIM_NULL) || m_gsd.hasNans()) { return false; } // Overviews achieved with GSD setting. This may be too slow. ossimDpt gsd (m_gsd); if (resLevel > 0) getGSD(gsd, resLevel); // Establish the ground and image rects for this tile: const ossimIrect img_tile_rect = result->getImageRectangle(); const ossimIpt tile_offset (img_tile_rect.ul()); const ossim_uint32 tile_width = img_tile_rect.width(); const ossim_uint32 tile_height = img_tile_rect.height(); const ossim_uint32 tile_size = img_tile_rect.area(); ossimGpt gnd_ul, gnd_lr; ossimDpt dpt_ul (img_tile_rect.ul().x - 0.5, img_tile_rect.ul().y - 0.5); ossimDpt dpt_lr (img_tile_rect.lr().x + 0.5, img_tile_rect.lr().y + 0.5); theGeometry->rnToWorld(dpt_ul, resLevel, gnd_ul); theGeometry->rnToWorld(dpt_lr, resLevel, gnd_lr); const ossimGrect gnd_rect (gnd_ul, gnd_lr); // Create array of buckets to store accumulated point data. ossim_uint32 numBands = result->getNumberOfBands(); if (numBands > getNumberOfInputBands()) { // This should never happen; ossimNotify(ossimNotifyLevel_FATAL) << "ossimPointCloudImageHandler::getTile() ERROR: \n" << "More bands were requested than was available from the point cloud source. Returning " << "blank tile." << endl; result->makeBlank(); return false; } std::map<ossim_int32, PcrBucket*> accumulator; // initialize a point block with desired fields as requested in the reader properties ossimPointBlock pointBlock (this); pointBlock.setFieldCode(componentToFieldCode()); m_pch->rewind(); ossimDpt ipt; ossimGpt pos; #define USE_GETBLOCK #ifdef USE_GETBLOCK m_pch->getBlock(gnd_rect, pointBlock); for (ossim_uint32 id=0; id<pointBlock.size(); ++id) { pos = pointBlock[id]->getPosition(); theGeometry->worldToRn(pos, resLevel, ipt); ipt.x = ossim::round<double,double>(ipt.x) - tile_offset.x; ipt.y = ossim::round<double,double>(ipt.y) - tile_offset.y; ossim_int32 bucketIndex = ipt.y*tile_width + ipt.x; if ((bucketIndex >= 0) && (bucketIndex < (ossim_int32)tile_size)) addSample(accumulator, bucketIndex, pointBlock[id]); } #else // using getFileBlock ossim_uint32 numPoints = m_pch->getNumPoints(); if (numPoints > ossimPointCloudHandler::DEFAULT_BLOCK_SIZE) numPoints = ossimPointCloudHandler::DEFAULT_BLOCK_SIZE; // Loop to read all point blocks: do { pointBlock.clear(); m_pch->getNextFileBlock(pointBlock, numPoints); //m_pch->normalizeBlock(pointBlock); for (ossim_uint32 id=0; id<pointBlock.size(); ++id) { // Check that each point in read block is inside the ROI before accumulating it: pos = pointBlock[id]->getPosition(); if (gnd_rect.pointWithin(pos)) { theGeometry->worldToRn(pos, resLevel, ipt); ipt.x = ossim::round<double,double>(ipt.x) - tile_offset.x; ipt.y = ossim::round<double,double>(ipt.y) - tile_offset.y; ossim_int32 bucketIndex = ipt.y*tile_width + ipt.x; if ((bucketIndex >= 0) && (bucketIndex < (ossim_int32)tile_size)) addSample(accumulator, bucketIndex, pointBlock[id]); } } } while (pointBlock.size() == numPoints); #endif // Finished accumulating, need to normalize and fill the tile. // We must always blank out the tile as we may not have a point for every pixel. normalize(accumulator); ossim_float32** buf = new ossim_float32*[numBands]; std::map<ossim_int32, PcrBucket*>::iterator accum_iter; ossim_float32 null_pixel = OSSIM_DEFAULT_NULL_PIX_FLOAT; result->setNullPix(null_pixel); for (ossim_uint32 band = 0; band < numBands; band++) { ossim_uint32 index = 0; buf[band] = result->getFloatBuf(band); for (ossim_uint32 y = 0; y < tile_height; y++) { for (ossim_uint32 x = 0; x < tile_width; x++) { accum_iter = accumulator.find(index); if (accum_iter != accumulator.end()) buf[band][index] = accum_iter->second->m_bucket[band]; else buf[band][index] = null_pixel; ++index; } } } delete [] buf; buf = 0; std::map<ossim_int32, PcrBucket*>::iterator pcr_iter = accumulator.begin(); while (pcr_iter != accumulator.end()) { delete pcr_iter->second; pcr_iter++; } result->validate(); return true; }
void ossimOpjCompressor::initOpjCodingParams( bool jp2, const ossimIpt& tileSize, const ossimIrect& imageRect ) { static const char MODULE[] = "ossimOpjCompressor::initOpjCodingParams"; if ( traceDebug() ) { ossimNotify(ossimNotifyLevel_DEBUG) << MODULE << " entered...\n"; } if ( m_params ) { delete m_params; } m_params = new opj_cparameters_t(); // Set encoding parameters to default values. opj_set_default_encoder_parameters( m_params ); // Output format: 0: J2K, 1: JP2, 2: JPT m_params->cod_format = jp2 ? 1 : 0; // std::string outfile = "test.jp2"; // strncpy(m_params->outfile, outfile.data(), outfile.size()); //--- // Shall we do an Multi-component Transformation(MCT) ? // 0:no_mct;1:rgb->ycc;2:custom mct //--- // Set the tiles size: m_params->cp_tx0 = 0; m_params->cp_ty0 = 0; m_params->cp_tdx = tileSize.x; m_params->cp_tdy = tileSize.y; m_params->tile_size_on = OPJ_TRUE; // No mct. m_params->tcp_mct = 0; //--- // Number of resolutions: // This sets m_levels if not set and // m_params->numresolution. //--- initLevels( imageRect ); // Set the block size. Note 64x64 is the current kakadu default. setCodeBlockSize( 64, 64 ); //--- // Set progression order to use. Note LRCP is the current opj default. // L=layer; R=resolution C=component; P=position // // OPJ_LRCP, OPJ_RLCP, OPJ_RPCL, PCRL, CPRL */ //--- setProgressionOrder( OPJ_LRCP ); // total pixels const ossim_float64 TP = imageRect.area(); if ( traceDebug() ) { ossimNotify(ossimNotifyLevel_DEBUG) << "quality type: " << getQualityTypeString() << endl; } //--- // Rate is a ratio of desired bytes / total bytes. So if you // want 4 bits per pixels it's total_pixels * 4 / 8 or // total_pixels * 4 * 0.125. //--- // Allocation by rate/distortion. m_params->cp_disto_alloc = 1; switch (m_qualityType) { case ossimOpjCompressor::OPJ_NUMERICALLY_LOSSLESS: { // cout << "ossimOpjCompressor::OPJ_NUMERICALLY_LOSSLESS..." << endl; // W5X3 Kernel setReversibleFlag(true); // Tmp drb... m_params->tcp_numlayers = 1; m_params->tcp_rates[0] = 1; #if 0 m_params->tcp_numlayers = 20; m_params->tcp_rates[0] = std::ceil( TP * 0.03125 * 0.125 ); m_params->tcp_rates[1] = std::ceil( TP * 0.0625 * 0.125 ); m_params->tcp_rates[2] = std::ceil( TP * 0.125 * 0.125 ); m_params->tcp_rates[3] = std::ceil( TP * 0.25 * 0.125 ); m_params->tcp_rates[4] = std::ceil( TP * 0.5 * 0.125 ); m_params->tcp_rates[5] = std::ceil( TP * 0.6 * 0.125 ); m_params->tcp_rates[6] = std::ceil( TP * 0.7 * 0.125 ); m_params->tcp_rates[7] = std::ceil( TP * 0.8 * 0.125 ); m_params->tcp_rates[8] = std::ceil( TP * 0.9 * 0.125 ); m_params->tcp_rates[9] = std::ceil( TP * 1.0 * 0.125 ); m_params->tcp_rates[10] = std::ceil( TP * 1.1 * 0.125 ); m_params->tcp_rates[11] = std::ceil( TP * 1.2 * 0.125 ); m_params->tcp_rates[12] = std::ceil( TP * 1.3 * 0.125 ); m_params->tcp_rates[13] = std::ceil( TP * 1.5 * 0.125 ); m_params->tcp_rates[14] = std::ceil( TP * 1.7 * 0.125 ); m_params->tcp_rates[15] = std::ceil( TP * 2.0 * 0.125 ); m_params->tcp_rates[16] = std::ceil( TP * 2.3 * 0.125 ); m_params->tcp_rates[17] = std::ceil( TP * 2.8 * 0.125 ); m_params->tcp_rates[18] = std::ceil( TP * 3.5 * 0.125 ); //--- // Indicate that the final quality layer should include all // compressed bits. //--- // m_params->tcp_rates[19] = OSSIM_DEFAULT_MAX_PIX_SINT32; // KDU_LONG_MAX; m_params->tcp_rates[19] = std::ceil( TP * 4.0 * 0.125 ); #endif break; } case ossimOpjCompressor::OPJ_VISUALLY_LOSSLESS: { // W9X7 kernel: setReversibleFlag(false); m_params->tcp_numlayers = 19; m_params->tcp_rates[0] = std::ceil( TP * 0.03125 * 0.125 ); m_params->tcp_rates[1] = std::ceil( TP * 0.0625 * 0.125 ); m_params->tcp_rates[2] = std::ceil( TP * 0.125 * 0.125 ); m_params->tcp_rates[3] = std::ceil( TP * 0.25 * 0.125 ); m_params->tcp_rates[4] = std::ceil( TP * 0.5 * 0.125 ); m_params->tcp_rates[5] = std::ceil( TP * 0.6 * 0.125 ); m_params->tcp_rates[6] = std::ceil( TP * 0.7 * 0.125 ); m_params->tcp_rates[7] = std::ceil( TP * 0.8 * 0.125 ); m_params->tcp_rates[8] = std::ceil( TP * 0.9 * 0.125 ); m_params->tcp_rates[9] = std::ceil( TP * 1.0 * 0.125 ); m_params->tcp_rates[10] = std::ceil( TP * 1.1 * 0.125 ); m_params->tcp_rates[11] = std::ceil( TP * 1.2 * 0.125 ); m_params->tcp_rates[12] = std::ceil( TP * 1.3 * 0.125 ); m_params->tcp_rates[13] = std::ceil( TP * 1.5 * 0.125 ); m_params->tcp_rates[14] = std::ceil( TP * 1.7 * 0.125 ); m_params->tcp_rates[15] = std::ceil( TP * 2.0 * 0.125 ); m_params->tcp_rates[16] = std::ceil( TP * 2.3 * 0.125 ); m_params->tcp_rates[17] = std::ceil( TP * 2.8 * 0.125 ); m_params->tcp_rates[18] = std::ceil( TP * 3.5 * 0.125 ); break; } case ossimOpjCompressor::OPJ_LOSSY: { // W9X7 kernel: setReversibleFlag(false); m_params->tcp_numlayers = 10; m_params->tcp_rates[0] = std::ceil( TP * 0.03125 * 0.125 ); m_params->tcp_rates[1] = std::ceil( TP * 0.0625 * 0.125 ); m_params->tcp_rates[2] = std::ceil( TP * 0.125 * 0.125 ); m_params->tcp_rates[3] = std::ceil( TP * 0.25 * 0.125 ); m_params->tcp_rates[4] = std::ceil( TP * 0.5 * 0.125 ); m_params->tcp_rates[5] = std::ceil( TP * 0.6 * 0.125 ); m_params->tcp_rates[6] = std::ceil( TP * 0.7 * 0.125 ); m_params->tcp_rates[7] = std::ceil( TP * 0.8 * 0.125 ); m_params->tcp_rates[8] = std::ceil( TP * 0.9 * 0.125 ); m_params->tcp_rates[9] = std::ceil( TP * 1.0 * 0.125 ); break; } default: { m_params->tcp_numlayers = 1; m_params->tcp_rates[0] = 1.0; if (traceDebug()) { ossimNotify(ossimNotifyLevel_WARN) << "unspecified quality type\n"; } } } // matches: switch (m_qualityType) //--- // Set reversible flag, note, this controls the kernel. // W5X3(default) if reversible = true, W9X7 if reversible is false. //--- m_params->irreversible = !m_reversible; if ( traceDebug() ) { ossimNotify(ossimNotifyLevel_DEBUG) << "m_reversible: " << m_reversible << "\nm_levels: " << m_levels << "\n"; ossim::print( ossimNotify(ossimNotifyLevel_DEBUG), *m_params ); } if ( traceDebug() ) { ossimNotify(ossimNotifyLevel_DEBUG) << MODULE << " exited...\n"; } }