std::unique_ptr makeScanlineConverter()

in cpp/spectrum/core/proc/ScanlineConversion.cpp [445:577]


std::unique_ptr<ScanlineConverter> makeScanlineConverter(
    const image::pixel::Specification& inputSpecification,
    const image::pixel::Specification& outputSpecification,
    const image::Color& backgroundColor) {
  if (inputSpecification == outputSpecification) {
    return std::make_unique<NoOpScanlineConverter>(
        inputSpecification, outputSpecification, backgroundColor);
  } else if (
      inputSpecification == image::pixel::specifications::Gray &&
      outputSpecification == image::pixel::specifications::RGB) {
    return std::make_unique<
        DefaultScanlineConverter<Pixel_1, Pixel_3, convert::grayToRgb>>(
        inputSpecification, outputSpecification, backgroundColor);

  } else if (
      inputSpecification == image::pixel::specifications::Gray &&
      outputSpecification == image::pixel::specifications::ARGB) {
    return std::make_unique<
        DefaultScanlineConverter<Pixel_1, Pixel_4, convert::grayToArgb>>(
        inputSpecification, outputSpecification, backgroundColor);

  } else if (
      inputSpecification == image::pixel::specifications::Gray &&
      outputSpecification == image::pixel::specifications::RGBA) {
    return std::make_unique<
        DefaultScanlineConverter<Pixel_1, Pixel_4, convert::grayToRgba>>(
        inputSpecification, outputSpecification, backgroundColor);

  } else if (
      inputSpecification == image::pixel::specifications::RGB &&
      outputSpecification == image::pixel::specifications::Gray) {
    return std::make_unique<
        DefaultScanlineConverter<Pixel_3, Pixel_1, convert::rgbToGray>>(
        inputSpecification, outputSpecification, backgroundColor);

  } else if (
      inputSpecification == image::pixel::specifications::RGB &&
      outputSpecification == image::pixel::specifications::ARGB) {
    return std::make_unique<
        DefaultScanlineConverter<Pixel_3, Pixel_4, convert::rgbToArgb>>(
        inputSpecification, outputSpecification, backgroundColor);

  } else if (
      inputSpecification == image::pixel::specifications::RGB &&
      outputSpecification == image::pixel::specifications::RGBA) {
    return std::make_unique<
        DefaultScanlineConverter<Pixel_3, Pixel_4, convert::rgbToRgba>>(
        inputSpecification, outputSpecification, backgroundColor);

  } else if (
      inputSpecification == image::pixel::specifications::ARGB &&
      outputSpecification == image::pixel::specifications::RGBA) {
    return std::make_unique<
        DefaultScanlineConverter<Pixel_4, Pixel_4, convert::argbToRgba>>(
        inputSpecification, outputSpecification, backgroundColor);

  } else if (
      inputSpecification == image::pixel::specifications::RGBA &&
      outputSpecification == image::pixel::specifications::ARGB) {
    return std::make_unique<
        DefaultScanlineConverter<Pixel_4, Pixel_4, convert::rgbaToArgb>>(
        inputSpecification, outputSpecification, backgroundColor);

  } else if (
      inputSpecification == image::pixel::specifications::ARGB &&
      outputSpecification == image::pixel::specifications::Gray) {
    return std::make_unique<DefaultScanlineConverter<
        Pixel_4,
        Pixel_1,
        convertwithbackground::argbToGray>>(
        inputSpecification, outputSpecification, backgroundColor);

  } else if (
      inputSpecification == image::pixel::specifications::RGBA &&
      outputSpecification == image::pixel::specifications::Gray) {
    return std::make_unique<DefaultScanlineConverter<
        Pixel_4,
        Pixel_1,
        convertwithbackground::rgbaToGray>>(
        inputSpecification, outputSpecification, backgroundColor);

  } else if (
      inputSpecification == image::pixel::specifications::ARGB &&
      outputSpecification == image::pixel::specifications::RGB) {
    return std::make_unique<DefaultScanlineConverter<
        Pixel_4,
        Pixel_3,
        convertwithbackground::argbToRgb>>(
        inputSpecification, outputSpecification, backgroundColor);

  } else if (
      inputSpecification == image::pixel::specifications::RGBA &&
      outputSpecification == image::pixel::specifications::RGB) {
    return std::make_unique<DefaultScanlineConverter<
        Pixel_4,
        Pixel_3,
        convertwithbackground::rgbaToRgb>>(
        inputSpecification, outputSpecification, backgroundColor);
  } else {
    // Fallback to dynamic conversion. It is currently a tad slower than the
    // the default converter (about 80ms for a 4k image on iPhone 7).
    if (inputSpecification.colorModel == image::pixel::colormodels::RGB) {
      if (outputSpecification.colorModel == image::pixel::colormodels::RGB) {
        return std::make_unique<
            DynamicScanlineConverter<indices::RGB, indices::RGB>>(
            inputSpecification, outputSpecification, backgroundColor);
      } else if (
          outputSpecification.colorModel == image::pixel::colormodels::Gray) {
        return std::make_unique<
            DynamicScanlineConverter<indices::RGB, indices::Gray>>(
            inputSpecification, outputSpecification, backgroundColor);
      }
    } else if (
        inputSpecification.colorModel == image::pixel::colormodels::Gray) {
      if (outputSpecification.colorModel == image::pixel::colormodels::RGB) {
        return std::make_unique<
            DynamicScanlineConverter<indices::Gray, indices::RGB>>(
            inputSpecification, outputSpecification, backgroundColor);
      } else if (
          outputSpecification.colorModel == image::pixel::colormodels::Gray) {
        return std::make_unique<
            DynamicScanlineConverter<indices::Gray, indices::Gray>>(
            inputSpecification, outputSpecification, backgroundColor);
      }
    }

    SPECTRUM_ERROR_FORMAT(
        error::CannotConvertScanlineBetweenSpecifications,
        "in: %s, out: %s",
        inputSpecification.string().c_str(),
        outputSpecification.string().c_str());
  }
}