LCOV - code coverage report
Current view: top level - gfx/2d - ImageScaling.cpp (source / functions) Hit Total Coverage
Test: output.info Lines: 0 114 0.0 %
Date: 2017-07-14 16:53:18 Functions: 0 9 0.0 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /* -*- Mode: C++; tab-width: 20; indent-tabs-mode: nil; c-basic-offset: 2 -*-
       2             :  * This Source Code Form is subject to the terms of the Mozilla Public
       3             :  * License, v. 2.0. If a copy of the MPL was not distributed with this
       4             :  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
       5             : 
       6             : #include "ImageScaling.h"
       7             : #include "2D.h"
       8             : #include "DataSurfaceHelpers.h"
       9             : 
      10             : #include <math.h>
      11             : #include <algorithm>
      12             : 
      13             : using namespace std;
      14             : 
      15             : namespace mozilla {
      16             : namespace gfx {
      17             : 
      18           0 : inline uint32_t Avg2x2(uint32_t a, uint32_t b, uint32_t c, uint32_t d)
      19             : {
      20             :   // Prepare half-adder work
      21           0 :   uint32_t sum = a ^ b ^ c;
      22           0 :   uint32_t carry = (a & b) | (a & c) | (b & c);
      23             : 
      24             :   // Before shifting, mask lower order bits of each byte to avoid underflow.
      25           0 :   uint32_t mask = 0xfefefefe;
      26             : 
      27             :   // Add d to sum and divide by 2.
      28           0 :   sum = (((sum ^ d) & mask) >> 1) + (sum & d);
      29             : 
      30             :   // Sum is now shifted into place relative to carry, add them together.
      31           0 :   return (((sum ^ carry) & mask) >> 1) + (sum & carry);
      32             : }
      33             : 
      34           0 : inline uint32_t Avg2(uint32_t a, uint32_t b)
      35             : {
      36             :   // Prepare half-adder work
      37           0 :   uint32_t sum = a ^ b;
      38           0 :   uint32_t carry = (a & b);
      39             : 
      40             :   // Before shifting, mask lower order bits of each byte to avoid underflow.
      41           0 :   uint32_t mask = 0xfefefefe;
      42             : 
      43             :   // Add d to sum and divide by 2.
      44           0 :   return ((sum & mask) >> 1) + carry;
      45             : }
      46             : 
      47             : void
      48           0 : ImageHalfScaler::ScaleForSize(const IntSize &aSize)
      49             : {
      50           0 :   uint32_t horizontalDownscales = 0;
      51           0 :   uint32_t verticalDownscales = 0;
      52             : 
      53           0 :   IntSize scaleSize = mOrigSize;
      54           0 :   while ((scaleSize.height / 2) > aSize.height) {
      55           0 :     verticalDownscales++;
      56           0 :     scaleSize.height /= 2;
      57             :   }
      58             : 
      59           0 :   while ((scaleSize.width / 2) > aSize.width) {
      60           0 :     horizontalDownscales++;
      61           0 :     scaleSize.width /= 2;
      62             :   }
      63             : 
      64           0 :   if (scaleSize == mOrigSize) {
      65           0 :     return;
      66             :   }
      67             : 
      68           0 :   delete [] mDataStorage;
      69             : 
      70           0 :   IntSize internalSurfSize;
      71           0 :   internalSurfSize.width = max(scaleSize.width, mOrigSize.width / 2);
      72           0 :   internalSurfSize.height = max(scaleSize.height, mOrigSize.height / 2);
      73             : 
      74           0 :   size_t bufLen = 0;
      75           0 :   mStride = GetAlignedStride<16>(internalSurfSize.width, 4);
      76           0 :   if (mStride > 0) {
      77             :     // Allocate 15 bytes extra to make sure we can get 16 byte alignment. We
      78             :     // should add tools for this, see bug 751696.
      79           0 :     bufLen = BufferSizeFromStrideAndHeight(mStride, internalSurfSize.height, 15);
      80             :   }
      81             : 
      82           0 :   if (bufLen == 0) {
      83           0 :     mSize.SizeTo(0, 0);
      84           0 :     mDataStorage = nullptr;
      85           0 :     return;
      86             :   }
      87           0 :   mDataStorage = new uint8_t[bufLen];
      88             : 
      89           0 :   if (uintptr_t(mDataStorage) % 16) {
      90             :     // Our storage does not start at a 16-byte boundary. Make sure mData does!
      91           0 :     mData = (uint8_t*)(uintptr_t(mDataStorage) +
      92           0 :       (16 - (uintptr_t(mDataStorage) % 16)));
      93             :   } else {
      94           0 :     mData = mDataStorage;
      95             :   }
      96             : 
      97           0 :   mSize = scaleSize;
      98             : 
      99             :   /* The surface we sample from might not be even sized, if it's not we will
     100             :    * ignore the last row/column. This means we lose some data but it keeps the
     101             :    * code very simple. There's also no perfect answer that provides a better
     102             :    * solution.
     103             :    */
     104           0 :   IntSize currentSampledSize = mOrigSize;
     105           0 :   uint32_t currentSampledStride = mOrigStride;
     106           0 :   uint8_t *currentSampledData = mOrigData;
     107             :   
     108           0 :   while (verticalDownscales && horizontalDownscales) {
     109           0 :     if (currentSampledSize.width % 2) {
     110           0 :       currentSampledSize.width -= 1;
     111             :     }
     112           0 :     if (currentSampledSize.height % 2) {
     113           0 :       currentSampledSize.height -= 1;
     114             :     }
     115             : 
     116           0 :     HalfImage2D(currentSampledData, currentSampledStride, currentSampledSize,
     117           0 :                 mData, mStride);
     118             : 
     119           0 :     verticalDownscales--;
     120           0 :     horizontalDownscales--;
     121           0 :     currentSampledSize.width /= 2;
     122           0 :     currentSampledSize.height /= 2;
     123           0 :     currentSampledData = mData;
     124           0 :     currentSampledStride = mStride;
     125             :   }
     126             : 
     127           0 :   while (verticalDownscales) {
     128           0 :     if (currentSampledSize.height % 2) {
     129           0 :       currentSampledSize.height -= 1;
     130             :     }
     131             : 
     132           0 :     HalfImageVertical(currentSampledData, currentSampledStride, currentSampledSize,
     133           0 :                       mData, mStride);
     134             : 
     135           0 :     verticalDownscales--;
     136           0 :     currentSampledSize.height /= 2;
     137           0 :     currentSampledData = mData;
     138           0 :     currentSampledStride = mStride;
     139             :   }
     140             : 
     141             : 
     142           0 :   while (horizontalDownscales) {
     143           0 :     if (currentSampledSize.width % 2) {
     144           0 :       currentSampledSize.width -= 1;
     145             :     }
     146             : 
     147           0 :     HalfImageHorizontal(currentSampledData, currentSampledStride, currentSampledSize,
     148           0 :                         mData, mStride);
     149             : 
     150           0 :     horizontalDownscales--;
     151           0 :     currentSampledSize.width /= 2;
     152           0 :     currentSampledData = mData;
     153           0 :     currentSampledStride = mStride;
     154             :   }
     155             : }
     156             : 
     157             : void
     158           0 : ImageHalfScaler::HalfImage2D(uint8_t *aSource, int32_t aSourceStride,
     159             :                              const IntSize &aSourceSize, uint8_t *aDest,
     160             :                              uint32_t aDestStride)
     161             : {
     162             : #ifdef USE_SSE2
     163           0 :   if (Factory::HasSSE2()) {
     164           0 :     HalfImage2D_SSE2(aSource, aSourceStride, aSourceSize, aDest, aDestStride);
     165             :   } else
     166             : #endif
     167             :   {
     168           0 :     HalfImage2D_C(aSource, aSourceStride, aSourceSize, aDest, aDestStride);
     169             :   }
     170           0 : }
     171             : 
     172             : void
     173           0 : ImageHalfScaler::HalfImageVertical(uint8_t *aSource, int32_t aSourceStride,
     174             :                                    const IntSize &aSourceSize, uint8_t *aDest,
     175             :                                    uint32_t aDestStride)
     176             : {
     177             : #ifdef USE_SSE2
     178           0 :   if (Factory::HasSSE2()) {
     179           0 :     HalfImageVertical_SSE2(aSource, aSourceStride, aSourceSize, aDest, aDestStride);
     180             :   } else
     181             : #endif
     182             :   {
     183           0 :     HalfImageVertical_C(aSource, aSourceStride, aSourceSize, aDest, aDestStride);
     184             :   }
     185           0 : }
     186             : 
     187             : void
     188           0 : ImageHalfScaler::HalfImageHorizontal(uint8_t *aSource, int32_t aSourceStride,
     189             :                                      const IntSize &aSourceSize, uint8_t *aDest,
     190             :                                      uint32_t aDestStride)
     191             : {
     192             : #ifdef USE_SSE2
     193           0 :   if (Factory::HasSSE2()) {
     194           0 :     HalfImageHorizontal_SSE2(aSource, aSourceStride, aSourceSize, aDest, aDestStride);
     195             :   } else
     196             : #endif
     197             :   {
     198           0 :     HalfImageHorizontal_C(aSource, aSourceStride, aSourceSize, aDest, aDestStride);
     199             :   }
     200           0 : }
     201             : 
     202             : void
     203           0 : ImageHalfScaler::HalfImage2D_C(uint8_t *aSource, int32_t aSourceStride,
     204             :                                const IntSize &aSourceSize, uint8_t *aDest,
     205             :                                uint32_t aDestStride)
     206             : {
     207           0 :   for (int y = 0; y < aSourceSize.height; y += 2) {
     208           0 :     uint32_t *storage = (uint32_t*)(aDest + (y / 2) * aDestStride);
     209           0 :     for (int x = 0; x < aSourceSize.width; x += 2) {
     210           0 :       uint8_t *upperRow = aSource + (y * aSourceStride + x * 4);
     211           0 :       uint8_t *lowerRow = aSource + ((y + 1) * aSourceStride + x * 4);
     212             : 
     213           0 :       *storage++ = Avg2x2(*(uint32_t*)upperRow, *((uint32_t*)upperRow + 1),
     214           0 :                           *(uint32_t*)lowerRow, *((uint32_t*)lowerRow + 1));
     215             :     }
     216             :   }
     217           0 : }
     218             : 
     219             : void
     220           0 : ImageHalfScaler::HalfImageVertical_C(uint8_t *aSource, int32_t aSourceStride,
     221             :                                      const IntSize &aSourceSize, uint8_t *aDest,
     222             :                                      uint32_t aDestStride)
     223             : {
     224           0 :   for (int y = 0; y < aSourceSize.height; y += 2) {
     225           0 :     uint32_t *storage = (uint32_t*)(aDest + (y / 2) * aDestStride);
     226           0 :     for (int x = 0; x < aSourceSize.width; x++) {
     227           0 :       uint32_t *upperRow = (uint32_t*)(aSource + (y * aSourceStride + x * 4));
     228           0 :       uint32_t *lowerRow = (uint32_t*)(aSource + ((y + 1) * aSourceStride + x * 4));
     229             : 
     230           0 :       *storage++ = Avg2(*upperRow, *lowerRow);
     231             :     }
     232             :   }
     233           0 : }
     234             : 
     235             : void
     236           0 : ImageHalfScaler::HalfImageHorizontal_C(uint8_t *aSource, int32_t aSourceStride,
     237             :                                        const IntSize &aSourceSize, uint8_t *aDest,
     238             :                                        uint32_t aDestStride)
     239             : {
     240           0 :   for (int y = 0; y < aSourceSize.height; y++) {
     241           0 :     uint32_t *storage = (uint32_t*)(aDest + y * aDestStride);
     242           0 :     for (int x = 0; x < aSourceSize.width;  x+= 2) {
     243           0 :       uint32_t *pixels = (uint32_t*)(aSource + (y * aSourceStride + x * 4));
     244             : 
     245           0 :       *storage++ = Avg2(*pixels, *(pixels + 1));
     246             :     }
     247             :   }
     248           0 : }
     249             : 
     250             : } // namespace gfx
     251             : } // namespace mozilla

Generated by: LCOV version 1.13