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/. */
7 #include "ConvolutionFilter.h"
8 #include "HelpersSkia.h"
9 #include "SkConvolver.h"
10 #include "skia/include/core/SkBitmap.h"
12 namespace mozilla::gfx
{
14 ConvolutionFilter::ConvolutionFilter()
15 : mFilter(MakeUnique
<skia::SkConvolutionFilter1D
>()) {}
17 ConvolutionFilter::~ConvolutionFilter() = default;
19 int32_t ConvolutionFilter::MaxFilter() const { return mFilter
->maxFilter(); }
21 int32_t ConvolutionFilter::NumValues() const { return mFilter
->numValues(); }
23 bool ConvolutionFilter::GetFilterOffsetAndLength(int32_t aRowIndex
,
24 int32_t* aResultOffset
,
25 int32_t* aResultLength
) {
26 if (aRowIndex
>= mFilter
->numValues()) {
29 mFilter
->FilterForValue(aRowIndex
, aResultOffset
, aResultLength
);
33 void ConvolutionFilter::ConvolveHorizontally(const uint8_t* aSrc
, uint8_t* aDst
,
35 skia::convolve_horizontally(aSrc
, *mFilter
, aDst
, aHasAlpha
);
38 void ConvolutionFilter::ConvolveVertically(uint8_t* const* aSrc
, uint8_t* aDst
,
39 int32_t aRowIndex
, int32_t aRowSize
,
41 MOZ_ASSERT(aRowIndex
< mFilter
->numValues());
46 mFilter
->FilterForValue(aRowIndex
, &filterOffset
, &filterLength
);
47 skia::convolve_vertically(filterValues
, filterLength
, aSrc
, aRowSize
, aDst
,
51 bool ConvolutionFilter::ComputeResizeFilter(ResizeMethod aResizeMethod
,
54 if (aSrcSize
< 0 || aDstSize
< 0) {
58 switch (aResizeMethod
) {
59 case ResizeMethod::BOX
:
60 return mFilter
->ComputeFilterValues(skia::SkBoxFilter(), aSrcSize
,
62 case ResizeMethod::LANCZOS3
:
63 return mFilter
->ComputeFilterValues(skia::SkLanczosFilter(), aSrcSize
,
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 ||
78 SkPixmap
srcPixmap(MakeSkiaImageInfo(IntSize(srcWidth
, srcHeight
), format
),
81 // Rescaler is compatible with N32 only. Convert to N32 if needed.
83 if (srcPixmap
.colorType() != kN32_SkColorType
) {
84 if (!tmpBitmap
.tryAllocPixels(
85 SkImageInfo::MakeN32Premul(srcWidth
, srcHeight
)) ||
86 !tmpBitmap
.writePixels(srcPixmap
) ||
87 !tmpBitmap
.peekPixels(&srcPixmap
)) {
92 ConvolutionFilter xFilter
;
93 ConvolutionFilter yFilter
;
94 ConvolutionFilter
* xOrYFilter
= &xFilter
;
95 bool isSquare
= srcWidth
== srcHeight
&& dstWidth
== dstHeight
;
96 if (!xFilter
.ComputeResizeFilter(ConvolutionFilter::ResizeMethod::LANCZOS3
,
97 srcWidth
, dstWidth
)) {
101 if (!yFilter
.ComputeResizeFilter(ConvolutionFilter::ResizeMethod::LANCZOS3
,
102 srcHeight
, dstHeight
)) {
105 xOrYFilter
= &yFilter
;
108 return skia::BGRAConvolve2D(
109 static_cast<const uint8_t*>(srcPixmap
.addr()), int(srcPixmap
.rowBytes()),
110 !srcPixmap
.isOpaque(), xFilter
.GetSkiaFilter(),
111 xOrYFilter
->GetSkiaFilter(), int(dstStride
), dstData
);
114 } // namespace mozilla::gfx