Beispiel #1
0
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";
   }
}