Team Ai
Datasetpublic

Brunobkr/llama.cpp_AlgMor24_github

ΩFFFΣLLIa • llama.cpp • AlgMor24 ██████╗ ███████╗███████╗███████╗██╗ ██╗ ██╗ █████╗ ██╔═══██╗██╔════╝██╔════╝██╔════╝██║ ██║ ██║██╔══██╗ ██║ ██║█████╗ █████╗ █████╗ ██║ ██║ ██║███████║ ██║ ██║██╔══╝ ██╔══╝ ██╔══╝ ██║ ██║ ██║██╔══██║ ╚██████╔╝██║ ██║ ███████╗███████╗███████╗██║██║ ██║ ╚═════╝ ╚═╝ ╚═╝ ╚══════╝╚══════╝╚══════╝╚═╝╚═╝ ╚═╝ High-Performance LLM / VLM Inference & Autonomous Agentic Ecosystem… See the full description on the dataset page: https://huggingface.co/datasets/Brunobkr/llama.cpp_AlgMor24_github.

sourceHugging Faceupdated 2mo agoView on Hugging Face
0likes3.1kdownloads
pipeline.cc1949 linesDownload Raw Back to src
1/*!2  Copyright 2013 Lovell Fuller and others.3  SPDX-License-Identifier: Apache-2.04*/5 6#include <algorithm>7#include <cmath>8#include <filesystem>  // NOLINT(build/c++17)9#include <map>10#include <memory>11#include <numeric>12#include <string>13#include <tuple>14#include <utility>15#include <vector>16#include <sys/types.h>17#include <sys/stat.h>18 19#include <vips/vips8>20#include <napi.h>21 22#include "./common.h"23#include "./operations.h"24#include "./pipeline.h"25 26class PipelineWorker : public Napi::AsyncWorker {27 public:28  PipelineWorker(Napi::Function callback, PipelineBaton *baton,29    Napi::Function debuglog, Napi::Function queueListener) :30    Napi::AsyncWorker(callback),31    baton(baton),32    debuglog(Napi::Persistent(debuglog)),33    queueListener(Napi::Persistent(queueListener)) {}34  ~PipelineWorker() {}35 36  // libuv worker37  void Execute() {38    // Decrement queued task counter39    sharp::counterQueue--;40    // Increment processing task counter41    sharp::counterProcess++;42 43    try {44      // Open input45      vips::VImage image;46      sharp::ImageType inputImageType;47      if (baton->join.empty()) {48        std::tie(image, inputImageType) = sharp::OpenInput(baton->input);49      } else {50        std::vector<VImage> images;51        bool hasAlpha = false;52        for (auto &join : baton->join) {53          std::tie(image, inputImageType) = sharp::OpenInput(join);54          image = sharp::EnsureColourspace(image, baton->colourspacePipeline);55          images.push_back(image);56          hasAlpha |= image.has_alpha();57        }58        if (hasAlpha) {59          for (auto &image : images) {60            if (!image.has_alpha()) {61              image = sharp::EnsureAlpha(image, 1);62            }63          }64        } else {65          baton->input->joinBackground.pop_back();66        }67        inputImageType = sharp::ImageType::PNG;68        image = VImage::arrayjoin(images, VImage::option()69          ->set("across", baton->input->joinAcross)70          ->set("shim", baton->input->joinShim)71          ->set("background", baton->input->joinBackground)72          ->set("halign", baton->input->joinHalign)73          ->set("valign", baton->input->joinValign));74        if (baton->input->joinAnimated) {75          image = image.copy();76          image.set(VIPS_META_N_PAGES, static_cast<int>(images.size()));77          image.set(VIPS_META_PAGE_HEIGHT, static_cast<int>(image.height() / images.size()));78        }79      }80      VipsAccess access = baton->input->access;81      image = sharp::EnsureColourspace(image, baton->colourspacePipeline);82 83      int nPages = baton->input->pages;84      if (nPages == -1) {85        // Resolve the number of pages if we need to render until the end of the document86        nPages = image.get_typeof(VIPS_META_N_PAGES) != 087          ? image.get_int(VIPS_META_N_PAGES) - std::max(0, baton->input->page)88          : 1;89      }90 91      // Get pre-resize page height92      int pageHeight = sharp::GetPageHeight(image);93 94      // Calculate angle of rotation95      VipsAngle rotation = VIPS_ANGLE_D0;96      VipsAngle autoRotation = VIPS_ANGLE_D0;97      bool autoFlop = false;98 99      if (baton->input->autoOrient) {100        // Rotate and flip image according to Exif orientation101        std::tie(autoRotation, autoFlop) = CalculateExifRotationAndFlop(sharp::ExifOrientation(image));102      }103 104      rotation = CalculateAngleRotation(baton->angle);105 106      bool const shouldRotateBefore = baton->rotateBefore &&107        (rotation != VIPS_ANGLE_D0 || baton->flip || baton->flop || baton->rotationAngle != 0.0);108      bool const shouldOrientBefore = (shouldRotateBefore || baton->orientBefore) &&109        (autoRotation != VIPS_ANGLE_D0 || autoFlop);110 111      if (shouldOrientBefore) {112        image = sharp::StaySequential(image, autoRotation != VIPS_ANGLE_D0);113        if (autoRotation != VIPS_ANGLE_D0) {114          if (autoRotation != VIPS_ANGLE_D180) {115            MultiPageUnsupported(nPages, "Rotate");116          }117          image = image.rot(autoRotation);118          autoRotation = VIPS_ANGLE_D0;119        }120        if (autoFlop) {121          image = image.flip(VIPS_DIRECTION_HORIZONTAL);122          autoFlop = false;123        }124      }125 126      if (shouldRotateBefore) {127        image = sharp::StaySequential(image, rotation != VIPS_ANGLE_D0 || baton->flip || baton->rotationAngle != 0.0);128        if (baton->flip) {129          image = image.flip(VIPS_DIRECTION_VERTICAL);130          baton->flip = false;131        }132        if (baton->flop) {133          image = image.flip(VIPS_DIRECTION_HORIZONTAL);134          baton->flop = false;135        }136        if (rotation != VIPS_ANGLE_D0) {137          if (rotation != VIPS_ANGLE_D180) {138            MultiPageUnsupported(nPages, "Rotate");139          }140          image = image.rot(rotation);141          rotation = VIPS_ANGLE_D0;142        }143        if (baton->rotationAngle != 0.0) {144          MultiPageUnsupported(nPages, "Rotate");145          std::vector<double> background;146          std::tie(image, background) = sharp::ApplyAlpha(image, baton->rotationBackground, false);147          image = image.rotate(baton->rotationAngle, VImage::option()->set("background", background)).copy_memory();148          baton->rotationAngle = 0.0;149        }150      }151 152      // Trim153      if (baton->trimThreshold >= 0.0) {154        MultiPageUnsupported(nPages, "Trim");155        image = sharp::StaySequential(image);156        image = sharp::Trim(image, baton->trimBackground, baton->trimThreshold, baton->trimLineArt, baton->trimMargin);157        baton->trimOffsetLeft = image.xoffset();158        baton->trimOffsetTop = image.yoffset();159      }160 161      // Pre extraction162      if (baton->topOffsetPre != -1) {163        image = nPages > 1164          ? sharp::CropMultiPage(image,165              baton->leftOffsetPre, baton->topOffsetPre, baton->widthPre, baton->heightPre, nPages, &pageHeight)166          : image.extract_area(baton->leftOffsetPre, baton->topOffsetPre, baton->widthPre, baton->heightPre);167      }168 169      // Get pre-resize image width and height170      int inputWidth = image.width();171      int inputHeight = image.height();172 173      // Is there just one page? Shrink to inputHeight instead174      if (nPages == 1) {175        pageHeight = inputHeight;176      }177 178      // Scaling calculations179      double hshrink;180      double vshrink;181      int targetResizeWidth = baton->width;182      int targetResizeHeight = baton->height;183 184      // When auto-rotating by 90 or 270 degrees, swap the target width and185      // height to ensure the behavior aligns with how it would have been if186      // the rotation had taken place *before* resizing.187      if (autoRotation == VIPS_ANGLE_D90 || autoRotation == VIPS_ANGLE_D270) {188        std::swap(targetResizeWidth, targetResizeHeight);189      }190 191      // Shrink to pageHeight, so we work for multi-page images192      std::tie(hshrink, vshrink) = sharp::ResolveShrink(193        inputWidth, pageHeight, targetResizeWidth, targetResizeHeight,194        baton->canvas, baton->withoutEnlargement, baton->withoutReduction);195 196      // The jpeg preload shrink.197      int jpegShrinkOnLoad = 1;198 199      // WebP, PDF, SVG scale200      double scale = 1.0;201 202      // Try to reload input using shrink-on-load for JPEG, WebP, SVG and PDF, when:203      //  - the width or height parameters are specified;204      //  - gamma correction doesn't need to be applied;205      //  - trimming or pre-resize extract isn't required;206      //  - gain map processing is not required;207      //  - input colourspace is not specified;208      bool const shouldPreShrink = (targetResizeWidth > 0 || targetResizeHeight > 0) &&209        baton->gamma == 0 && baton->topOffsetPre == -1 && baton->trimThreshold < 0.0 &&210        !baton->keepGainMap && !baton->withGainMap &&211        baton->colourspacePipeline == VIPS_INTERPRETATION_LAST && !(shouldOrientBefore || shouldRotateBefore);212 213      if (shouldPreShrink) {214        // The common part of the shrink: the bit by which both axes must be shrunk215        double shrink = std::min(hshrink, vshrink);216 217        if (inputImageType == sharp::ImageType::JPEG) {218          // Leave at least a factor of two for the final resize step, when fastShrinkOnLoad: false219          // for more consistent results and to avoid extra sharpness to the image220          int factor = baton->fastShrinkOnLoad ? 1 : 2;221          if (shrink >= 8 * factor) {222            jpegShrinkOnLoad = 8;223          } else if (shrink >= 4 * factor) {224            jpegShrinkOnLoad = 4;225          } else if (shrink >= 2 * factor) {226            jpegShrinkOnLoad = 2;227          }228          // Lower shrink-on-load for known libjpeg rounding errors229          if (jpegShrinkOnLoad > 1 && static_cast<int>(shrink) == jpegShrinkOnLoad) {230            jpegShrinkOnLoad /= 2;231          }232        } else if (inputImageType == sharp::ImageType::WEBP && baton->fastShrinkOnLoad && shrink > 1.0) {233          // Avoid upscaling via webp234          scale = 1.0 / shrink;235        } else if (inputImageType == sharp::ImageType::SVG ||236                   inputImageType == sharp::ImageType::PDF) {237          scale = 1.0 / shrink;238        }239      }240 241      // Reload input using shrink-on-load, it'll be an integer shrink242      // factor for jpegload*, a double scale factor for webpload*,243      // pdfload* and svgload*244      if (jpegShrinkOnLoad > 1) {245        vips::VOption *option = GetOptionsForImageType(inputImageType, baton->input)->set("shrink", jpegShrinkOnLoad);246        if (baton->input->buffer != nullptr) {247          // Reload JPEG buffer248          VipsBlob *blob = vips_blob_new(nullptr, baton->input->buffer, baton->input->bufferLength);249          image = VImage::jpegload_buffer(blob, option);250          vips_area_unref(reinterpret_cast<VipsArea*>(blob));251        } else {252          // Reload JPEG file253          image = VImage::jpegload(const_cast<char*>(baton->input->file.data()), option);254        }255      } else if (scale != 1.0) {256        vips::VOption *option = GetOptionsForImageType(inputImageType, baton->input)->set("scale", scale);257        if (inputImageType == sharp::ImageType::WEBP) {258          if (baton->input->buffer != nullptr) {259            // Reload WebP buffer260            VipsBlob *blob = vips_blob_new(nullptr, baton->input->buffer, baton->input->bufferLength);261            image = VImage::webpload_buffer(blob, option);262            vips_area_unref(reinterpret_cast<VipsArea*>(blob));263          } else {264            // Reload WebP file265            image = VImage::webpload(const_cast<char*>(baton->input->file.data()), option);266          }267        } else if (inputImageType == sharp::ImageType::SVG) {268          if (baton->input->buffer != nullptr) {269            // Reload SVG buffer270            VipsBlob *blob = vips_blob_new(nullptr, baton->input->buffer, baton->input->bufferLength);271            image = VImage::svgload_buffer(blob, option);272            vips_area_unref(reinterpret_cast<VipsArea*>(blob));273          } else {274            // Reload SVG file275            image = VImage::svgload(const_cast<char*>(baton->input->file.data()), option);276          }277          sharp::SetDensity(image, baton->input->density);278          if (image.width() > 32767 || image.height() > 32767) {279            throw std::runtime_error("Input SVG image will exceed 32767x32767 pixel limit when scaled");280          }281        } else if (inputImageType == sharp::ImageType::PDF) {282          if (baton->input->buffer != nullptr) {283            // Reload PDF buffer284            VipsBlob *blob = vips_blob_new(nullptr, baton->input->buffer, baton->input->bufferLength);285            image = VImage::pdfload_buffer(blob, option);286            vips_area_unref(reinterpret_cast<VipsArea*>(blob));287          } else {288            // Reload PDF file289            image = VImage::pdfload(const_cast<char*>(baton->input->file.data()), option);290          }291          sharp::SetDensity(image, baton->input->density);292        }293      } else {294        if (inputImageType == sharp::ImageType::SVG && (image.width() > 32767 || image.height() > 32767)) {295          throw std::runtime_error("Input SVG image exceeds 32767x32767 pixel limit");296        }297      }298      if (baton->input->autoOrient) {299        image = sharp::RemoveExifOrientation(image);300      }301      VImage gainMap;302      int gainMapScaleFactor = 1;303      if (sharp::HasGainMap(image)) {304        if (baton->keepGainMap) {305          gainMap = image.gainmap();306          if (image.get_typeof("gainmap-scale-factor") == G_TYPE_INT) {307            gainMapScaleFactor = image.get_int("gainmap-scale-factor");308          }309        } else if (baton->withGainMap) {310          image = image.uhdr2scRGB();311        }312        image = sharp::RemoveGainMap(image);313      } else {314        baton->keepGainMap = false;315        baton->withGainMap = false;316      }317 318      // Any pre-shrinking may already have been done319      inputWidth = image.width();320      inputHeight = image.height();321 322      // After pre-shrink, but before the main shrink stage323      // Reuse the initial pageHeight if we didn't pre-shrink324      if (shouldPreShrink) {325        pageHeight = sharp::GetPageHeight(image);326      }327 328      // Shrink to pageHeight, so we work for multi-page images329      std::tie(hshrink, vshrink) = sharp::ResolveShrink(330        inputWidth, pageHeight, targetResizeWidth, targetResizeHeight,331        baton->canvas, baton->withoutEnlargement, baton->withoutReduction);332 333      int targetHeight = static_cast<int>(std::rint(static_cast<double>(pageHeight) / vshrink));334      int targetPageHeight = targetHeight;335 336      // In toilet-roll mode, we must adjust vshrink so that we exactly hit337      // pageHeight or we'll have pixels straddling pixel boundaries338      if (inputHeight > pageHeight) {339        targetHeight *= nPages;340        vshrink = static_cast<double>(inputHeight) / targetHeight;341      }342 343      // Ensure we're using a device-independent colour space344      std::pair<char*, size_t> inputProfile(nullptr, 0);345      if ((baton->keepMetadata & VIPS_FOREIGN_KEEP_ICC) && baton->withIccProfile.empty()) {346        // Cache input profile for use with output347        inputProfile = sharp::GetProfile(image);348        baton->input->ignoreIcc = true;349      }350      char const *processingProfile = image.interpretation() == VIPS_INTERPRETATION_RGB16 ? "p3" : "srgb";351      if (352        sharp::HasProfile(image) &&353        image.interpretation() != VIPS_INTERPRETATION_LABS &&354        image.interpretation() != VIPS_INTERPRETATION_GREY16 &&355        baton->colourspacePipeline != VIPS_INTERPRETATION_CMYK &&356        !baton->input->ignoreIcc && !baton->withGainMap357      ) {358        // Convert to sRGB/P3 using embedded profile359        try {360          image = image.icc_transform(processingProfile, VImage::option()361            ->set("embedded", true)362            ->set("depth", sharp::Is16Bit(image.interpretation()) ? 16 : 8)363            ->set("intent", VIPS_INTENT_PERCEPTUAL));364        } catch(...) {365          sharp::VipsWarningCallback(nullptr, G_LOG_LEVEL_WARNING, "Invalid embedded profile", nullptr);366        }367      } else if (368        image.interpretation() == VIPS_INTERPRETATION_CMYK &&369        baton->colourspacePipeline != VIPS_INTERPRETATION_CMYK370      ) {371        image = image.icc_transform(processingProfile, VImage::option()372          ->set("input_profile", "cmyk")373          ->set("intent", VIPS_INTENT_PERCEPTUAL));374      }375 376      // Flatten image to remove alpha channel377      if (baton->flatten && image.has_alpha()) {378        image = sharp::Flatten(image, baton->flattenBackground);379      }380 381      // Gamma encoding (darken)382      if (baton->gamma >= 1 && baton->gamma <= 3) {383        image = sharp::Gamma(image, 1.0 / baton->gamma);384      }385 386      // Convert to greyscale (linear, therefore after gamma encoding, if any)387      if (baton->greyscale) {388        image = image.colourspace(VIPS_INTERPRETATION_B_W);389      }390 391      bool const shouldResize = hshrink != 1.0 || vshrink != 1.0;392      bool const shouldBlur = baton->blurSigma != 0.0;393      bool const shouldConv = baton->convKernelWidth * baton->convKernelHeight > 0;394      bool const shouldSharpen = baton->sharpenSigma != 0.0;395      bool const shouldComposite = !baton->composite.empty();396 397      if (shouldComposite && !image.has_alpha()) {398        image = sharp::EnsureAlpha(image, 1);399      }400 401      VipsBandFormat premultiplyFormat = image.format();402      bool const shouldPremultiplyAlpha = image.has_alpha() &&403        (shouldResize || shouldBlur || shouldConv || shouldSharpen);404 405      if (shouldPremultiplyAlpha) {406        image = image.premultiply().cast(premultiplyFormat);407      }408 409      // Resize410      if (shouldResize) {411        image = image.resize(1.0 / hshrink, VImage::option()412          ->set("vscale", 1.0 / vshrink)413          ->set("kernel", baton->kernel));414        if (baton->keepGainMap) {415          gainMap = gainMap.resize(1.0 / hshrink, VImage::option()416            ->set("vscale", 1.0 / vshrink)417            ->set("kernel", baton->kernel));418        }419      }420 421      image = sharp::StaySequential(image,422        autoRotation != VIPS_ANGLE_D0 ||423        baton->flip ||424        rotation != VIPS_ANGLE_D0);425      // Auto-rotate post-extract426      if (autoRotation != VIPS_ANGLE_D0) {427        if (autoRotation != VIPS_ANGLE_D180) {428          MultiPageUnsupported(nPages, "Rotate");429        }430        image = image.rot(autoRotation);431        if (baton->keepGainMap) {432          gainMap = gainMap.rot(autoRotation);433        }434      }435      // Mirror vertically (up-down) about the x-axis436      if (baton->flip) {437        image = image.flip(VIPS_DIRECTION_VERTICAL);438        if (baton->keepGainMap) {439          gainMap = gainMap.flip(VIPS_DIRECTION_VERTICAL);440        }441      }442      // Mirror horizontally (left-right) about the y-axis443      if (baton->flop != autoFlop) {444        image = image.flip(VIPS_DIRECTION_HORIZONTAL);445        if (baton->keepGainMap) {446          gainMap = gainMap.flip(VIPS_DIRECTION_HORIZONTAL);447        }448      }449      // Rotate post-extract 90-angle450      if (rotation != VIPS_ANGLE_D0) {451        if (rotation != VIPS_ANGLE_D180) {452          MultiPageUnsupported(nPages, "Rotate");453        }454        image = image.rot(rotation);455        if (baton->keepGainMap) {456          gainMap = gainMap.rot(rotation);457        }458      }459 460      // Join additional color channels to the image461      if (!baton->joinChannelIn.empty()) {462        VImage joinImage;463        sharp::ImageType joinImageType = sharp::ImageType::UNKNOWN;464 465        for (unsigned int i = 0; i < baton->joinChannelIn.size(); i++) {466          baton->joinChannelIn[i]->access = access;467          std::tie(joinImage, joinImageType) = sharp::OpenInput(baton->joinChannelIn[i]);468          joinImage = sharp::EnsureColourspace(joinImage, baton->colourspacePipeline);469          image = image.bandjoin(joinImage);470        }471        image = image.copy(VImage::option()->set("interpretation", baton->colourspace));472        image = sharp::RemoveGifPalette(image);473      }474 475      inputWidth = image.width();476      inputHeight = nPages > 1 ? targetPageHeight : image.height();477 478      // Resolve dimensions479      if (baton->width <= 0) {480        baton->width = inputWidth;481      }482      if (baton->height <= 0) {483        baton->height = inputHeight;484      }485 486      // Crop/embed487      if (inputWidth != baton->width || inputHeight != baton->height) {488        if (baton->canvas == sharp::Canvas::EMBED) {489          std::vector<double> background;490          std::tie(image, background) = sharp::ApplyAlpha(image, baton->resizeBackground, shouldPremultiplyAlpha);491 492          // Embed493          const auto& [left, top] = sharp::CalculateEmbedPosition(494            inputWidth, inputHeight, baton->width, baton->height, baton->position);495          const int width = std::max(inputWidth, baton->width);496          const int height = std::max(inputHeight, baton->height);497 498          image = nPages > 1499            ? sharp::EmbedMultiPage(image,500                left, top, width, height, VIPS_EXTEND_BACKGROUND, background, nPages, &targetPageHeight)501            : image.embed(left, top, width, height, VImage::option()502              ->set("extend", VIPS_EXTEND_BACKGROUND)503              ->set("background", background));504          if (baton->keepGainMap) {505            gainMap = gainMap.embed(left / gainMapScaleFactor, top / gainMapScaleFactor,506              width / gainMapScaleFactor, height / gainMapScaleFactor, VImage::option()507                ->set("extend", VIPS_EXTEND_BACKGROUND)508                ->set("background", 0));509          }510        } else if (baton->canvas == sharp::Canvas::CROP) {511          if (baton->width > inputWidth) {512            baton->width = inputWidth;513          }514          if (baton->height > inputHeight) {515            baton->height = inputHeight;516          }517 518          // Crop519          if (baton->position < 9) {520            // Gravity-based crop521            const auto& [left, top] = sharp::CalculateCrop(522              inputWidth, inputHeight, baton->width, baton->height, baton->position);523            const int width = std::min(inputWidth, baton->width);524            const int height = std::min(inputHeight, baton->height);525 526            image = nPages > 1527              ? sharp::CropMultiPage(image,528                  left, top, width, height, nPages, &targetPageHeight)529              : image.extract_area(left, top, width, height);530            if (baton->keepGainMap) {531              gainMap = gainMap.extract_area(left / gainMapScaleFactor, top / gainMapScaleFactor,532                width / gainMapScaleFactor, height / gainMapScaleFactor);533            }534          } else {535            int attention_x;536            int attention_y;537 538            // Attention-based or Entropy-based crop539            MultiPageUnsupported(nPages, "Resize strategy");540            KeepGainMapUnsupported(baton->keepGainMap, "Resize strategy");541            image = sharp::StaySequential(image);542            image = image.smartcrop(baton->width, baton->height, VImage::option()543              ->set("interesting", baton->position == 16 ? VIPS_INTERESTING_ENTROPY : VIPS_INTERESTING_ATTENTION)544              ->set("premultiplied", shouldPremultiplyAlpha)545              ->set("attention_x", &attention_x)546              ->set("attention_y", &attention_y));547            baton->hasCropOffset = true;548            baton->cropOffsetLeft = static_cast<int>(image.xoffset());549            baton->cropOffsetTop = static_cast<int>(image.yoffset());550            baton->hasAttentionCenter = true;551            baton->attentionX = static_cast<int>(attention_x * jpegShrinkOnLoad / scale);552            baton->attentionY = static_cast<int>(attention_y * jpegShrinkOnLoad / scale);553          }554        }555      }556 557      // Rotate post-extract non-90 angle558      if (!baton->rotateBefore && baton->rotationAngle != 0.0) {559        MultiPageUnsupported(nPages, "Rotate");560        image = sharp::StaySequential(image);561        std::vector<double> background;562        std::tie(image, background) = sharp::ApplyAlpha(image, baton->rotationBackground, shouldPremultiplyAlpha);563        image = image.rotate(baton->rotationAngle, VImage::option()->set("background", background));564        if (baton->keepGainMap) {565          gainMap = gainMap.rotate(baton->rotationAngle, VImage::option()->set("background", 0));566        }567      }568 569      // Post extraction570      if (baton->topOffsetPost != -1) {571        if (nPages > 1) {572          image = sharp::CropMultiPage(image,573            baton->leftOffsetPost, baton->topOffsetPost, baton->widthPost, baton->heightPost,574            nPages, &targetPageHeight);575          // heightPost is used in the info object, so update to reflect the number of pages576          baton->heightPost *= nPages;577        } else {578          image = image.extract_area(579            baton->leftOffsetPost, baton->topOffsetPost, baton->widthPost, baton->heightPost);580          if (baton->keepGainMap) {581            gainMap = gainMap.extract_area(baton->leftOffsetPost / gainMapScaleFactor,582              baton->topOffsetPost / gainMapScaleFactor, baton->widthPost / gainMapScaleFactor,583              baton->heightPost / gainMapScaleFactor);584          }585        }586      }587 588      // Affine transform589      if (!baton->affineMatrix.empty()) {590        MultiPageUnsupported(nPages, "Affine");591        KeepGainMapUnsupported(baton->keepGainMap, "Affine");592        image = sharp::StaySequential(image);593        std::vector<double> background;594        std::tie(image, background) = sharp::ApplyAlpha(image, baton->affineBackground, shouldPremultiplyAlpha);595        vips::VInterpolate interp = vips::VInterpolate::new_from_name(596          const_cast<char*>(baton->affineInterpolator.data()));597        image = image.affine(baton->affineMatrix, VImage::option()->set("background", background)598          ->set("idx", baton->affineIdx)599          ->set("idy", baton->affineIdy)600          ->set("odx", baton->affineOdx)601          ->set("ody", baton->affineOdy)602          ->set("interpolate", interp));603      }604 605      // Extend edges606      if (baton->extendTop > 0 || baton->extendBottom > 0 || baton->extendLeft > 0 || baton->extendRight > 0) {607        // Embed608        baton->width = image.width() + baton->extendLeft + baton->extendRight;609        baton->height = (nPages > 1 ? targetPageHeight : image.height()) + baton->extendTop + baton->extendBottom;610 611        std::vector<double> background;612        if (baton->extendWith == VIPS_EXTEND_BACKGROUND) {613          std::tie(image, background) = sharp::ApplyAlpha(image, baton->extendBackground, shouldPremultiplyAlpha);614        }615        image = sharp::StaySequential(image, nPages > 1 || baton->extendWith != VIPS_EXTEND_BACKGROUND);616        auto options = VImage::option()->set("extend", baton->extendWith);617        if (baton->extendWith == VIPS_EXTEND_BACKGROUND) {618          options->set("background", background);619        }620        image = nPages > 1621          ? sharp::EmbedMultiPage(image,622              baton->extendLeft, baton->extendTop, baton->width, baton->height,623              baton->extendWith, background, nPages, &targetPageHeight)624          : image.embed(baton->extendLeft, baton->extendTop, baton->width, baton->height, options);625        if (baton->keepGainMap) {626          gainMap = gainMap.embed(baton->extendLeft / gainMapScaleFactor, baton->extendTop / gainMapScaleFactor,627            baton->width / gainMapScaleFactor, baton->height / gainMapScaleFactor, VImage::option()628              ->set("extend", baton->extendWith)629              ->set("background", 0));630        }631      }632      // Median - must happen before blurring, due to the utility of blurring after thresholding633      if (baton->medianSize > 0) {634        image = image.median(baton->medianSize);635      }636 637      // Threshold - must happen before blurring, due to the utility of blurring after thresholding638      // Threshold - must happen before unflatten to enable non-white unflattening639      if (baton->threshold != 0) {640        image = sharp::Threshold(image, baton->threshold, baton->thresholdGrayscale);641      }642 643      // Dilate - must happen before blurring, due to the utility of dilating after thresholding644      if (baton->dilateWidth != 0) {645        image = sharp::Dilate(image, baton->dilateWidth);646      }647 648      // Erode - must happen before blurring, due to the utility of eroding after thresholding649      if (baton->erodeWidth != 0) {650        image = sharp::Erode(image, baton->erodeWidth);651      }652 653      // Blur654      if (shouldBlur) {655        image = sharp::Blur(image, baton->blurSigma, baton->precision, baton->minAmpl);656        if (baton->keepGainMap) {657          gainMap = sharp::Blur(gainMap, baton->blurSigma, baton->precision, baton->minAmpl);658        }659      }660 661      // Unflatten the image662      if (baton->unflatten) {663        image = sharp::Unflatten(image);664      }665 666      // Convolve667      if (shouldConv) {668        KeepGainMapUnsupported(baton->keepGainMap, "Convolve");669        image = sharp::Convolve(image,670          baton->convKernelWidth, baton->convKernelHeight,671          baton->convKernelScale, baton->convKernelOffset,672          baton->convKernel);673      }674 675      // Recomb676      if (!baton->recombMatrix.empty()) {677        KeepGainMapUnsupported(baton->keepGainMap, "Recomb");678        image = sharp::Recomb(image, baton->recombMatrix);679      }680 681      // Modulate682      if (baton->brightness != 1.0 || baton->saturation != 1.0 || baton->hue != 0.0 || baton->lightness != 0.0) {683        KeepGainMapUnsupported(baton->keepGainMap, "Modulate");684        image = sharp::Modulate(image, baton->brightness, baton->saturation, baton->hue, baton->lightness);685      }686 687      // Sharpen688      if (shouldSharpen) {689        image = sharp::Sharpen(image, baton->sharpenSigma, baton->sharpenM1, baton->sharpenM2,690          baton->sharpenX1, baton->sharpenY2, baton->sharpenY3);691      }692 693      // Reverse premultiplication after all transformations694      if (shouldPremultiplyAlpha) {695        image = image.unpremultiply().cast(premultiplyFormat);696      }697      baton->premultiplied = shouldPremultiplyAlpha;698 699      // Composite700      if (shouldComposite) {701        KeepGainMapUnsupported(baton->keepGainMap, "Composite");702        std::vector<VImage> images = { image };703        std::vector<int> modes, xs, ys;704        for (Composite *composite : baton->composite) {705          VImage compositeImage;706          sharp::ImageType compositeImageType = sharp::ImageType::UNKNOWN;707          composite->input->access = access;708          std::tie(compositeImage, compositeImageType) = sharp::OpenInput(composite->input);709 710          if (composite->input->autoOrient) {711            // Respect EXIF Orientation712            VipsAngle compositeAutoRotation = VIPS_ANGLE_D0;713            bool compositeAutoFlop = false;714            std::tie(compositeAutoRotation, compositeAutoFlop) =715              CalculateExifRotationAndFlop(sharp::ExifOrientation(compositeImage));716 717            compositeImage = sharp::RemoveExifOrientation(compositeImage);718            compositeImage = sharp::StaySequential(compositeImage, compositeAutoRotation != VIPS_ANGLE_D0);719 720            if (compositeAutoRotation != VIPS_ANGLE_D0) {721              compositeImage = compositeImage.rot(compositeAutoRotation);722            }723            if (compositeAutoFlop) {724              compositeImage = compositeImage.flip(VIPS_DIRECTION_HORIZONTAL);725            }726          }727 728          // Verify within current dimensions729          if (compositeImage.width() > image.width() || compositeImage.height() > image.height()) {730            throw std::runtime_error("Image to composite must have same dimensions or smaller");731          }732          // Check if overlay is tiled733          if (composite->tile) {734            int across = 0;735            int down = 0;736            // Use gravity in overlay737            if (compositeImage.width() <= image.width()) {738              across = static_cast<int>(ceil(static_cast<double>(image.width()) / compositeImage.width()));739              // Ensure odd number of tiles across when gravity is centre, north or south740              if (composite->gravity == 0 || composite->gravity == 1 || composite->gravity == 3) {741                across |= 1;742              }743            }744            if (compositeImage.height() <= image.height()) {745              down = static_cast<int>(ceil(static_cast<double>(image.height()) / compositeImage.height()));746              // Ensure odd number of tiles down when gravity is centre, east or west747              if (composite->gravity == 0 || composite->gravity == 2 || composite->gravity == 4) {748                down |= 1;749              }750            }751            if (across != 0 || down != 0) {752              int left;753              int top;754              compositeImage = sharp::StaySequential(compositeImage).replicate(across, down);755              if (composite->hasOffset) {756                std::tie(left, top) = sharp::CalculateCrop(757                  compositeImage.width(), compositeImage.height(), image.width(), image.height(),758                  composite->left, composite->top);759              } else {760                std::tie(left, top) = sharp::CalculateCrop(761                  compositeImage.width(), compositeImage.height(), image.width(), image.height(), composite->gravity);762              }763              compositeImage = compositeImage.extract_area(left, top, image.width(), image.height());764            }765            // gravity was used for extract_area, set it back to its default value of 0766            composite->gravity = 0;767          }768          // Ensure image to composite is with unpremultiplied alpha769          compositeImage = sharp::EnsureAlpha(compositeImage, 1);770          if (composite->premultiplied) compositeImage = compositeImage.unpremultiply();771          // Calculate position772          int left;773          int top;774          if (composite->hasOffset) {775            // Composite image at given offsets776            if (composite->tile) {777              std::tie(left, top) = sharp::CalculateCrop(image.width(), image.height(),778                compositeImage.width(), compositeImage.height(), composite->left, composite->top);779            } else {780              left = composite->left;781              top = composite->top;782            }783          } else {784            // Composite image with given gravity785            std::tie(left, top) = sharp::CalculateCrop(image.width(), image.height(),786              compositeImage.width(), compositeImage.height(), composite->gravity);787          }788          images.push_back(compositeImage);789          modes.push_back(composite->mode);790          xs.push_back(left);791          ys.push_back(top);792        }793        image = VImage::composite(images, modes, VImage::option()794          ->set("compositing_space", baton->colourspacePipeline == VIPS_INTERPRETATION_LAST795            ? VIPS_INTERPRETATION_sRGB796            : baton->colourspacePipeline)797          ->set("x", xs)798          ->set("y", ys));799        image = sharp::RemoveGifPalette(image);800      }801 802      // Gamma decoding (brighten)803      if (baton->gammaOut >= 1 && baton->gammaOut <= 3) {804        image = sharp::Gamma(image, baton->gammaOut);805      }806 807      // Linear adjustment (a * in + b)808      if (!baton->linearA.empty()) {809        image = sharp::Linear(image, baton->linearA, baton->linearB);810      }811 812      // Apply normalisation - stretch luminance to cover full dynamic range813      if (baton->normalise) {814        KeepGainMapUnsupported(baton->keepGainMap, "Normalise");815        image = sharp::StaySequential(image);816        image = sharp::Normalise(image, baton->normaliseLower, baton->normaliseUpper);817      }818 819      // Apply contrast limiting adaptive histogram equalization (CLAHE)820      if (baton->claheWidth != 0 && baton->claheHeight != 0) {821        KeepGainMapUnsupported(baton->keepGainMap, "Clahe");822        image = sharp::StaySequential(image);823        image = sharp::Clahe(image, baton->claheWidth, baton->claheHeight, baton->claheMaxSlope);824      }825 826      // Apply bitwise boolean operation between images827      if (baton->boolean != nullptr) {828        KeepGainMapUnsupported(baton->keepGainMap, "Boolean");829        VImage booleanImage;830        sharp::ImageType booleanImageType = sharp::ImageType::UNKNOWN;831        baton->boolean->access = access;832        std::tie(booleanImage, booleanImageType) = sharp::OpenInput(baton->boolean);833        booleanImage = sharp::EnsureColourspace(booleanImage, baton->colourspacePipeline);834        image = sharp::Boolean(image, booleanImage, baton->booleanOp);835        image = sharp::RemoveGifPalette(image);836      }837 838      // Apply per-channel Bandbool bitwise operations after all other operations839      if (baton->bandBoolOp >= VIPS_OPERATION_BOOLEAN_AND && baton->bandBoolOp < VIPS_OPERATION_BOOLEAN_LAST) {840        image = sharp::Bandbool(image, baton->bandBoolOp);841      }842 843      // Tint the image844      if (baton->tint[0] >= 0.0) {845        image = sharp::Tint(image, baton->tint);846      }847 848      // Remove alpha channel, if any849      if (baton->removeAlpha) {850        image = sharp::RemoveAlpha(image);851      }852 853      // Ensure alpha channel, if missing854      if (baton->ensureAlpha != -1) {855        image = sharp::EnsureAlpha(image, baton->ensureAlpha);856      }857 858      // Ensure output colour space859      if (sharp::Is16Bit(image.interpretation())) {860        image = image.cast(VIPS_FORMAT_USHORT);861      }862      if (image.interpretation() != baton->colourspace) {863        image = image.colourspace(baton->colourspace, VImage::option()->set("source_space", image.interpretation()));864        if (inputProfile.first != nullptr && baton->withIccProfile.empty()) {865          image = sharp::SetProfile(image, inputProfile);866        }867      }868 869      // Extract channel870      if (baton->extractChannel > -1) {871        KeepGainMapUnsupported(baton->keepGainMap, "Extract channel");872        if (baton->extractChannel >= image.bands()) {873          if (baton->extractChannel == 3 && image.has_alpha()) {874            baton->extractChannel = image.bands() - 1;875          } else {876            (baton->err)877              .append("Cannot extract channel ").append(std::to_string(baton->extractChannel))878              .append(" from image with channels 0-").append(std::to_string(image.bands() - 1));879            return Error();880          }881        }882        VipsInterpretation colourspace = sharp::Is16Bit(image.interpretation())883          ? VIPS_INTERPRETATION_GREY16884          : VIPS_INTERPRETATION_B_W;885        image = image886          .extract_band(baton->extractChannel)887          .copy(VImage::option()->set("interpretation", colourspace));888      }889 890      // Apply output ICC profile891      if (!baton->withIccProfile.empty()) {892        try {893          image = image.icc_transform(const_cast<char*>(baton->withIccProfile.data()), VImage::option()894            ->set("input_profile", processingProfile)895            ->set("embedded", true)896            ->set("depth", sharp::Is16Bit(image.interpretation()) ? 16 : 8)897            ->set("intent", VIPS_INTENT_PERCEPTUAL));898        } catch(...) {899          sharp::VipsWarningCallback(nullptr, G_LOG_LEVEL_WARNING, "Invalid profile", nullptr);900        }901      }902 903      // Negate the colours in the image904      if (baton->negate) {905        image = sharp::Negate(image, baton->negateAlpha);906        if (baton->keepGainMap) {907          gainMap = sharp::Negate(gainMap, false);908        }909      }910 911      // Override EXIF Orientation tag912      if (baton->withMetadataOrientation != -1) {913        image = sharp::SetExifOrientation(image, baton->withMetadataOrientation);914      }915      // Override pixel density916      if (baton->withMetadataDensity > 0) {917        image = sharp::SetDensity(image, baton->withMetadataDensity);918      }919      // EXIF key/value pairs920      if (baton->keepMetadata & VIPS_FOREIGN_KEEP_EXIF) {921        image = image.copy();922        if (!baton->withExifMerge) {923          image = sharp::RemoveExif(image);924        }925        for (const auto& [key, value] : baton->withExif) {926          image.set(key.c_str(), value.c_str());927        }928      }929      // XMP buffer930      if ((baton->keepMetadata & VIPS_FOREIGN_KEEP_XMP) && !baton->withXmp.empty()) {931        image = image.copy();932        image.set(VIPS_META_XMP_NAME, nullptr,933          const_cast<void*>(static_cast<void const*>(baton->withXmp.c_str())), baton->withXmp.size());934      }935      // Number of channels used in output image936      baton->channels = image.bands();937      baton->width = image.width();938      baton->height = image.height();939 940      image = sharp::SetAnimationProperties(941        image, nPages, targetPageHeight, baton->delay, baton->loop);942 943      if (image.get_typeof(VIPS_META_PAGE_HEIGHT) == G_TYPE_INT) {944        baton->pageHeightOut = image.get_int(VIPS_META_PAGE_HEIGHT);945        baton->pagesOut = image.get_int(VIPS_META_N_PAGES);946      }947      baton->hasAlphaOut = image.has_alpha();948 949      // Output950      sharp::SetTimeout(image, baton->timeoutSeconds);951      if (baton->fileOut.empty()) {952        // Buffer output953        if (baton->formatOut == "jpeg" || (baton->formatOut == "input" && inputImageType == sharp::ImageType::JPEG)) {954          // Write JPEG to buffer955          sharp::AssertImageTypeDimensions(image, sharp::ImageType::JPEG);956          VipsArea *area;957          if (baton->keepGainMap) {958            image = ReattachGainMap(image, gainMap, baton);959            area = reinterpret_cast<VipsArea*>(image.uhdrsave_buffer(VImage::option()960              ->set("keep", baton->keepMetadata)961              ->set("Q", baton->jpegQuality)962              ->set("gainmap_scale_factor", gainMapScaleFactor)));963          } else {964            area = reinterpret_cast<VipsArea*>(image.jpegsave_buffer(VImage::option()965              ->set("keep", baton->keepMetadata)966              ->set("Q", baton->jpegQuality)967              ->set("interlace", baton->jpegProgressive)968              ->set("subsample_mode", baton->jpegChromaSubsampling == "4:4:4"969                ? VIPS_FOREIGN_SUBSAMPLE_OFF970                : VIPS_FOREIGN_SUBSAMPLE_ON)971              ->set("trellis_quant", baton->jpegTrellisQuantisation)972              ->set("quant_table", baton->jpegQuantisationTable)973              ->set("overshoot_deringing", baton->jpegOvershootDeringing)974              ->set("optimize_scans", baton->jpegOptimiseScans)975              ->set("optimize_coding", baton->jpegOptimiseCoding)));976          }977          baton->bufferOut = static_cast<char*>(area->data);978          baton->bufferOutLength = area->length;979          area->free_fn = nullptr;980          vips_area_unref(area);981          baton->formatOut = "jpeg";982          if (baton->colourspace == VIPS_INTERPRETATION_CMYK) {983            baton->channels = std::min(baton->channels, 4);984          } else {985            baton->channels = std::min(baton->channels, 3);986          }987          baton->hasAlphaOut = false;988        } else if (baton->formatOut == "jp2" || (baton->formatOut == "input"989          && inputImageType == sharp::ImageType::JP2)) {990          // Write JP2 to Buffer991          sharp::AssertImageTypeDimensions(image, sharp::ImageType::JP2);992          VipsArea *area = reinterpret_cast<VipsArea*>(image.jp2ksave_buffer(VImage::option()993            ->set("Q", baton->jp2Quality)994            ->set("lossless", baton->jp2Lossless)995            ->set("subsample_mode", baton->jp2ChromaSubsampling == "4:4:4"996              ? VIPS_FOREIGN_SUBSAMPLE_OFF : VIPS_FOREIGN_SUBSAMPLE_ON)997            ->set("tile_height", baton->jp2TileHeight)998            ->set("tile_width", baton->jp2TileWidth)));999          baton->bufferOut = static_cast<char*>(area->data);1000          baton->bufferOutLength = area->length;1001          area->free_fn = nullptr;1002          vips_area_unref(area);1003          baton->formatOut = "jp2";1004        } else if (baton->formatOut == "png" || (baton->formatOut == "input" &&1005          (inputImageType == sharp::ImageType::PNG || inputImageType == sharp::ImageType::SVG))) {1006          // Write PNG to buffer1007          sharp::AssertImageTypeDimensions(image, sharp::ImageType::PNG);1008          VipsArea *area = reinterpret_cast<VipsArea*>(image.pngsave_buffer(VImage::option()1009            ->set("keep", baton->keepMetadata)1010            ->set("interlace", baton->pngProgressive)1011            ->set("compression", baton->pngCompressionLevel)1012            ->set("filter", baton->pngAdaptiveFiltering ? VIPS_FOREIGN_PNG_FILTER_ALL : VIPS_FOREIGN_PNG_FILTER_NONE)1013            ->set("palette", baton->pngPalette)1014            ->set("Q", baton->pngQuality)1015            ->set("effort", baton->pngEffort)1016            ->set("bitdepth", sharp::Is16Bit(image.interpretation()) ? 16 : baton->pngBitdepth)1017            ->set("dither", baton->pngDither)));1018          baton->bufferOut = static_cast<char*>(area->data);1019          baton->bufferOutLength = area->length;1020          area->free_fn = nullptr;1021          vips_area_unref(area);1022          baton->formatOut = "png";1023        } else if (baton->formatOut == "webp" ||1024          (baton->formatOut == "input" && inputImageType == sharp::ImageType::WEBP)) {1025          // Write WEBP to buffer1026          sharp::AssertImageTypeDimensions(image, sharp::ImageType::WEBP);1027          VipsArea *area = reinterpret_cast<VipsArea*>(image.webpsave_buffer(VImage::option()1028            ->set("keep", baton->keepMetadata)1029            ->set("Q", baton->webpQuality)1030            ->set("lossless", baton->webpLossless)1031            ->set("near_lossless", baton->webpNearLossless)1032            ->set("smart_subsample", baton->webpSmartSubsample)1033            ->set("smart_deblock", baton->webpSmartDeblock)1034            ->set("preset", baton->webpPreset)1035            ->set("effort", baton->webpEffort)1036            ->set("min_size", baton->webpMinSize)1037            ->set("mixed", baton->webpMixed)1038            ->set("exact", baton->webpExact)1039            ->set("alpha_q", baton->webpAlphaQuality)));1040          baton->bufferOut = static_cast<char*>(area->data);1041          baton->bufferOutLength = area->length;1042          area->free_fn = nullptr;1043          vips_area_unref(area);1044          baton->formatOut = "webp";1045        } else if (baton->formatOut == "gif" ||1046          (baton->formatOut == "input" && inputImageType == sharp::ImageType::GIF)) {1047          // Write GIF to buffer1048          sharp::AssertImageTypeDimensions(image, sharp::ImageType::GIF);1049          VipsArea *area = reinterpret_cast<VipsArea*>(image.gifsave_buffer(VImage::option()1050            ->set("keep", baton->keepMetadata)1051            ->set("bitdepth", baton->gifBitdepth)1052            ->set("effort", baton->gifEffort)1053            ->set("reuse", baton->gifReuse)1054            ->set("interlace", baton->gifProgressive)1055            ->set("interframe_maxerror", baton->gifInterFrameMaxError)1056            ->set("interpalette_maxerror", baton->gifInterPaletteMaxError)1057            ->set("keep_duplicate_frames", baton->gifKeepDuplicateFrames)1058            ->set("dither", baton->gifDither)));1059          baton->bufferOut = static_cast<char*>(area->data);1060          baton->bufferOutLength = area->length;1061          area->free_fn = nullptr;1062          vips_area_unref(area);1063          baton->formatOut = "gif";1064        } else if (baton->formatOut == "tiff" ||1065          (baton->formatOut == "input" && inputImageType == sharp::ImageType::TIFF)) {1066          // Write TIFF to buffer1067          if (baton->tiffCompression == VIPS_FOREIGN_TIFF_COMPRESSION_JPEG) {1068            sharp::AssertImageTypeDimensions(image, sharp::ImageType::JPEG);1069            baton->channels = std::min(baton->channels, 3);1070            baton->hasAlphaOut = false;1071          }1072          // Cast pixel values to float, if required1073          if (baton->tiffPredictor == VIPS_FOREIGN_TIFF_PREDICTOR_FLOAT) {1074            image = image.cast(VIPS_FORMAT_FLOAT);1075          }1076          VipsArea *area = reinterpret_cast<VipsArea*>(image.tiffsave_buffer(VImage::option()1077            ->set("keep", baton->keepMetadata)1078            ->set("Q", baton->tiffQuality)1079            ->set("bitdepth", baton->tiffBitdepth)1080            ->set("compression", baton->tiffCompression)1081            ->set("bigtiff", baton->tiffBigtiff)1082            ->set("miniswhite", baton->tiffMiniswhite)1083            ->set("predictor", baton->tiffPredictor)1084            ->set("pyramid", baton->tiffPyramid)1085            ->set("tile", baton->tiffTile)1086            ->set("tile_height", baton->tiffTileHeight)1087            ->set("tile_width", baton->tiffTileWidth)1088            ->set("xres", baton->tiffXres)1089            ->set("yres", baton->tiffYres)1090            ->set("resunit", baton->tiffResolutionUnit)));1091          baton->bufferOut = static_cast<char*>(area->data);1092          baton->bufferOutLength = area->length;1093          area->free_fn = nullptr;1094          vips_area_unref(area);1095          baton->formatOut = "tiff";1096        } else if (baton->formatOut == "heif" ||1097          (baton->formatOut == "input" && inputImageType == sharp::ImageType::HEIF)) {1098          // Write HEIF to buffer1099          sharp::AssertImageTypeDimensions(image, sharp::ImageType::HEIF);1100          image = sharp::RemoveAnimationProperties(image);1101          VipsArea *area = reinterpret_cast<VipsArea*>(image.heifsave_buffer(VImage::option()1102            ->set("keep", baton->keepMetadata)1103            ->set("Q", baton->heifQuality)1104            ->set("compression", baton->heifCompression)1105            ->set("effort", baton->heifEffort)1106            ->set("bitdepth", baton->heifBitdepth)1107            ->set("tune", baton->heifTune.c_str())1108            ->set("subsample_mode", baton->heifChromaSubsampling == "4:4:4"1109              ? VIPS_FOREIGN_SUBSAMPLE_OFF : VIPS_FOREIGN_SUBSAMPLE_ON)1110            ->set("lossless", baton->heifLossless)));1111          baton->bufferOut = static_cast<char*>(area->data);1112          baton->bufferOutLength = area->length;1113          area->free_fn = nullptr;1114          vips_area_unref(area);1115          baton->formatOut = "heif";1116        } else if (baton->formatOut == "dz") {1117          // Write DZ to buffer1118          baton->tileContainer = VIPS_FOREIGN_DZ_CONTAINER_ZIP;1119          if (!image.has_alpha()) {1120            baton->tileBackground.pop_back();1121          }1122          image = sharp::StaySequential(image, baton->tileAngle != 0);1123          vips::VOption *options = BuildOptionsDZ(baton);1124          VipsArea *area = reinterpret_cast<VipsArea*>(image.dzsave_buffer(options));1125          baton->bufferOut = static_cast<char*>(area->data);1126          baton->bufferOutLength = area->length;1127          area->free_fn = nullptr;1128          vips_area_unref(area);1129          baton->formatOut = "dz";1130          if (baton->tileFormat == "jpeg") {1131            baton->hasAlphaOut = false;1132          }1133        } else if (baton->formatOut == "jxl" ||1134          (baton->formatOut == "input" && inputImageType == sharp::ImageType::JXL)) {1135          // Write JXL to buffer1136          image = sharp::RemoveAnimationProperties(image);1137          VipsArea *area = reinterpret_cast<VipsArea*>(image.jxlsave_buffer(VImage::option()1138            ->set("keep", baton->keepMetadata)1139            ->set("distance", baton->jxlDistance)1140            ->set("tier", baton->jxlDecodingTier)1141            ->set("effort", baton->jxlEffort)1142            ->set("lossless", baton->jxlLossless)));1143          baton->bufferOut = static_cast<char*>(area->data);1144          baton->bufferOutLength = area->length;1145          area->free_fn = nullptr;1146          vips_area_unref(area);1147          baton->formatOut = "jxl";1148        } else if (baton->formatOut == "raw" ||1149          (baton->formatOut == "input" && inputImageType == sharp::ImageType::RAW)) {1150          // Write raw, uncompressed image data to buffer1151          if (baton->greyscale || image.interpretation() == VIPS_INTERPRETATION_B_W) {1152            // Extract first band for greyscale image1153            image = image[0];1154            baton->channels = 1;1155          }1156          if (image.format() != baton->rawDepth) {1157            // Cast pixels to requested format1158            image = image.cast(baton->rawDepth);1159          }1160          // Get raw image data1161          baton->bufferOut = static_cast<char*>(image.write_to_memory(&baton->bufferOutLength));1162          if (baton->bufferOut == nullptr) {1163            throw std::runtime_error("Could not allocate enough memory for raw output");1164          }1165          baton->formatOut = "raw";1166        } else {1167          // Unsupported output format1168          auto unsupported = std::string("Unsupported output format ");1169          if (baton->formatOut == "input") {1170            unsupported.append("when trying to match input format of ");1171            unsupported.append(ImageTypeId(inputImageType));1172          } else {1173            unsupported.append(baton->formatOut);1174          }1175          throw std::runtime_error(unsupported);1176        }1177      } else {1178        // File output1179        bool const isJpeg = sharp::IsJpeg(baton->fileOut);1180        bool const isPng = sharp::IsPng(baton->fileOut);1181        bool const isWebp = sharp::IsWebp(baton->fileOut);1182        bool const isGif = sharp::IsGif(baton->fileOut);1183        bool const isTiff = sharp::IsTiff(baton->fileOut);1184        bool const isJp2 = sharp::IsJp2(baton->fileOut);1185        bool const isHeif = sharp::IsHeif(baton->fileOut);1186        bool const isJxl = sharp::IsJxl(baton->fileOut);1187        bool const isDz = sharp::IsDz(baton->fileOut);1188        bool const isDzZip = sharp::IsDzZip(baton->fileOut);1189        bool const isV = sharp::IsV(baton->fileOut);1190        bool const mightMatchInput = baton->formatOut == "input";1191        bool const willMatchInput = mightMatchInput &&1192         !(isJpeg || isPng || isWebp || isGif || isTiff || isJp2 || isHeif || isDz || isDzZip || isV);1193 1194        if (baton->formatOut == "jpeg" || (mightMatchInput && isJpeg) ||1195          (willMatchInput && inputImageType == sharp::ImageType::JPEG)) {1196          // Write JPEG to file1197          sharp::AssertImageTypeDimensions(image, sharp::ImageType::JPEG);1198          if (baton->keepGainMap) {1199            image = ReattachGainMap(image, gainMap, baton);1200            image.uhdrsave(const_cast<char*>(baton->fileOut.data()), VImage::option()

Showing the first 1,200 of 1949 lines. Download the file for the rest.

Brunobkr/llama.cpp_AlgMor24_github · Team Ai