image::Specification BaseRecipe::perform()

in cpp/spectrum/core/recipes/BaseRecipe.cpp [29:97]


image::Specification BaseRecipe::perform(const Operation& operation) const {
  const auto& parameters = operation.parameters;
  const auto decisions = decisions::BaseDecision::calculate(operation);

  // processing blocks
  std::vector<std::unique_ptr<proc::ScanlineProcessingBlock>> processingBlocks;

  auto decompressor =
      operation.makeDecompressor(decisions.resize.getSamplingRatio());

  const auto scanlineGenerator = [&decompressor] {
    return decompressor->readScanline();
  };

  // (1) cropping
  if (decisions.resize.shouldCrop()) {
    const auto cropRequirement = decisions.resize.cropRequirement();
    const auto croppingInput = decisions.resize.sizeAfterSampling();
    processingBlocks.push_back(
        std::make_unique<proc::CroppingScanlineProcessingBlock>(
            parameters.inputImageSpecification.pixelSpecification,
            croppingInput,
            cropRequirement->apply(croppingInput)));
  }

  // (2) scaling
  if (decisions.resize.shouldScale()) {
    processingBlocks.push_back(
        std::make_unique<proc::ScalingScanlineProcessingBlock>(
            parameters.inputImageSpecification.pixelSpecification,
            decisions.resize.sizeAfterCropping(),
            decisions.resize.sizeAfterScaling(),
            operation.configuration.general.samplingMethod()));
  }

  // (3) rotation
  if (decisions.orientation.shouldRotatePixels()) {
    processingBlocks.push_back(
        std::make_unique<proc::RotationScanlineProcessingBlock>(
            parameters.inputImageSpecification.pixelSpecification,
            decisions.resize.sizeAfterScaling(),
            decisions.orientation.orientation));
  }

  auto compressor =
      operation.makeCompressor(decisions.outputImageSpecification);

  const auto scanlineConverter = proc::makeScanlineConverter(
      parameters.inputImageSpecification.pixelSpecification,
      decisions.outputImageSpecification.pixelSpecification,
      operation.configuration.general.defaultBackgroundColor());

  // scanline consumer
  const auto scanlineConsumer = [scanlineConverter = scanlineConverter.get(),
                                 &compressor = *compressor](auto scanline) {
    compressor.writeScanline(
        scanlineConverter->convertScanline(std::move(scanline)));
  };

  // run chain
  proc::ScanlinePump scanlinePump(
      scanlineGenerator,
      std::move(processingBlocks),
      scanlineConsumer,
      decompressor->outputImageSpecification().size.height);
  scanlinePump.pumpAll();

  return decisions.outputImageSpecification;
}