tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

ConvolutionFilter.cpp (4138B)


      1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
      2 /* vim: set ts=8 sts=2 et sw=2 tw=80: */
      3 /* This Source Code Form is subject to the terms of the Mozilla Public
      4 * License, v. 2.0. If a copy of the MPL was not distributed with this
      5 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
      6 
      7 #include "ConvolutionFilter.h"
      8 #include "HelpersSkia.h"
      9 #include "SkConvolver.h"
     10 #include "skia/include/core/SkBitmap.h"
     11 
     12 namespace mozilla::gfx {
     13 
     14 ConvolutionFilter::ConvolutionFilter()
     15    : mFilter(MakeUnique<skia::SkConvolutionFilter1D>()) {}
     16 
     17 ConvolutionFilter::~ConvolutionFilter() = default;
     18 
     19 int32_t ConvolutionFilter::MaxFilter() const { return mFilter->maxFilter(); }
     20 
     21 int32_t ConvolutionFilter::NumValues() const { return mFilter->numValues(); }
     22 
     23 bool ConvolutionFilter::GetFilterOffsetAndLength(int32_t aRowIndex,
     24                                                 int32_t* aResultOffset,
     25                                                 int32_t* aResultLength) {
     26  if (aRowIndex >= mFilter->numValues()) {
     27    return false;
     28  }
     29  mFilter->FilterForValue(aRowIndex, aResultOffset, aResultLength);
     30  return true;
     31 }
     32 
     33 void ConvolutionFilter::ConvolveHorizontally(const uint8_t* aSrc, uint8_t* aDst,
     34                                             SurfaceFormat aFormat) {
     35  skia::convolve_horizontally(aSrc, *mFilter, aDst, aFormat);
     36 }
     37 
     38 void ConvolutionFilter::ConvolveVertically(uint8_t* const* aSrc, uint8_t* aDst,
     39                                           int32_t aRowIndex, int32_t aRowSize,
     40                                           SurfaceFormat aFormat) {
     41  MOZ_ASSERT(aRowIndex < mFilter->numValues());
     42 
     43  int32_t filterOffset;
     44  int32_t filterLength;
     45  auto filterValues =
     46      mFilter->FilterForValue(aRowIndex, &filterOffset, &filterLength);
     47  skia::convolve_vertically(filterValues, filterLength, aSrc, aRowSize, aDst,
     48                            aFormat);
     49 }
     50 
     51 bool ConvolutionFilter::ComputeResizeFilter(ResizeMethod aResizeMethod,
     52                                            int32_t aSrcSize,
     53                                            int32_t aDstSize) {
     54  if (aSrcSize < 0 || aDstSize < 0) {
     55    return false;
     56  }
     57 
     58  switch (aResizeMethod) {
     59    case ResizeMethod::BOX:
     60      return mFilter->ComputeFilterValues(skia::SkBoxFilter(), aSrcSize,
     61                                          aDstSize);
     62    case ResizeMethod::LANCZOS3:
     63      return mFilter->ComputeFilterValues(skia::SkLanczosFilter(), aSrcSize,
     64                                          aDstSize);
     65    default:
     66      return false;
     67  }
     68 }
     69 
     70 bool Scale(uint8_t* srcData, int32_t srcWidth, int32_t srcHeight,
     71           int32_t srcStride, uint8_t* dstData, int32_t dstWidth,
     72           int32_t dstHeight, int32_t dstStride, SurfaceFormat format) {
     73  if (!srcData || !dstData || srcWidth < 1 || srcHeight < 1 || dstWidth < 1 ||
     74      dstHeight < 1) {
     75    return false;
     76  }
     77 
     78  switch (format) {
     79    case SurfaceFormat::B8G8R8A8:
     80    case SurfaceFormat::B8G8R8X8:
     81    case SurfaceFormat::R8G8B8A8:
     82    case SurfaceFormat::R8G8B8X8:
     83      // 4 byte formats with alpha at last byte are supported.
     84      break;
     85    case SurfaceFormat::A8:
     86      // 1 byte formats are supported.
     87      break;
     88    default:
     89      return false;
     90  }
     91 
     92  SkPixmap srcPixmap(MakeSkiaImageInfo(IntSize(srcWidth, srcHeight), format),
     93                     srcData, srcStride);
     94 
     95  ConvolutionFilter xFilter;
     96  ConvolutionFilter yFilter;
     97  ConvolutionFilter* xOrYFilter = &xFilter;
     98  bool isSquare = srcWidth == srcHeight && dstWidth == dstHeight;
     99  if (!xFilter.ComputeResizeFilter(ConvolutionFilter::ResizeMethod::LANCZOS3,
    100                                   srcWidth, dstWidth)) {
    101    return false;
    102  }
    103  if (!isSquare) {
    104    if (!yFilter.ComputeResizeFilter(ConvolutionFilter::ResizeMethod::LANCZOS3,
    105                                     srcHeight, dstHeight)) {
    106      return false;
    107    }
    108    xOrYFilter = &yFilter;
    109  }
    110 
    111  return skia::BGRAConvolve2D(
    112      static_cast<const uint8_t*>(srcPixmap.addr()), int(srcPixmap.rowBytes()),
    113      format, xFilter.GetSkiaFilter(), xOrYFilter->GetSkiaFilter(),
    114      int(dstStride), dstData);
    115 }
    116 
    117 }  // namespace mozilla::gfx