Skip to content
Snippets Groups Projects
Picture.cpp 44.1 KiB
Newer Older
  • Learn to ignore specific revisions
  • Karsten Suehring's avatar
    Karsten Suehring committed
    #if JVET_N0857_TILES_BRICKS
      brickMap             = nullptr;
    #else
    
    Karsten Suehring's avatar
    Karsten Suehring committed
    #endif
    
      cs                   = nullptr;
      m_bIsBorderExtended  = false;
      usedByCurr           = false;
      longTerm             = false;
      reconstructed        = false;
      neededForOutput      = false;
      referenced           = false;
      layer                = std::numeric_limits<uint32_t>::max();
      fieldPic             = false;
      topField             = false;
      for( int i = 0; i < MAX_NUM_CHANNEL_TYPE; i++ )
      {
        m_prevQP[i] = -1;
      }
    
    }
    
    void Picture::create(const ChromaFormat &_chromaFormat, const Size &size, const unsigned _maxCUSize, const unsigned _margin, const bool _decoder)
    {
      UnitArea::operator=( UnitArea( _chromaFormat, Area( Position{ 0, 0 }, size ) ) );
      margin            =  _margin;
      const Area a      = Area( Position(), size );
      M_BUFS( 0, PIC_RECONSTRUCTION ).create( _chromaFormat, a, _maxCUSize, _margin, MEMORY_ALIGN_DEF_SIZE );
    
      if( !_decoder )
      {
        M_BUFS( 0, PIC_ORIGINAL ).    create( _chromaFormat, a );
    
    Taoran Lu's avatar
    Taoran Lu committed
        M_BUFS( 0, PIC_TRUE_ORIGINAL ). create( _chromaFormat, a );
    
      }
    #if !KEEP_PRED_AND_RESI_SIGNALS
    
      m_ctuArea = UnitArea( _chromaFormat, Area( Position{ 0, 0 }, Size( _maxCUSize, _maxCUSize ) ) );
    #endif
    
      m_hashMap.clearAll();
    
    }
    
    void Picture::destroy()
    {
    #if ENABLE_SPLIT_PARALLELISM
    #if ENABLE_WPP_PARALLELISM
      for( int jId = 0; jId < ( PARL_SPLIT_MAX_NUM_THREADS * PARL_WPP_MAX_NUM_THREADS ); jId++ )
    #else
      for( int jId = 0; jId < PARL_SPLIT_MAX_NUM_THREADS; jId++ )
    #endif
    #endif
      for (uint32_t t = 0; t < NUM_PIC_TYPES; t++)
      {
        M_BUFS( jId, t ).destroy();
      }
    
      m_hashMap.clearAll();
    
      if( cs )
      {
        cs->destroy();
        delete cs;
        cs = nullptr;
      }
    
      for( auto &ps : slices )
      {
        delete ps;
      }
      slices.clear();
    
      for( auto &psei : SEIs )
      {
        delete psei;
      }
      SEIs.clear();
    
    
    Karsten Suehring's avatar
    Karsten Suehring committed
    #if JVET_N0857_TILES_BRICKS
      if ( brickMap )
      {
        brickMap->destroy();
        delete brickMap;
        brickMap = nullptr;
      }
    #else
    
      if ( tileMap )
      {
        tileMap->destroy();
        delete tileMap;
        tileMap = nullptr;
      }
    
    Karsten Suehring's avatar
    Karsten Suehring committed
    #endif
    
      if (m_spliceIdx)
      {
        delete[] m_spliceIdx;
        m_spliceIdx = NULL;
      }
    
    }
    
    void Picture::createTempBuffers( const unsigned _maxCUSize )
    {
    #if KEEP_PRED_AND_RESI_SIGNALS
      const Area a( Position{ 0, 0 }, lumaSize() );
    #else
      const Area a = m_ctuArea.Y();
    #endif
    
    #if ENABLE_SPLIT_PARALLELISM
      scheduler.startParallel();
    
      for( int jId = 0; jId < scheduler.getNumPicInstances(); jId++ )
    #endif
      {
        M_BUFS( jId, PIC_PREDICTION                   ).create( chromaFormat, a,   _maxCUSize );
        M_BUFS( jId, PIC_RESIDUAL                     ).create( chromaFormat, a,   _maxCUSize );
    #if ENABLE_SPLIT_PARALLELISM
        if( jId > 0 ) M_BUFS( jId, PIC_RECONSTRUCTION ).create( chromaFormat, Y(), _maxCUSize, margin, MEMORY_ALIGN_DEF_SIZE );
    #endif
      }
    
      if( cs ) cs->rebindPicBufs();
    }
    
    void Picture::destroyTempBuffers()
    {
    #if ENABLE_SPLIT_PARALLELISM
      scheduler.finishParallel();
    
      for( int jId = 0; jId < scheduler.getNumPicInstances(); jId++ )
    #endif
      for( uint32_t t = 0; t < NUM_PIC_TYPES; t++ )
      {
        if( t == PIC_RESIDUAL || t == PIC_PREDICTION ) M_BUFS( jId, t ).destroy();
    #if ENABLE_SPLIT_PARALLELISM
        if( t == PIC_RECONSTRUCTION &&       jId > 0 ) M_BUFS( jId, t ).destroy();
    #endif
      }
    
      if( cs ) cs->rebindPicBufs();
    }
    
           PelBuf     Picture::getOrigBuf(const CompArea &blk)        { return getBuf(blk,  PIC_ORIGINAL); }
    const CPelBuf     Picture::getOrigBuf(const CompArea &blk)  const { return getBuf(blk,  PIC_ORIGINAL); }
           PelUnitBuf Picture::getOrigBuf(const UnitArea &unit)       { return getBuf(unit, PIC_ORIGINAL); }
    const CPelUnitBuf Picture::getOrigBuf(const UnitArea &unit) const { return getBuf(unit, PIC_ORIGINAL); }
           PelUnitBuf Picture::getOrigBuf()                           { return M_BUFS(0,    PIC_ORIGINAL); }
    const CPelUnitBuf Picture::getOrigBuf()                     const { return M_BUFS(0,    PIC_ORIGINAL); }
    
    
    Taoran Lu's avatar
    Taoran Lu committed
           PelBuf     Picture::getOrigBuf(const ComponentID compID)       { return getBuf(compID, PIC_ORIGINAL); }
    const CPelBuf     Picture::getOrigBuf(const ComponentID compID) const { return getBuf(compID, PIC_ORIGINAL); }
           PelUnitBuf Picture::getTrueOrigBuf()                           { return M_BUFS(0, PIC_TRUE_ORIGINAL); }
    const CPelUnitBuf Picture::getTrueOrigBuf()                     const { return M_BUFS(0, PIC_TRUE_ORIGINAL); }
           PelBuf     Picture::getTrueOrigBuf(const CompArea &blk)        { return getBuf(blk, PIC_TRUE_ORIGINAL); }
    const CPelBuf     Picture::getTrueOrigBuf(const CompArea &blk)  const { return getBuf(blk, PIC_TRUE_ORIGINAL); }
    
           PelBuf     Picture::getPredBuf(const CompArea &blk)        { return getBuf(blk,  PIC_PREDICTION); }
    const CPelBuf     Picture::getPredBuf(const CompArea &blk)  const { return getBuf(blk,  PIC_PREDICTION); }
           PelUnitBuf Picture::getPredBuf(const UnitArea &unit)       { return getBuf(unit, PIC_PREDICTION); }
    const CPelUnitBuf Picture::getPredBuf(const UnitArea &unit) const { return getBuf(unit, PIC_PREDICTION); }
    
           PelBuf     Picture::getResiBuf(const CompArea &blk)        { return getBuf(blk,  PIC_RESIDUAL); }
    const CPelBuf     Picture::getResiBuf(const CompArea &blk)  const { return getBuf(blk,  PIC_RESIDUAL); }
           PelUnitBuf Picture::getResiBuf(const UnitArea &unit)       { return getBuf(unit, PIC_RESIDUAL); }
    const CPelUnitBuf Picture::getResiBuf(const UnitArea &unit) const { return getBuf(unit, PIC_RESIDUAL); }
    
           PelBuf     Picture::getRecoBuf(const ComponentID compID)       { return getBuf(compID,                    PIC_RECONSTRUCTION); }
    const CPelBuf     Picture::getRecoBuf(const ComponentID compID) const { return getBuf(compID,                    PIC_RECONSTRUCTION); }
           PelBuf     Picture::getRecoBuf(const CompArea &blk)            { return getBuf(blk,                       PIC_RECONSTRUCTION); }
    const CPelBuf     Picture::getRecoBuf(const CompArea &blk)      const { return getBuf(blk,                       PIC_RECONSTRUCTION); }
           PelUnitBuf Picture::getRecoBuf(const UnitArea &unit)           { return getBuf(unit,                      PIC_RECONSTRUCTION); }
    const CPelUnitBuf Picture::getRecoBuf(const UnitArea &unit)     const { return getBuf(unit,                      PIC_RECONSTRUCTION); }
           PelUnitBuf Picture::getRecoBuf()                               { return M_BUFS(scheduler.getSplitPicId(), PIC_RECONSTRUCTION); }
    const CPelUnitBuf Picture::getRecoBuf()                         const { return M_BUFS(scheduler.getSplitPicId(), PIC_RECONSTRUCTION); }
    
    
    #if JVET_N0415_CTB_ALF
    void Picture::finalInit(const SPS& sps, const PPS& pps, APS** apss)
    #else
    
    Hendry's avatar
    Hendry committed
    void Picture::finalInit(const SPS& sps, const PPS& pps, APS& aps)
    
    Karsten Suehring's avatar
    Karsten Suehring committed
    #if JVET_N0857_TILES_BRICKS
      if( brickMap )
      {
        brickMap->destroy();
        delete brickMap;
        brickMap = nullptr;
      }
    #else
    
      if( tileMap )
      {
        tileMap->destroy();
        delete tileMap;
        tileMap = nullptr;
      }
    
    Karsten Suehring's avatar
    Karsten Suehring committed
    #endif
    
    
      const ChromaFormat chromaFormatIDC = sps.getChromaFormatIdc();
      const int          iWidth = sps.getPicWidthInLumaSamples();
      const int          iHeight = sps.getPicHeightInLumaSamples();
    
      if( cs )
      {
        cs->initStructData();
      }
      else
      {
        cs = new CodingStructure( g_globalUnitCache.cuCache, g_globalUnitCache.puCache, g_globalUnitCache.tuCache );
        cs->sps = &sps;
        cs->create( chromaFormatIDC, Area( 0, 0, iWidth, iHeight ), true );
      }
    
      cs->picture = this;
      cs->slice   = nullptr;  // the slices for this picture have not been set at this point. update cs->slice after swapSliceObject()
      cs->pps     = &pps;
    
    #if JVET_N0415_CTB_ALF
      memcpy(cs->apss, apss, sizeof(cs->apss));
    #else
    
    Hendry's avatar
    Hendry committed
      cs->aps = &aps;
    
    Karsten Suehring's avatar
    Karsten Suehring committed
    #if JVET_N0857_TILES_BRICKS
      brickMap = new BrickMap;
      brickMap->create( sps, pps );
    #else
    
      tileMap = new TileMap;
      tileMap->create( sps, pps );
    
    Karsten Suehring's avatar
    Karsten Suehring committed
    #endif
    
      if (m_spliceIdx == NULL)
      {
        m_ctuNums = cs->pcv->sizeInCtus;
        m_spliceIdx = new int[m_ctuNums];
        memset(m_spliceIdx, 0, m_ctuNums * sizeof(int));
      }
    
    }
    
    void Picture::allocateNewSlice()
    {
      slices.push_back(new Slice);
      Slice& slice = *slices.back();
    
    #if JVET_N0415_CTB_ALF
      memcpy(slice.getAPSs(), cs->apss, sizeof(cs->apss));
    #else
    
    Hendry's avatar
    Hendry committed
      slice.setAPS(cs->aps);
    
      slice.setPPS( cs->pps);
      slice.setSPS( cs->sps);
      if(slices.size()>=2)
      {
        slice.copySliceInfo( slices[slices.size()-2] );
        slice.initSlice();
      }
    }
    
    Slice *Picture::swapSliceObject(Slice * p, uint32_t i)
    {
      p->setSPS(cs->sps);
      p->setPPS(cs->pps);
    
    #if JVET_N0415_CTB_ALF
      p->setAPSs(cs->apss);
    #else
    
    Hendry's avatar
    Hendry committed
      p->setAPS(cs->aps);
    
    
      Slice * pTmp = slices[i];
      slices[i] = p;
      pTmp->setSPS(0);
      pTmp->setPPS(0);
    
    #if JVET_N0415_CTB_ALF
      memset(pTmp->getAPSs(), 0, sizeof(*pTmp->getAPSs())*MAX_NUM_APS);
    #else
    
    Hendry's avatar
    Hendry committed
      pTmp->setAPS(0);
    
      return pTmp;
    }
    
    void Picture::clearSliceBuffer()
    {
      for (uint32_t i = 0; i < uint32_t(slices.size()); i++)
      {
        delete slices[i];
      }
      slices.clear();
    }
    
    #if ENABLE_SPLIT_PARALLELISM
    
    void Picture::finishParallelPart( const UnitArea& area )
    {
      const UnitArea clipdArea = clipArea( area, *this );
      const int      sourceID  = scheduler.getSplitPicId( 0 );
      CHECK( scheduler.getSplitJobId() > 0, "Finish-CU cannot be called from within a mode- or split-parallelized block!" );
    
      // distribute the reconstruction across all of the parallel workers
      for( int tId = 1; tId < scheduler.getNumSplitThreads(); tId++ )
      {
        const int destID = scheduler.getSplitPicId( tId );
    
        M_BUFS( destID, PIC_RECONSTRUCTION ).subBuf( clipdArea ).copyFrom( M_BUFS( sourceID, PIC_RECONSTRUCTION ).subBuf( clipdArea ) );
      }
    }
    
    #if ENABLE_WPP_PARALLELISM
    void Picture::finishCtuPart( const UnitArea& ctuArea )
    {
      const UnitArea clipdArea = clipArea( ctuArea, *this );
      const int      sourceID  = scheduler.getSplitPicId( 0 );
      // distribute the reconstruction across all of the parallel workers
      for( int dataId = 0; dataId < scheduler.getNumPicInstances(); dataId++ )
      {
        if( dataId == sourceID ) continue;
    
        M_BUFS( dataId, PIC_RECONSTRUCTION ).subBuf( clipdArea ).copyFrom( M_BUFS( sourceID, PIC_RECONSTRUCTION ).subBuf( clipdArea ) );
      }
    }
    #endif
    
    #endif
    
    void Picture::extendPicBorder()
    {
      if ( m_bIsBorderExtended )
      {
        return;
      }
    
      for(int comp=0; comp<getNumberValidComponents( cs->area.chromaFormat ); comp++)
      {
        ComponentID compID = ComponentID( comp );
        PelBuf p = M_BUFS( 0, PIC_RECONSTRUCTION ).get( compID );
        Pel *piTxt = p.bufAt(0,0);
        int xmargin = margin >> getComponentScaleX( compID, cs->area.chromaFormat );
        int ymargin = margin >> getComponentScaleY( compID, cs->area.chromaFormat );
    
        Pel*  pi = piTxt;
        // do left and right margins
    
        if (cs->sps->getWrapAroundEnabledFlag())
    
          int xoffset = cs->sps->getWrapAroundOffset() >> getComponentScaleX( compID, cs->area.chromaFormat );
    
    Philippe Hanhart's avatar
    Philippe Hanhart committed
          for (int y = 0; y < p.height; y++)
    
    Philippe Hanhart's avatar
    Philippe Hanhart committed
            for (int x = 0; x < xmargin; x++ )
            {
    
              pi[ -x - 1       ] = pi[ -x - 1       + xoffset ];
    
    Philippe Hanhart's avatar
    Philippe Hanhart committed
              pi[  p.width + x ] = pi[  p.width + x - xoffset ];
            }
            pi += p.stride;
    
    Philippe Hanhart's avatar
    Philippe Hanhart committed
        else
        {
          for (int y = 0; y < p.height; y++)
          {
            for (int x = 0; x < xmargin; x++ )
            {
              pi[ -xmargin + x ] = pi[0];
              pi[  p.width + x ] = pi[p.width-1];
            }
            pi += p.stride;
          }
        }
    
    
        // pi is now the (0,height) (bottom left of image within bigger picture
        pi -= (p.stride + xmargin);
        // pi is now the (-marginX, height-1)
        for (int y = 0; y < ymargin; y++ )
        {
          ::memcpy( pi + (y+1)*p.stride, pi, sizeof(Pel)*(p.width + (xmargin << 1)));
        }
    
        // pi is still (-marginX, height-1)
        pi -= ((p.height-1) * p.stride);
        // pi is now (-marginX, 0)
        for (int y = 0; y < ymargin; y++ )
        {
          ::memcpy( pi - (y+1)*p.stride, pi, sizeof(Pel)*(p.width + (xmargin<<1)) );
        }
      }
    
      m_bIsBorderExtended = true;
    }
    
    PelBuf Picture::getBuf( const ComponentID compID, const PictureType &type )
    {
    
      return M_BUFS( ( type == PIC_ORIGINAL || type == PIC_TRUE_ORIGINAL ) ? 0 : scheduler.getSplitPicId(), type ).getBuf( compID );
    
    }
    
    const CPelBuf Picture::getBuf( const ComponentID compID, const PictureType &type ) const
    {
    
      return M_BUFS( ( type == PIC_ORIGINAL || type == PIC_TRUE_ORIGINAL ) ? 0 : scheduler.getSplitPicId(), type ).getBuf( compID );
    
    }
    
    PelBuf Picture::getBuf( const CompArea &blk, const PictureType &type )
    {
      if( !blk.valid() )
      {
        return PelBuf();
      }
    
    #if ENABLE_SPLIT_PARALLELISM
    
      const int jId = ( type == PIC_ORIGINAL || type == PIC_TRUE_ORIGINAL ) ? 0 : scheduler.getSplitPicId();
    
    
    #endif
    #if !KEEP_PRED_AND_RESI_SIGNALS
      if( type == PIC_RESIDUAL || type == PIC_PREDICTION )
      {
        CompArea localBlk = blk;
        localBlk.x &= ( cs->pcv->maxCUWidthMask  >> getComponentScaleX( blk.compID, blk.chromaFormat ) );
        localBlk.y &= ( cs->pcv->maxCUHeightMask >> getComponentScaleY( blk.compID, blk.chromaFormat ) );
    
        return M_BUFS( jId, type ).getBuf( localBlk );
      }
    #endif
    
      return M_BUFS( jId, type ).getBuf( blk );
    }
    
    const CPelBuf Picture::getBuf( const CompArea &blk, const PictureType &type ) const
    {
      if( !blk.valid() )
      {
        return PelBuf();
      }
    
    #if ENABLE_SPLIT_PARALLELISM
    
      const int jId = ( type == PIC_ORIGINAL || type == PIC_TRUE_ORIGINAL ) ? 0 : scheduler.getSplitPicId();
    
    
    #endif
    #if !KEEP_PRED_AND_RESI_SIGNALS
      if( type == PIC_RESIDUAL || type == PIC_PREDICTION )
      {
        CompArea localBlk = blk;
        localBlk.x &= ( cs->pcv->maxCUWidthMask  >> getComponentScaleX( blk.compID, blk.chromaFormat ) );
        localBlk.y &= ( cs->pcv->maxCUHeightMask >> getComponentScaleY( blk.compID, blk.chromaFormat ) );
    
        return M_BUFS( jId, type ).getBuf( localBlk );
      }
    #endif
    
      return M_BUFS( jId, type ).getBuf( blk );
    }
    
    PelUnitBuf Picture::getBuf( const UnitArea &unit, const PictureType &type )
    {
      if( chromaFormat == CHROMA_400 )
      {
        return PelUnitBuf( chromaFormat, getBuf( unit.Y(), type ) );
      }
      else
      {
        return PelUnitBuf( chromaFormat, getBuf( unit.Y(), type ), getBuf( unit.Cb(), type ), getBuf( unit.Cr(), type ) );
      }
    }
    
    const CPelUnitBuf Picture::getBuf( const UnitArea &unit, const PictureType &type ) const
    {
      if( chromaFormat == CHROMA_400 )
      {
        return CPelUnitBuf( chromaFormat, getBuf( unit.Y(), type ) );
      }
      else
      {
        return CPelUnitBuf( chromaFormat, getBuf( unit.Y(), type ), getBuf( unit.Cb(), type ), getBuf( unit.Cr(), type ) );
      }
    }
    
    Pel* Picture::getOrigin( const PictureType &type, const ComponentID compID ) const
    {
    #if ENABLE_SPLIT_PARALLELISM
    
      const int jId = ( type == PIC_ORIGINAL || type == PIC_TRUE_ORIGINAL ) ? 0 : scheduler.getSplitPicId();
    
    
    void Picture::createSpliceIdx(int nums)
    {
      m_ctuNums = nums;
      m_spliceIdx = new int[m_ctuNums];
      memset(m_spliceIdx, 0, m_ctuNums * sizeof(int));
    }
    
    bool Picture::getSpliceFull()
    {
      int count = 0;
      for (int i = 0; i < m_ctuNums; i++)
      {
        if (m_spliceIdx[i] != 0)
          count++;
      }
      if (count < m_ctuNums * 0.25)
        return false;
      return true;
    }
    
    
    void Picture::addPictureToHashMapForInter()
    {
      int picWidth = slices[0]->getSPS()->getPicWidthInLumaSamples();
      int picHeight = slices[0]->getSPS()->getPicHeightInLumaSamples();
    
      uint32_t* blockHashValues[2][2];
    
      bool* bIsBlockSame[2][3];
    
      for (int i = 0; i < 2; i++)
      {
        for (int j = 0; j < 2; j++)
        {
    
          blockHashValues[i][j] = new uint32_t[picWidth*picHeight];
    
        }
    
        for (int j = 0; j < 3; j++)
        {
          bIsBlockSame[i][j] = new bool[picWidth*picHeight];
        }
      }
    
    #if JVET_N0247_HASH_IMPROVE
      m_hashMap.create(picWidth, picHeight);
    #else
    
      m_hashMap.create();
    
      m_hashMap.generateBlock2x2HashValue(getOrigBuf(), picWidth, picHeight, slices[0]->getSPS()->getBitDepths(), blockHashValues[0], bIsBlockSame[0]);//2x2
      m_hashMap.generateBlockHashValue(picWidth, picHeight, 4, 4, blockHashValues[0], blockHashValues[1], bIsBlockSame[0], bIsBlockSame[1]);//4x4
      m_hashMap.addToHashMapByRowWithPrecalData(blockHashValues[1], bIsBlockSame[1][2], picWidth, picHeight, 4, 4);
    
    #if !JVET_N0247_HASH_IMPROVE
    
      m_hashMap.generateRectangleHashValue(picWidth, picHeight, 8, 4, blockHashValues[1], blockHashValues[0], bIsBlockSame[1], bIsBlockSame[0]);//8x4
      m_hashMap.addToHashMapByRowWithPrecalData(blockHashValues[0], bIsBlockSame[0][2], picWidth, picHeight, 8, 4);
    
      m_hashMap.generateRectangleHashValue(picWidth, picHeight, 4, 8, blockHashValues[1], blockHashValues[0], bIsBlockSame[1], bIsBlockSame[0]);//4x8
      m_hashMap.addToHashMapByRowWithPrecalData(blockHashValues[0], bIsBlockSame[0][2], picWidth, picHeight, 4, 8);
    
    
      m_hashMap.generateBlockHashValue(picWidth, picHeight, 8, 8, blockHashValues[1], blockHashValues[0], bIsBlockSame[1], bIsBlockSame[0]);//8x8
      m_hashMap.addToHashMapByRowWithPrecalData(blockHashValues[0], bIsBlockSame[0][2], picWidth, picHeight, 8, 8);
    
      m_hashMap.generateBlockHashValue(picWidth, picHeight, 16, 16, blockHashValues[0], blockHashValues[1], bIsBlockSame[0], bIsBlockSame[1]);//16x16
      m_hashMap.addToHashMapByRowWithPrecalData(blockHashValues[1], bIsBlockSame[1][2], picWidth, picHeight, 16, 16);
    
      m_hashMap.generateBlockHashValue(picWidth, picHeight, 32, 32, blockHashValues[1], blockHashValues[0], bIsBlockSame[1], bIsBlockSame[0]);//32x32
      m_hashMap.addToHashMapByRowWithPrecalData(blockHashValues[0], bIsBlockSame[0][2], picWidth, picHeight, 32, 32);
    
      m_hashMap.generateBlockHashValue(picWidth, picHeight, 64, 64, blockHashValues[0], blockHashValues[1], bIsBlockSame[0], bIsBlockSame[1]);//64x64
      m_hashMap.addToHashMapByRowWithPrecalData(blockHashValues[1], bIsBlockSame[1][2], picWidth, picHeight, 64, 64);
    
      m_hashMap.setInitial();
    
      for (int i = 0; i < 2; i++)
      {
        for (int j = 0; j < 2; j++)
        {
          delete[] blockHashValues[i][j];
        }
    
        for (int j = 0; j < 3; j++)
        {
          delete[] bIsBlockSame[i][j];
        }
      }
    }