/*
 * Copyright 2015 Google Inc.
 *
 * Use of this source code is governed by a BSD-style license that can be
 * found in the LICENSE file.
 */

#include "SkBitmapScaler.h"
#include "SkBitmapFilter.h"
#include "SkConvolver.h"
#include "SkImageInfo.h"
#include "SkPixmap.h"
#include "SkRect.h"
#include "SkTArray.h"

// SkResizeFilter ----------------------------------------------------------------

// Encapsulates computation and storage of the filters required for one complete
// resize operation.
class SkResizeFilter {
public:
    SkResizeFilter(SkBitmapScaler::ResizeMethod method,
                   int srcFullWidth, int srcFullHeight,
                   float destWidth, float destHeight,
                   const SkRect& destSubset);
    ~SkResizeFilter() { delete fBitmapFilter; }

    // Returns the filled filter values.
    const SkConvolutionFilter1D& xFilter() { return fXFilter; }
    const SkConvolutionFilter1D& yFilter() { return fYFilter; }

private:

    SkBitmapFilter* fBitmapFilter;

    // Computes one set of filters either horizontally or vertically. The caller
    // will specify the "min" and "max" rather than the bottom/top and
    // right/bottom so that the same code can be re-used in each dimension.
    //
    // |srcDependLo| and |srcDependSize| gives the range for the source
    // depend rectangle (horizontally or vertically at the caller's discretion
    // -- see above for what this means).
    //
    // Likewise, the range of destination values to compute and the scale factor
    // for the transform is also specified.

    void computeFilters(int srcSize,
                        float destSubsetLo, float destSubsetSize,
                        float scale,
                        SkConvolutionFilter1D* output);

    SkConvolutionFilter1D fXFilter;
    SkConvolutionFilter1D fYFilter;
};

SkResizeFilter::SkResizeFilter(SkBitmapScaler::ResizeMethod method,
                               int srcFullWidth, int srcFullHeight,
                               float destWidth, float destHeight,
                               const SkRect& destSubset) {

    SkASSERT(method >= SkBitmapScaler::RESIZE_FirstMethod &&
             method <= SkBitmapScaler::RESIZE_LastMethod);

    fBitmapFilter = nullptr;
    switch(method) {
        case SkBitmapScaler::RESIZE_BOX:
            fBitmapFilter = new SkBoxFilter;
            break;
        case SkBitmapScaler::RESIZE_TRIANGLE:
            fBitmapFilter = new SkTriangleFilter;
            break;
        case SkBitmapScaler::RESIZE_MITCHELL:
            fBitmapFilter = new SkMitchellFilter;
            break;
        case SkBitmapScaler::RESIZE_HAMMING:
            fBitmapFilter = new SkHammingFilter;
            break;
        case SkBitmapScaler::RESIZE_LANCZOS3:
            fBitmapFilter = new SkLanczosFilter;
            break;
    }


    float scaleX = destWidth / srcFullWidth;
    float scaleY = destHeight / srcFullHeight;

    this->computeFilters(srcFullWidth, destSubset.fLeft, destSubset.width(),
                         scaleX, &fXFilter);
    if (srcFullWidth == srcFullHeight &&
        destSubset.fLeft == destSubset.fTop &&
        destSubset.width() == destSubset.height()&&
        scaleX == scaleY) {
        fYFilter = fXFilter;
    } else {
        this->computeFilters(srcFullHeight, destSubset.fTop, destSubset.height(),
                          scaleY, &fYFilter);
    }
}

// TODO(egouriou): Take advantage of periods in the convolution.
// Practical resizing filters are periodic outside of the border area.
// For Lanczos, a scaling by a (reduced) factor of p/q (q pixels in the
// source become p pixels in the destination) will have a period of p.
// A nice consequence is a period of 1 when downscaling by an integral
// factor. Downscaling from typical display resolutions is also bound
// to produce interesting periods as those are chosen to have multiple
// small factors.
// Small periods reduce computational load and improve cache usage if
// the coefficients can be shared. For periods of 1 we can consider
// loading the factors only once outside the borders.
void SkResizeFilter::computeFilters(int srcSize,
                                    float destSubsetLo, float destSubsetSize,
                                    float scale,
                                    SkConvolutionFilter1D* output) {
    float destSubsetHi = destSubsetLo + destSubsetSize;  // [lo, hi)

    // When we're doing a magnification, the scale will be larger than one. This
    // means the destination pixels are much smaller than the source pixels, and
    // that the range covered by the filter won't necessarily cover any source
    // pixel boundaries. Therefore, we use these clamped values (max of 1) for
    // some computations.
    float clampedScale = SkTMin(1.0f, scale);

    // This is how many source pixels from the center we need to count
    // to support the filtering function.
    float srcSupport = fBitmapFilter->width() / clampedScale;

    float invScale = 1.0f / scale;

    SkSTArray<64, float, true> filterValuesArray;
    SkSTArray<64, SkConvolutionFilter1D::ConvolutionFixed, true> fixedFilterValuesArray;

    // Loop over all pixels in the output range. We will generate one set of
    // filter values for each one. Those values will tell us how to blend the
    // source pixels to compute the destination pixel.

    // This is the pixel in the source directly under the pixel in the dest.
    // Note that we base computations on the "center" of the pixels. To see
    // why, observe that the destination pixel at coordinates (0, 0) in a 5.0x
    // downscale should "cover" the pixels around the pixel with *its center*
    // at coordinates (2.5, 2.5) in the source, not those around (0, 0).
    // Hence we need to scale coordinates (0.5, 0.5), not (0, 0).
    destSubsetLo = SkScalarFloorToScalar(destSubsetLo);
    destSubsetHi = SkScalarCeilToScalar(destSubsetHi);
    float srcPixel = (destSubsetLo + 0.5f) * invScale;
    int destLimit = SkScalarTruncToInt(destSubsetHi - destSubsetLo);
    output->reserveAdditional(destLimit, SkScalarCeilToInt(destLimit * srcSupport * 2));
    for (int destI = 0; destI < destLimit; srcPixel += invScale, destI++) {
        // Compute the (inclusive) range of source pixels the filter covers.
        float srcBegin = SkTMax(0.f, SkScalarFloorToScalar(srcPixel - srcSupport));
        float srcEnd = SkTMin(srcSize - 1.f, SkScalarCeilToScalar(srcPixel + srcSupport));

        // Compute the unnormalized filter value at each location of the source
        // it covers.

        // Sum of the filter values for normalizing.
        // Distance from the center of the filter, this is the filter coordinate
        // in source space. We also need to consider the center of the pixel
        // when comparing distance against 'srcPixel'. In the 5x downscale
        // example used above the distance from the center of the filter to
        // the pixel with coordinates (2, 2) should be 0, because its center
        // is at (2.5, 2.5).
        float destFilterDist = (srcBegin + 0.5f - srcPixel) * clampedScale;
        int filterCount = SkScalarTruncToInt(srcEnd - srcBegin) + 1;
        if (filterCount <= 0) {
            // true when srcSize is equal to srcPixel - srcSupport; this may be a bug
            return;
        }
        filterValuesArray.reset(filterCount);
        float filterSum = fBitmapFilter->evaluate_n(destFilterDist, clampedScale, filterCount,
                                                filterValuesArray.begin());

        // The filter must be normalized so that we don't affect the brightness of
        // the image. Convert to normalized fixed point.
        int fixedSum = 0;
        fixedFilterValuesArray.reset(filterCount);
        const float* filterValues = filterValuesArray.begin();
        SkConvolutionFilter1D::ConvolutionFixed* fixedFilterValues = fixedFilterValuesArray.begin();
        float invFilterSum = 1 / filterSum;
        for (int fixedI = 0; fixedI < filterCount; fixedI++) {
            int curFixed = SkConvolutionFilter1D::FloatToFixed(filterValues[fixedI] * invFilterSum);
            fixedSum += curFixed;
            fixedFilterValues[fixedI] = SkToS16(curFixed);
        }
        SkASSERT(fixedSum <= 0x7FFF);

        // The conversion to fixed point will leave some rounding errors, which
        // we add back in to avoid affecting the brightness of the image. We
        // arbitrarily add this to the center of the filter array (this won't always
        // be the center of the filter function since it could get clipped on the
        // edges, but it doesn't matter enough to worry about that case).
        int leftovers = SkConvolutionFilter1D::FloatToFixed(1) - fixedSum;
        fixedFilterValues[filterCount / 2] += leftovers;

        // Now it's ready to go.
        output->AddFilter(SkScalarFloorToInt(srcBegin), fixedFilterValues, filterCount);
    }
}

///////////////////////////////////////////////////////////////////////////////////////////////////

static bool valid_for_resize(const SkPixmap& source, int dstW, int dstH) {
    // TODO: Seems like we shouldn't care about the swizzle of source, just that it's 8888
    return source.addr() && source.colorType() == kN32_SkColorType &&
           source.width() >= 1 && source.height() >= 1 && dstW >= 1 && dstH >= 1;
}

bool SkBitmapScaler::Resize(const SkPixmap& result, const SkPixmap& source, ResizeMethod method) {
    if (!valid_for_resize(source, result.width(), result.height())) {
        return false;
    }
    if (!result.addr() || result.colorType() != source.colorType()) {
        return false;
    }

    SkRect destSubset = SkRect::MakeIWH(result.width(), result.height());

    SkResizeFilter filter(method, source.width(), source.height(),
                          result.width(), result.height(), destSubset);

    // Get a subset encompassing this touched area. We construct the
    // offsets and row strides such that it looks like a new bitmap, while
    // referring to the old data.
    const uint8_t* sourceSubset = reinterpret_cast<const uint8_t*>(source.addr());

    return BGRAConvolve2D(sourceSubset, static_cast<int>(source.rowBytes()),
                          !source.isOpaque(), filter.xFilter(), filter.yFilter(),
                          static_cast<int>(result.rowBytes()),
                          static_cast<unsigned char*>(result.writable_addr()));
}

bool SkBitmapScaler::Resize(SkBitmap* resultPtr, const SkPixmap& source, ResizeMethod method,
                            int destWidth, int destHeight, SkBitmap::Allocator* allocator) {
    // Preflight some of the checks, to avoid allocating the result if we don't need it.
    if (!valid_for_resize(source, destWidth, destHeight)) {
        return false;
    }

    SkBitmap result;
    // Note: pass along the profile information even thought this is no the right answer because
    // this could be scaling in sRGB.
    result.setInfo(SkImageInfo::MakeN32(destWidth, destHeight, source.alphaType(),
                                        sk_ref_sp(source.info().colorSpace())));
    result.allocPixels(allocator, nullptr);

    SkPixmap resultPM;
    if (!result.peekPixels(&resultPM) || !Resize(resultPM, source, method)) {
        return false;
    }

    *resultPtr = result;
    resultPtr->lockPixels();
    SkASSERT(resultPtr->getPixels());
    return true;
}
