<commit_before>// __BEGIN_LICENSE__
// Copyright (C) 2006, 2007 United States Government as represented by
// the Administrator of the National Aeronautics and Space Administration.
// All Rights Reserved.
// __END_LICENSE__


/// \file BlockRasterizeView.h
/// 
/// Defines a wrapper view that causes an image view to be rasterized
/// one block at a time, rather than all at once, and supports multi-
/// threaded rasterization as well as block-level cacheing.  Even when 
/// you don't need those features, in some situations rasterizing one 
/// block at a time can dramatically improve performance by reducing 
/// memory utilization.
///
#ifndef __VW_IMAGE_BLOCKRASTERIZE_H__
#define __VW_IMAGE_BLOCKRASTERIZE_H__

#include <vw/Core/Cache.h>
#include <vw/Image/ImageViewBase.h>
#include <vw/Image/PixelAccessors.h>
#include <vw/Image/Manipulation.h>
#include <vw/Image/BlockProcessor.h>

namespace vw {

  /// A wrapper view that rasterizes its child in blocks.
  template <class ImageT>
  class BlockRasterizeView : public ImageViewBase<BlockRasterizeView<ImageT> > {
  public:
    typedef typename ImageT::pixel_type pixel_type;
    typedef typename ImageT::pixel_type result_type;
    typedef ProceduralPixelAccessor<BlockRasterizeView> pixel_accessor;

    BlockRasterizeView( ImageT const& image,
                        Vector2i const& block_size,
                        int num_threads = 0,
                        bool cache = false )
      : m_child( new ImageT(image) ),
        m_block_size( block_size ),
        m_num_threads( num_threads ),
        m_cache_ptr( cache ? (&vw_system_cache()) : 0 )
    {
      initialize();
    }

    BlockRasterizeView( ImageT const& image,
                        Vector2i const& block_size,
                        int num_threads,
                        Cache &cache )
      : m_child( new ImageT(image) ),
        m_block_size( block_size ),
        m_num_threads( num_threads ),
        m_cache_ptr( &cache )
    {
      initialize();
    }

    inline int32 cols() const { return m_child->cols(); }
    inline int32 rows() const { return m_child->rows(); }
    inline int32 planes() const { return m_child->planes(); }
    inline pixel_accessor origin() const { return pixel_accessor( *this, 0, 0, 0 ); }

    inline result_type operator()( int32 x, int32 y, int32 p = 0 ) const {
#if VW_DEBUG_LEVEL > 1
      vw_out(VerboseDebugMessage, "image") << "ImageResourceView rasterizing pixel (" << x << "," << y << "," << p << ")" << std::endl;
#endif
      if ( m_cache_ptr ) {
        // Early-out optimization for single-block resources
        if( m_block_table->size() == 1 ) {
          return ((*m_block_table)[0])->operator()( x, y, p );
        }
        int32 ix = x/m_block_size.x(), iy = y/m_block_size.y();
        return block(ix,iy)->operator()( x-ix*m_block_size.x(), y - iy*m_block_size.y(), p );
      }
      else return (*m_child)(x,y,p);
    }

    ImageT& child() { return *m_child; }
    ImageT const& child() const { return *m_child; }

    typedef CropView<ImageView<pixel_type> > prerasterize_type;
    inline prerasterize_type prerasterize( BBox2i bbox ) const { 
      ImageView<pixel_type> buf( bbox.width(), bbox.height(), planes() );
      rasterize( buf, bbox );
      return CropView<ImageView<pixel_type> >( buf, BBox2i(-bbox.min().x(),-bbox.min().y(),cols(),rows()) );
    }
    template <class DestT> inline void rasterize( DestT const& dest, BBox2i bbox ) const {
      RasterizeFunctor<DestT> rasterizer( *this, dest, bbox.min() );
      BlockProcessor<RasterizeFunctor<DestT> > process( rasterizer, m_block_size, m_num_threads );
      process(bbox);
    }

  private:
    // Allows RasterizeFunctor to access cache-related members.
    template <class DestT> friend class RasterizeFunctor;

    // These function objects are spawned to rasterize the child image.
    // One functor is created per child thread, and they are called 
    // in succession with bounding boxes that are each contained 
    // within one block.
    template <class DestT>
    class RasterizeFunctor {
      BlockRasterizeView const& m_view;
      DestT const& m_dest;
      Vector2i m_offset;
    public:
      RasterizeFunctor( BlockRasterizeView const& view, DestT const& dest, Vector2i const& offset )
        : m_view(view), m_dest(dest), m_offset(offset) {}
      void operator()( BBox2i const& bbox ) const {
#if VW_DEBUG_LEVEL > 1
        vw_out(VerboseDebugMessage, "image") << "BlockRasterizeView::RasterizeFunctor( " << bbox << " )" << std::endl;
#endif
        if( m_view.m_cache_ptr ) {
          int32 ix=bbox.min().x()/m_view.m_block_size.x(), iy=bbox.min().y()/m_view.m_block_size.y();
#if VW_DEBUG_LEVEL > 1
          int32 maxix=(bbox.max().x()-1)/m_view.m_block_size.x(), maxiy=(bbox.max().y()-1)/m_view.m_block_size.y();
          if( maxix != ix || maxiy != iy ) {
            vw_throw(LogicErr() << "BlockRasterizeView::RasterizeFunctor: bbox spans more than one cache block!");
          }
#endif
          m_view.block(ix,iy)->rasterize( crop( m_dest, bbox-m_offset ), bbox-Vector2i(ix*m_view.m_block_size.x(),iy*m_view.m_block_size.y()) );
        }
        else m_view.child().rasterize( crop( m_dest, bbox-m_offset ), bbox );
      }
    };

    // These objects rasterize a full block of image data to be 
    // stored in the cache.
    class BlockGenerator {
      boost::shared_ptr<ImageT> m_child;
      BBox2i m_bbox;
    public:
      typedef ImageView<pixel_type> value_type;

      BlockGenerator( boost::shared_ptr<ImageT> const& child, BBox2i const& bbox )
        : m_child( child ), m_bbox( bbox ) {}

      size_t size() const {
        return m_bbox.width() * m_bbox.height() * m_child->planes() * sizeof(pixel_type);
      }

      boost::shared_ptr<ImageView<pixel_type> > generate() const {
        boost::shared_ptr<ImageView<pixel_type> > ptr( new ImageView<pixel_type>( m_bbox.width(), m_bbox.height(), m_child->planes() ) );
        m_child->rasterize( *ptr, m_bbox );
        return ptr;
      }
    };

    void initialize() {
      if( m_block_size.x() <= 0 || m_block_size.y() <= 0 ) {
        const int32 default_blocksize = 2*1024*1024; // 2 megabytes<commit_msg>template classes must be declared before they can be friends<commit_after>// __BEGIN_LICENSE__
// Copyright (C) 2006, 2007 United States Government as represented by
// the Administrator of the National Aeronautics and Space Administration.
// All Rights Reserved.
// __END_LICENSE__


/// \file BlockRasterizeView.h
/// 
/// Defines a wrapper view that causes an image view to be rasterized
/// one block at a time, rather than all at once, and supports multi-
/// threaded rasterization as well as block-level cacheing.  Even when 
/// you don't need those features, in some situations rasterizing one 
/// block at a time can dramatically improve performance by reducing 
/// memory utilization.
///
#ifndef __VW_IMAGE_BLOCKRASTERIZE_H__
#define __VW_IMAGE_BLOCKRASTERIZE_H__

#include <vw/Core/Cache.h>
#include <vw/Image/ImageViewBase.h>
#include <vw/Image/PixelAccessors.h>
#include <vw/Image/Manipulation.h>
#include <vw/Image/BlockProcessor.h>

namespace vw {

  /// A wrapper view that rasterizes its child in blocks.
  template <class ImageT>
  class BlockRasterizeView : public ImageViewBase<BlockRasterizeView<ImageT> > {
  public:
    typedef typename ImageT::pixel_type pixel_type;
    typedef typename ImageT::pixel_type result_type;
    typedef ProceduralPixelAccessor<BlockRasterizeView> pixel_accessor;

    BlockRasterizeView( ImageT const& image,
                        Vector2i const& block_size,
                        int num_threads = 0,
                        bool cache = false )
      : m_child( new ImageT(image) ),
        m_block_size( block_size ),
        m_num_threads( num_threads ),
        m_cache_ptr( cache ? (&vw_system_cache()) : 0 )
    {
      initialize();
    }

    BlockRasterizeView( ImageT const& image,
                        Vector2i const& block_size,
                        int num_threads,
                        Cache &cache )
      : m_child( new ImageT(image) ),
        m_block_size( block_size ),
        m_num_threads( num_threads ),
        m_cache_ptr( &cache )
    {
      initialize();
    }

    inline int32 cols() const { return m_child->cols(); }
    inline int32 rows() const { return m_child->rows(); }
    inline int32 planes() const { return m_child->planes(); }
    inline pixel_accessor origin() const { return pixel_accessor( *this, 0, 0, 0 ); }

    inline result_type operator()( int32 x, int32 y, int32 p = 0 ) const {
#if VW_DEBUG_LEVEL > 1
      vw_out(VerboseDebugMessage, "image") << "ImageResourceView rasterizing pixel (" << x << "," << y << "," << p << ")" << std::endl;
#endif
      if ( m_cache_ptr ) {
        // Early-out optimization for single-block resources
        if( m_block_table->size() == 1 ) {
          return ((*m_block_table)[0])->operator()( x, y, p );
        }
        int32 ix = x/m_block_size.x(), iy = y/m_block_size.y();
        return block(ix,iy)->operator()( x-ix*m_block_size.x(), y - iy*m_block_size.y(), p );
      }
      else return (*m_child)(x,y,p);
    }

    ImageT& child() { return *m_child; }
    ImageT const& child() const { return *m_child; }

    typedef CropView<ImageView<pixel_type> > prerasterize_type;
    inline prerasterize_type prerasterize( BBox2i bbox ) const { 
      ImageView<pixel_type> buf( bbox.width(), bbox.height(), planes() );
      rasterize( buf, bbox );
      return CropView<ImageView<pixel_type> >( buf, BBox2i(-bbox.min().x(),-bbox.min().y(),cols(),rows()) );
    }
    template <class DestT> inline void rasterize( DestT const& dest, BBox2i bbox ) const {
      RasterizeFunctor<DestT> rasterizer( *this, dest, bbox.min() );
      BlockProcessor<RasterizeFunctor<DestT> > process( rasterizer, m_block_size, m_num_threads );
      process(bbox);
    }

  private:
    // These function objects are spawned to rasterize the child image.
    // One functor is created per child thread, and they are called 
    // in succession with bounding boxes that are each contained 
    // within one block.
    template <class DestT>
    class RasterizeFunctor {
      BlockRasterizeView const& m_view;
      DestT const& m_dest;
      Vector2i m_offset;
    public:
      RasterizeFunctor( BlockRasterizeView const& view, DestT const& dest, Vector2i const& offset )
        : m_view(view), m_dest(dest), m_offset(offset) {}
      void operator()( BBox2i const& bbox ) const {
#if VW_DEBUG_LEVEL > 1
        vw_out(VerboseDebugMessage, "image") << "BlockRasterizeView::RasterizeFunctor( " << bbox << " )" << std::endl;
#endif
        if( m_view.m_cache_ptr ) {
          int32 ix=bbox.min().x()/m_view.m_block_size.x(), iy=bbox.min().y()/m_view.m_block_size.y();
#if VW_DEBUG_LEVEL > 1
          int32 maxix=(bbox.max().x()-1)/m_view.m_block_size.x(), maxiy=(bbox.max().y()-1)/m_view.m_block_size.y();
          if( maxix != ix || maxiy != iy ) {
            vw_throw(LogicErr() << "BlockRasterizeView::RasterizeFunctor: bbox spans more than one cache block!");
          }
#endif
          m_view.block(ix,iy)->rasterize( crop( m_dest, bbox-m_offset ), bbox-Vector2i(ix*m_view.m_block_size.x(),iy*m_view.m_block_size.y()) );
        }
        else m_view.child().rasterize( crop( m_dest, bbox-m_offset ), bbox );
      }
    };

    // Allows RasterizeFunctor to access cache-related members.
    template <class DestT> friend class RasterizeFunctor;

    // These objects rasterize a full block of image data to be 
    // stored in the cache.
    class BlockGenerator {
      boost::shared_ptr<ImageT> m_child;
      BBox2i m_bbox;
    public:
      typedef ImageView<pixel_type> value_type;

      BlockGenerator( boost::shared_ptr<ImageT> const& child, BBox2i const& bbox )
        : m_child( child ), m_bbox( bbox ) {}

      size_t size() const {
        return m_bbox.width() * m_bbox.height() * m_child->planes() * sizeof(pixel_type);
      }

      boost::shared_ptr<ImageView<pixel_type> > generate() const {
        boost::shared_ptr<ImageView<pixel_type> > ptr( new ImageView<pixel_type>( m_bbox.width(), m_bbox.height(), m_child->planes() ) );
        m_child->rasterize( *ptr, m_bbox );
        return ptr;
      }
    };

    void initialize() {
      if( m_block_size.x() <= 0 || m_block_size.y() <= 0 ) {
        const int32 default_blocksize = 2*1024*1024; // 2 megabytes
{'fraction_non_alphanumeric': 0.12420561499477113, 'fraction_numerical': 0.010296838548789317, 'mean_word_length': 2.9341772151898735, 'pattern_counts': {'":': 0, '<': 115, '<?xml version=': 0, '>': 85, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '3804149', 'n_tokens_mistral': 4218, 'n_tokens_neox': 4037, 'n_words': 1018}