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.
03k
1/*!2 Copyright 2013 Lovell Fuller and others.3 SPDX-License-Identifier: Apache-2.04*/5 6#include <algorithm>7#include <functional>8#include <memory>9#include <tuple>10#include <vector>11#include <vips/vips8>12 13#include "./common.h"14#include "./operations.h"15 16using vips::VImage;17 18namespace sharp {19 /*20 * Tint an image using the provided RGB.21 */22 VImage Tint(VImage image, std::vector<double> const tint) {23 std::vector<double> const tintLab = (VImage::black(1, 1) + tint)24 .colourspace(VIPS_INTERPRETATION_LAB, VImage::option()->set("source_space", VIPS_INTERPRETATION_sRGB))25 .getpoint(0, 0);26 // LAB identity function27 VImage identityLab = VImage::identity(VImage::option()->set("bands", 3))28 .colourspace(VIPS_INTERPRETATION_LAB, VImage::option()->set("source_space", VIPS_INTERPRETATION_sRGB));29 // Scale luminance range, 0.0 to 1.030 VImage l = identityLab[0] / 100;31 // Weighting functions32 VImage weightL = 1.0 - 4.0 * ((l - 0.5) * (l - 0.5));33 VImage weightAB = (weightL * tintLab).extract_band(1, VImage::option()->set("n", 2));34 identityLab = identityLab[0].bandjoin(weightAB);35 // Convert lookup table to sRGB36 VImage lut = identityLab.colourspace(VIPS_INTERPRETATION_sRGB,37 VImage::option()->set("source_space", VIPS_INTERPRETATION_LAB));38 // Original colourspace39 VipsInterpretation typeBeforeTint = image.interpretation();40 if (typeBeforeTint == VIPS_INTERPRETATION_RGB) {41 typeBeforeTint = VIPS_INTERPRETATION_sRGB;42 }43 // Apply lookup table44 if (image.has_alpha()) {45 VImage alpha = image[image.bands() - 1];46 image = RemoveAlpha(image)47 .colourspace(VIPS_INTERPRETATION_B_W)48 .maplut(lut)49 .colourspace(typeBeforeTint)50 .bandjoin(alpha);51 } else {52 image = image53 .colourspace(VIPS_INTERPRETATION_B_W)54 .maplut(lut)55 .colourspace(typeBeforeTint);56 }57 return image;58 }59 60 /*61 * Stretch luminance to cover full dynamic range.62 */63 VImage Normalise(VImage image, int const lower, int const upper) {64 // Get original colourspace65 VipsInterpretation typeBeforeNormalize = image.interpretation();66 if (typeBeforeNormalize == VIPS_INTERPRETATION_RGB) {67 typeBeforeNormalize = VIPS_INTERPRETATION_sRGB;68 }69 // Convert to LAB colourspace70 VImage lab = image.colourspace(VIPS_INTERPRETATION_LAB);71 // Extract luminance72 VImage luminance = lab[0];73 74 // Find luminance range75 int const min = lower == 0 ? luminance.min() : luminance.percent(lower);76 int const max = upper == 100 ? luminance.max() : luminance.percent(upper);77 78 if (std::abs(max - min) > 1) {79 // Extract chroma80 VImage chroma = lab.extract_band(1, VImage::option()->set("n", 2));81 // Calculate multiplication factor and addition82 double f = 100.0 / (max - min);83 double a = -(min * f);84 // Scale luminance, join to chroma, convert back to original colourspace85 VImage normalized = luminance.linear(f, a).bandjoin(chroma).colourspace(typeBeforeNormalize);86 // Attach original alpha channel, if any87 if (image.has_alpha()) {88 // Extract original alpha channel89 VImage alpha = image[image.bands() - 1];90 // Join alpha channel to normalised image91 return normalized.bandjoin(alpha);92 } else {93 return normalized;94 }95 }96 return image;97 }98 99 /*100 * Contrast limiting adapative histogram equalization (CLAHE)101 */102 VImage Clahe(VImage image, int const width, int const height, int const maxSlope) {103 return image.hist_local(width, height, VImage::option()->set("max_slope", maxSlope));104 }105 106 /*107 * Gamma encoding/decoding108 */109 VImage Gamma(VImage image, double const exponent) {110 if (image.has_alpha()) {111 // Separate alpha channel112 VImage alpha = image[image.bands() - 1];113 return RemoveAlpha(image).gamma(VImage::option()->set("exponent", exponent)).bandjoin(alpha);114 } else {115 return image.gamma(VImage::option()->set("exponent", exponent));116 }117 }118 119 /*120 * Flatten image to remove alpha channel121 */122 VImage Flatten(VImage image, std::vector<double> flattenBackground) {123 double const multiplier = sharp::Is16Bit(image.interpretation()) ? 256.0 : 1.0;124 std::vector<double> background {125 flattenBackground[0] * multiplier,126 flattenBackground[1] * multiplier,127 flattenBackground[2] * multiplier128 };129 return image.flatten(VImage::option()->set("background", background));130 }131 132 /**133 * Produce the "negative" of the image.134 */135 VImage Negate(VImage image, bool const negateAlpha) {136 if (image.has_alpha() && !negateAlpha) {137 // Separate alpha channel138 VImage alpha = image[image.bands() - 1];139 return RemoveAlpha(image).invert().bandjoin(alpha);140 } else {141 return image.invert();142 }143 }144 145 /*146 * Gaussian blur. Use sigma of -1.0 for fast blur.147 */148 VImage Blur(VImage image, double const sigma, VipsPrecision precision, double const minAmpl) {149 if (sigma == -1.0) {150 // Fast, mild blur - averages neighbouring pixels151 VImage blur = VImage::new_matrixv(3, 3,152 1.0, 1.0, 1.0,153 1.0, 1.0, 1.0,154 1.0, 1.0, 1.0);155 blur.set("scale", 9.0);156 return image.conv(blur);157 } else {158 // Slower, accurate Gaussian blur159 return StaySequential(image).gaussblur(sigma, VImage::option()160 ->set("precision", precision)161 ->set("min_ampl", minAmpl));162 }163 }164 165 /*166 * Convolution with a kernel.167 */168 VImage Convolve(VImage image, int const width, int const height,169 double const scale, double const offset,170 std::vector<double> const &kernel_v171 ) {172 VImage kernel = VImage::new_from_memory(173 static_cast<void*>(const_cast<double*>(kernel_v.data())),174 width * height * sizeof(double),175 width,176 height,177 1,178 VIPS_FORMAT_DOUBLE);179 kernel.set("scale", scale);180 kernel.set("offset", offset);181 182 return image.conv(kernel);183 }184 185 /*186 * Recomb with a Matrix of the given bands/channel size.187 * Eg. RGB will be a 3x3 matrix.188 */189 VImage Recomb(VImage image, std::vector<double> const& matrix) {190 double* m = const_cast<double*>(matrix.data());191 image = image.colourspace(VIPS_INTERPRETATION_sRGB);192 if (matrix.size() == 9) {193 return image194 .recomb(image.bands() == 3195 ? VImage::new_matrix(3, 3, m, 9)196 : VImage::new_matrixv(4, 4,197 m[0], m[1], m[2], 0.0,198 m[3], m[4], m[5], 0.0,199 m[6], m[7], m[8], 0.0,200 0.0, 0.0, 0.0, 1.0));201 } else {202 return image.recomb(VImage::new_matrix(4, 4, m, 16));203 }204 }205 206 VImage Modulate(VImage image, double const brightness, double const saturation,207 int const hue, double const lightness) {208 VipsInterpretation colourspaceBeforeModulate = image.interpretation();209 if (image.has_alpha()) {210 // Separate alpha channel211 VImage alpha = image[image.bands() - 1];212 return RemoveAlpha(image)213 .colourspace(VIPS_INTERPRETATION_LCH)214 .linear(215 { brightness, saturation, 1},216 { lightness, 0.0, static_cast<double>(hue) }217 )218 .colourspace(colourspaceBeforeModulate)219 .bandjoin(alpha);220 } else {221 return image222 .colourspace(VIPS_INTERPRETATION_LCH)223 .linear(224 { brightness, saturation, 1 },225 { lightness, 0.0, static_cast<double>(hue) }226 )227 .colourspace(colourspaceBeforeModulate);228 }229 }230 231 /*232 * Sharpen flat and jagged areas. Use sigma of -1.0 for fast sharpen.233 */234 VImage Sharpen(VImage image, double const sigma, double const m1, double const m2,235 double const x1, double const y2, double const y3) {236 if (sigma == -1.0) {237 // Fast, mild sharpen238 VImage sharpen = VImage::new_matrixv(3, 3,239 -1.0, -1.0, -1.0,240 -1.0, 32.0, -1.0,241 -1.0, -1.0, -1.0);242 sharpen.set("scale", 24.0);243 return image.conv(sharpen);244 } else {245 // Slow, accurate sharpen in LAB colour space, with control over flat vs jagged areas246 VipsInterpretation colourspaceBeforeSharpen = image.interpretation();247 if (colourspaceBeforeSharpen == VIPS_INTERPRETATION_RGB) {248 colourspaceBeforeSharpen = VIPS_INTERPRETATION_sRGB;249 }250 return image251 .sharpen(VImage::option()252 ->set("sigma", sigma)253 ->set("m1", m1)254 ->set("m2", m2)255 ->set("x1", x1)256 ->set("y2", y2)257 ->set("y3", y3))258 .colourspace(colourspaceBeforeSharpen);259 }260 }261 262 VImage Threshold(VImage image, double const threshold, bool const thresholdGrayscale) {263 if (!thresholdGrayscale) {264 return image >= threshold;265 }266 return image.colourspace(VIPS_INTERPRETATION_B_W) >= threshold;267 }268 269 /*270 Perform boolean/bitwise operation on image color channels - results in one channel image271 */272 VImage Bandbool(VImage image, VipsOperationBoolean const boolean) {273 image = image.bandbool(boolean);274 return image.copy(VImage::option()->set("interpretation", VIPS_INTERPRETATION_B_W));275 }276 277 /*278 Perform bitwise boolean operation between images279 */280 VImage Boolean(VImage image, VImage imageR, VipsOperationBoolean const boolean) {281 return image.boolean(imageR, boolean);282 }283 284 /*285 Trim an image286 */287 VImage Trim(VImage image, std::vector<double> background, double threshold, bool const lineArt, int const margin) {288 if (image.width() < 3 && image.height() < 3) {289 throw std::runtime_error("Image to trim must be at least 3x3 pixels");290 }291 if (background.size() == 0) {292 // Top-left pixel provides the default background colour if none is given293 background = image.extract_area(0, 0, 1, 1)(0, 0);294 } else if (sharp::Is16Bit(image.interpretation())) {295 for (size_t i = 0; i < background.size(); i++) {296 background[i] *= 256.0;297 }298 threshold *= 256.0;299 }300 std::vector<double> backgroundAlpha({ background.back() });301 if (image.has_alpha()) {302 background.pop_back();303 } else {304 background.resize(image.bands());305 }306 int left, top, width, height;307 left = image.find_trim(&top, &width, &height, VImage::option()308 ->set("background", background)309 ->set("line_art", lineArt)310 ->set("threshold", threshold));311 if (image.has_alpha()) {312 // Search alpha channel (A)313 int leftA, topA, widthA, heightA;314 VImage alpha = image[image.bands() - 1];315 leftA = alpha.find_trim(&topA, &widthA, &heightA, VImage::option()316 ->set("background", backgroundAlpha)317 ->set("line_art", lineArt)318 ->set("threshold", threshold));319 if (widthA > 0 && heightA > 0) {320 if (width > 0 && height > 0) {321 // Combined bounding box (B)322 int leftB = std::min(left, leftA);323 int topB = std::min(top, topA);324 int widthB = std::max(left + width, leftA + widthA) - leftB;325 int heightB = std::max(top + height, topA + heightA) - topB;326 if (margin > 0) {327 leftB = std::max(0, leftB - margin);328 topB = std::max(0, topB - margin);329 widthB = std::min(image.width() - leftB, widthB + 2 * margin);330 heightB = std::min(image.height() - topB, heightB + 2 * margin);331 }332 return image.extract_area(leftB, topB, widthB, heightB);333 } else {334 // Use alpha only335 if (margin > 0) {336 leftA = std::max(0, leftA - margin);337 topA = std::max(0, topA - margin);338 widthA = std::min(image.width() - leftA, widthA + 2 * margin);339 heightA = std::min(image.height() - topA, heightA + 2 * margin);340 }341 return image.extract_area(leftA, topA, widthA, heightA);342 }343 }344 }345 if (width > 0 && height > 0) {346 if (margin > 0) {347 left = std::max(0, left - margin);348 top = std::max(0, top - margin);349 width = std::min(image.width() - left, width + 2 * margin);350 height = std::min(image.height() - top, height + 2 * margin);351 }352 return image.extract_area(left, top, width, height);353 }354 return image;355 }356 357 /*358 * Calculate (a * in + b)359 */360 VImage Linear(VImage image, std::vector<double> const a, std::vector<double> const b) {361 size_t const bands = static_cast<size_t>(image.bands());362 if (a.size() > bands) {363 throw std::runtime_error("Band expansion using linear is unsupported");364 }365 bool const uchar = !Is16Bit(image.interpretation());366 if (image.has_alpha() && a.size() != bands && (a.size() == 1 || a.size() == bands - 1 || bands - 1 == 1)) {367 // Separate alpha channel368 VImage alpha = image[bands - 1];369 return RemoveAlpha(image).linear(a, b, VImage::option()->set("uchar", uchar)).bandjoin(alpha);370 } else {371 return image.linear(a, b, VImage::option()->set("uchar", uchar));372 }373 }374 375 /*376 * Unflatten377 */378 VImage Unflatten(VImage image) {379 if (image.has_alpha()) {380 VImage alpha = image[image.bands() - 1];381 VImage noAlpha = RemoveAlpha(image);382 return noAlpha.bandjoin(alpha & (noAlpha.colourspace(VIPS_INTERPRETATION_B_W) < 255));383 } else {384 return image.bandjoin(image.colourspace(VIPS_INTERPRETATION_B_W) < 255);385 }386 }387 388 /*389 * Ensure the image is in a given colourspace390 */391 VImage EnsureColourspace(VImage image, VipsInterpretation colourspace) {392 if (colourspace != VIPS_INTERPRETATION_LAST && image.interpretation() != colourspace) {393 image = image.colourspace(colourspace,394 VImage::option()->set("source_space", image.interpretation()));395 }396 return image;397 }398 399 /*400 * Split and crop each frame, reassemble, and update pageHeight.401 */402 VImage CropMultiPage(VImage image, int left, int top, int width, int height,403 int nPages, int *pageHeight) {404 if (top == 0 && height == *pageHeight) {405 // Fast path; no need to adjust the height of the multi-page image406 return image.extract_area(left, 0, width, image.height());407 } else {408 std::vector<VImage> pages;409 pages.reserve(nPages);410 411 // Split the image into cropped frames412 image = StaySequential(image);413 for (int i = 0; i < nPages; i++) {414 pages.push_back(415 image.extract_area(left, *pageHeight * i + top, width, height));416 }417 418 // Reassemble the frames into a tall, thin image419 VImage assembled = VImage::arrayjoin(pages,420 VImage::option()->set("across", 1));421 422 // Update the page height423 *pageHeight = height;424 425 return assembled;426 }427 }428 429 /*430 * Split into frames, embed each frame, reassemble, and update pageHeight.431 */432 VImage EmbedMultiPage(VImage image, int left, int top, int width, int height,433 VipsExtend extendWith, std::vector<double> background, int nPages, int *pageHeight) {434 if (top == 0 && height == *pageHeight) {435 // Fast path; no need to adjust the height of the multi-page image436 return image.embed(left, 0, width, image.height(), VImage::option()437 ->set("extend", extendWith)438 ->set("background", background));439 } else if (left == 0 && width == image.width()) {440 // Fast path; no need to adjust the width of the multi-page image441 std::vector<VImage> pages;442 pages.reserve(nPages);443 444 // Rearrange the tall image into a vertical grid445 image = image.grid(*pageHeight, nPages, 1);446 447 // Do the embed on the wide image448 image = image.embed(0, top, image.width(), height, VImage::option()449 ->set("extend", extendWith)450 ->set("background", background));451 452 // Split the wide image into frames453 for (int i = 0; i < nPages; i++) {454 pages.push_back(455 image.extract_area(width * i, 0, width, height));456 }457 458 // Reassemble the frames into a tall, thin image459 VImage assembled = VImage::arrayjoin(pages,460 VImage::option()->set("across", 1));461 462 // Update the page height463 *pageHeight = height;464 465 return assembled;466 } else {467 std::vector<VImage> pages;468 pages.reserve(nPages);469 470 // Split the image into frames471 for (int i = 0; i < nPages; i++) {472 pages.push_back(473 image.extract_area(0, *pageHeight * i, image.width(), *pageHeight));474 }475 476 // Embed each frame in the target size477 for (int i = 0; i < nPages; i++) {478 pages[i] = pages[i].embed(left, top, width, height, VImage::option()479 ->set("extend", extendWith)480 ->set("background", background));481 }482 483 // Reassemble the frames into a tall, thin image484 VImage assembled = VImage::arrayjoin(pages,485 VImage::option()->set("across", 1));486 487 // Update the page height488 *pageHeight = height;489 490 return assembled;491 }492 }493 494 /*495 * Dilate an image496 */497 VImage Dilate(VImage image, int const width) {498 int const maskWidth = 2 * width + 1;499 VImage mask = VImage::new_matrix(maskWidth, maskWidth);500 return image.morph(501 mask,502 VIPS_OPERATION_MORPHOLOGY_DILATE).invert();503 }504 505 /*506 * Erode an image507 */508 VImage Erode(VImage image, int const width) {509 int const maskWidth = 2 * width + 1;510 VImage mask = VImage::new_matrix(maskWidth, maskWidth);511 return image.morph(512 mask,513 VIPS_OPERATION_MORPHOLOGY_ERODE).invert();514 }515 516} // namespace sharp517 