LCOV - code coverage report
Current view: top level - eq - roiEmptySpaceFinder.cpp (source / functions) Hit Total Coverage
Test: Equalizer Lines: 1 106 0.9 %
Date: 2017-12-16 05:07:20 Functions: 2 8 25.0 %

          Line data    Source code
       1             : 
       2             : /* Copyright (c) 2009, Maxim Makhinya
       3             :  *               2010-2013, Stefan Eilemann <eile@eyescale.ch>
       4             :  *
       5             :  * This library is free software; you can redistribute it and/or modify it under
       6             :  * the terms of the GNU Lesser General Public License version 2.1 as published
       7             :  * by the Free Software Foundation.
       8             :  *
       9             :  * This library is distributed in the hope that it will be useful, but WITHOUT
      10             :  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
      11             :  * FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public License for more
      12             :  * details.
      13             :  *
      14             :  * You should have received a copy of the GNU Lesser General Public License
      15             :  * along with this library; if not, write to the Free Software Foundation, Inc.,
      16             :  * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
      17             :  */
      18             : 
      19             : #include "roiEmptySpaceFinder.h"
      20             : 
      21             : #include <eq/fabric/pixelViewport.h>
      22             : 
      23             : namespace eq
      24             : {
      25           0 : void ROIEmptySpaceFinder::_resize(const int32_t w, const int32_t h)
      26             : {
      27           0 :     _w = w;
      28           0 :     _h = h;
      29             : 
      30           0 :     _mask = 0;
      31             : 
      32           0 :     if (static_cast<int32_t>(_data.size()) < w * h)
      33           0 :         _data.resize(w * h);
      34             : 
      35           0 :     setLimits((w - 1) * (h - 1), 1.0);
      36           0 : }
      37             : 
      38           0 : void ROIEmptySpaceFinder::update(const uint8_t* mask, const int32_t w,
      39             :                                  const int32_t h)
      40             : {
      41           0 :     _resize(w, h);
      42             : 
      43           0 :     _mask = mask;
      44           0 :     const uint8_t* s = mask + _w * (_h - 1);
      45           0 :     uint16_t* d = &_data[_w * (_h - 1)];
      46             : 
      47             :     // First element
      48           0 :     d[_w - 1] = s[_w - 1] > 0 ? 1 : 0;
      49             : 
      50             :     // First raw
      51           0 :     for (int32_t x = _w - 2; x >= 0; x--)
      52           0 :         d[x] = d[x + 1] + (s[x] > 0 ? 1 : 0);
      53             : 
      54             :     // All other raws
      55           0 :     for (int32_t y = 1; y < _h; y++)
      56             :     {
      57           0 :         const uint16_t* dp = d; // previous calculated raw
      58           0 :         s -= _w;
      59           0 :         d -= _w;
      60           0 :         uint16_t rawSum = 0;
      61           0 :         for (int32_t x = _w - 1; x >= 0; x--)
      62             :         {
      63           0 :             rawSum += s[x] > 0 ? 1 : 0;
      64           0 :             d[x] = dp[x] + rawSum;
      65             :         }
      66             :     }
      67           0 : }
      68             : 
      69           0 : inline uint16_t ROIEmptySpaceFinder::_getArea(const int32_t x, const int32_t y,
      70             :                                               const int32_t w,
      71             :                                               const int32_t h) const
      72             : {
      73           0 :     return _getArea(w, h, &_data[0] + y * _w + x);
      74             : }
      75             : 
      76           0 : inline uint16_t ROIEmptySpaceFinder::_getArea(const int32_t w, const int32_t h,
      77             :                                               const uint16_t* data) const
      78             : {
      79           0 :     const uint16_t* data_ = data + h * _w;
      80           0 :     return *data - data[w] - *data_ + data_[w];
      81             : }
      82             : 
      83           0 : bool ROIEmptySpaceFinder::_updateMaximalEmptyRegion(
      84             :     const int32_t x, const int32_t y, const int32_t w, const int32_t h,
      85             :     PixelViewport& pvp, const uint16_t* data) const
      86             : {
      87           0 :     uint16_t maxArea = pvp.w * pvp.h;
      88           0 :     bool updated = false;
      89           0 :     int32_t maxW = 0;
      90           0 :     int32_t maxH = 0;
      91             : 
      92             :     // find biggest diagonal
      93           0 :     int32_t cwh = 2;
      94           0 :     while (cwh <= w && cwh <= h && _getArea(cwh, cwh, data) == 0)
      95           0 :         cwh++;
      96             : 
      97           0 :     cwh--;
      98             : 
      99           0 :     if (cwh * cwh > maxArea)
     100             :     {
     101           0 :         maxArea = cwh * cwh;
     102           0 :         maxW = cwh;
     103           0 :         maxH = cwh;
     104           0 :         updated = true;
     105             :     }
     106             : 
     107             :     // check parallelepipids
     108           0 :     if (cwh * w > maxArea)
     109             :     {
     110           0 :         int32_t ch = cwh;
     111           0 :         for (int32_t cw = cwh + 1; cw <= w; cw++)
     112             :         {
     113           0 :             while (_getArea(cw, ch, data) != 0)
     114             :             {
     115           0 :                 ch--;
     116           0 :                 if (ch == 0)
     117             :                 {
     118           0 :                     cw = w + 1;
     119           0 :                     break;
     120             :                 }
     121             :             }
     122           0 :             if (cw * ch > maxArea)
     123             :             {
     124           0 :                 maxArea = cw * ch;
     125           0 :                 maxW = cw;
     126           0 :                 maxH = ch;
     127           0 :                 updated = true;
     128             :             }
     129             :         }
     130             :     }
     131             : 
     132           0 :     if (cwh * h > maxArea)
     133             :     {
     134           0 :         int32_t cw = cwh;
     135           0 :         for (int32_t ch = cwh + 1; ch <= h; ch++)
     136             :         {
     137           0 :             while (_getArea(cw, ch, data) != 0)
     138             :             {
     139           0 :                 cw--;
     140           0 :                 if (cw == 0)
     141             :                 {
     142           0 :                     ch = h + 1;
     143           0 :                     break;
     144             :                 }
     145             :             }
     146           0 :             if (cw * ch > maxArea)
     147             :             {
     148           0 :                 maxArea = cw * ch;
     149           0 :                 maxW = cw;
     150           0 :                 maxH = ch;
     151           0 :                 updated = true;
     152             :             }
     153             :         }
     154             :     }
     155             : 
     156           0 :     if (updated)
     157           0 :         pvp = PixelViewport(x, y, maxW, maxH);
     158             : 
     159           0 :     return updated;
     160             : }
     161             : 
     162           0 : PixelViewport ROIEmptySpaceFinder::getLargestEmptyArea(
     163             :     const PixelViewport& pvp) const
     164             : {
     165           0 :     LBASSERT(pvp.x >= 0 && pvp.w > 0 && pvp.y >= 0 && pvp.h > 0 &&
     166             :              pvp.x + pvp.w < _w && pvp.y + pvp.h < _h);
     167             : 
     168           0 :     LBASSERT(_mask);
     169             : 
     170           0 :     PixelViewport res(pvp.x, pvp.y, 0, 0);
     171             : 
     172           0 :     uint16_t maxArea = _getArea(pvp.x, pvp.y, pvp.w, pvp.h);
     173           0 :     const uint16_t minRel = static_cast<uint16_t>(pvp.w * pvp.h * _limRel);
     174             : 
     175             :     // totally empty
     176           0 :     if (maxArea == 0)
     177           0 :         return pvp;
     178             : 
     179             :     // totally full
     180           0 :     if (maxArea == pvp.w * pvp.h)
     181           0 :         return res;
     182             : 
     183             :     // over limit
     184           0 :     if (maxArea < _limAbs || maxArea < minRel)
     185           0 :         return res;
     186             : 
     187             :     // search for biggest empty pvp
     188           0 :     const uint16_t* data = &_data[0] + pvp.y * _w;
     189           0 :     const uint8_t* m = _mask + pvp.y * _w;
     190             : 
     191           0 :     maxArea = 0;
     192             : 
     193           0 :     for (int y = pvp.y, h = pvp.h; h > 0; y++, h--)
     194             :     {
     195             :         // skeep if found area bigger than the rest of image
     196           0 :         if (h * pvp.w - _getArea(pvp.x, y, pvp.w, h) <= maxArea)
     197           0 :             break;
     198             : 
     199           0 :         for (int x = pvp.x, w = pvp.w; w > 0; x++, w--)
     200             :         {
     201             :             // skeep non empty blocks
     202           0 :             if (m[x] != 0)
     203           0 :                 continue;
     204             : 
     205             :             // skeep if found area bigger than the rest of image
     206           0 :             if (w * h - _getArea(w, h, data + x) <= maxArea)
     207             :             {
     208           0 :                 w = 0;
     209           0 :                 continue;
     210             :             }
     211             : 
     212           0 :             if (_updateMaximalEmptyRegion(x, y, w, h, res, data + x))
     213           0 :                 maxArea = res.w * res.h;
     214             :         }
     215           0 :         m += _w;
     216           0 :         data += _w;
     217             :     }
     218             : 
     219           0 :     const uint16_t curArea = res.w * res.h;
     220           0 :     if (curArea < _limAbs || curArea < minRel)
     221           0 :         return PixelViewport(pvp.x, pvp.y, 0, 0);
     222             : 
     223           0 :     return res;
     224             : }
     225          30 : }

Generated by: LCOV version 1.11