ResizeDecision calculateResizeDecisionWithScaling()

in cpp/spectrum/core/ResizeUtil.cpp [125:189]


ResizeDecision calculateResizeDecisionWithScaling(
    const image::Size& inputSize,
    const image::Size& sizeAfterCropping,
    const folly::Optional<requirements::Resize>& resizeRequirement,
    const float thresholdForSkippingScaling) {
  if (!resizeRequirement.hasValue()) {
    return ResizeDecision(inputSize).rate(
        RESIZE_RATING::GOOD_WITHOUT_SCALING, 0);
  } else {
    const auto targetSize = resizeRequirement->targetSize;

    // CASE 0: if matches perfectly, then return as optimal solution
    if (targetSize == sizeAfterCropping) {
      return ResizeDecision(inputSize).rate(RESIZE_RATING::OPTIMAL);
    }

    const auto isSmaller = sizeAfterCropping.containedIn(targetSize);
    const bool isLarger = !isSmaller;
    const float relativeDeltaToTargetWidth = std::abs(
        1.0f - ((float)sizeAfterCropping.width / (float)targetSize.width));
    const float relativeDeltaToTargetHeight = std::abs(
        1.0f - ((float)sizeAfterCropping.height / (float)targetSize.height));

    // used as a measure of how much too small the image is compared to its
    // container (i.e. the minimal amount to make it fill the container)
    const float relativeDeltaToTargetMin =
        std::min(relativeDeltaToTargetWidth, relativeDeltaToTargetHeight);
    const auto isWithinMinResizingthreshold =
        relativeDeltaToTargetMin <= thresholdForSkippingScaling;

    // CASE 1a: if matches within accepted boundaries, then return as a good
    // solution
    if (isSmaller &&
        resizeRequirement->mode == requirements::Resize::Mode::ExactOrSmaller &&
        isWithinMinResizingthreshold) {
      return ResizeDecision(inputSize).rate(
          RESIZE_RATING::GOOD_WITHOUT_SCALING, relativeDeltaToTargetMin);
    }

    // used as a measure of how much to large the image is compared to its
    // container (i.e. the minimal amount of scaling to make it fit within)
    const float relativeDeltaToTargetMax =
        std::max(relativeDeltaToTargetWidth, relativeDeltaToTargetHeight);

    // CASE 1b: if matches within accepted boundaries, then return as a good
    // solution
    if (isLarger &&
        resizeRequirement->mode == requirements::Resize::Mode::ExactOrLarger &&
        isWithinMinResizingthreshold) {
      return ResizeDecision(inputSize).rate(
          RESIZE_RATING::GOOD_WITHOUT_SCALING, relativeDeltaToTargetMin);
    }

    // CASE 2: if it is larger and requires scaling (and it is allowed) then
    // return as a good solution
    if (isLarger) {
      return ResizeDecision(inputSize)
          .scaling(sizeAfterCropping.downscaledToFit(targetSize))
          .rate(RESIZE_RATING::GOOD_WITH_SCALING, relativeDeltaToTargetMax);
    } else {
      return ResizeDecision(inputSize).rate(
          RESIZE_RATING::BAD_TOO_SMALL, relativeDeltaToTargetMin);
    }
  }
}