@guru-ai-product/ai-product-kit 0.2.251113194913 → 0.2.251113205658

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (129) hide show
  1. package/mcp/skills/aipk_init_project/template/AGENTS_TEMPLATE.md +1 -1
  2. package/mcp/src/server.js +1 -1
  3. package/package.json +1 -1
  4. package/skills/aipk_design/GURU_AI.md +119 -7
  5. package/skills/aipk_design/SKILL.md +8 -7
  6. package/skills/aipk_design/{auto_panel_splitter → update-requirements-from-design}/SKILL.md +18 -16
  7. package/skills/aipk_design/update-requirements-from-design/scripts/sharp-runtime/node_modules/.package-lock.json +113 -0
  8. package/skills/aipk_design/update-requirements-from-design/scripts/sharp-runtime/node_modules/@img/colour/LICENSE.md +82 -0
  9. package/skills/aipk_design/update-requirements-from-design/scripts/sharp-runtime/node_modules/@img/colour/README.md +15 -0
  10. package/skills/aipk_design/update-requirements-from-design/scripts/sharp-runtime/node_modules/@img/colour/color.cjs +1594 -0
  11. package/skills/aipk_design/update-requirements-from-design/scripts/sharp-runtime/node_modules/@img/colour/index.cjs +1 -0
  12. package/skills/aipk_design/update-requirements-from-design/scripts/sharp-runtime/node_modules/@img/colour/package.json +45 -0
  13. package/skills/aipk_design/update-requirements-from-design/scripts/sharp-runtime/node_modules/@img/sharp-darwin-arm64/LICENSE +191 -0
  14. package/skills/aipk_design/update-requirements-from-design/scripts/sharp-runtime/node_modules/@img/sharp-darwin-arm64/README.md +18 -0
  15. package/skills/aipk_design/update-requirements-from-design/scripts/sharp-runtime/node_modules/@img/sharp-darwin-arm64/lib/sharp-darwin-arm64.node +0 -0
  16. package/skills/aipk_design/update-requirements-from-design/scripts/sharp-runtime/node_modules/@img/sharp-darwin-arm64/package.json +40 -0
  17. package/skills/aipk_design/update-requirements-from-design/scripts/sharp-runtime/node_modules/@img/sharp-libvips-darwin-arm64/README.md +46 -0
  18. package/skills/aipk_design/update-requirements-from-design/scripts/sharp-runtime/node_modules/@img/sharp-libvips-darwin-arm64/lib/glib-2.0/include/glibconfig.h +220 -0
  19. package/skills/aipk_design/update-requirements-from-design/scripts/sharp-runtime/node_modules/@img/sharp-libvips-darwin-arm64/lib/index.js +1 -0
  20. package/skills/aipk_design/update-requirements-from-design/scripts/sharp-runtime/node_modules/@img/sharp-libvips-darwin-arm64/lib/libvips-cpp.8.17.3.dylib +0 -0
  21. package/skills/aipk_design/update-requirements-from-design/scripts/sharp-runtime/node_modules/@img/sharp-libvips-darwin-arm64/package.json +36 -0
  22. package/skills/aipk_design/update-requirements-from-design/scripts/sharp-runtime/node_modules/@img/sharp-libvips-darwin-arm64/versions.json +30 -0
  23. package/skills/aipk_design/update-requirements-from-design/scripts/sharp-runtime/node_modules/detect-libc/LICENSE +201 -0
  24. package/skills/aipk_design/update-requirements-from-design/scripts/sharp-runtime/node_modules/detect-libc/README.md +163 -0
  25. package/skills/aipk_design/update-requirements-from-design/scripts/sharp-runtime/node_modules/detect-libc/index.d.ts +14 -0
  26. package/skills/aipk_design/update-requirements-from-design/scripts/sharp-runtime/node_modules/detect-libc/lib/detect-libc.js +313 -0
  27. package/skills/aipk_design/update-requirements-from-design/scripts/sharp-runtime/node_modules/detect-libc/lib/elf.js +39 -0
  28. package/skills/aipk_design/update-requirements-from-design/scripts/sharp-runtime/node_modules/detect-libc/lib/filesystem.js +51 -0
  29. package/skills/aipk_design/update-requirements-from-design/scripts/sharp-runtime/node_modules/detect-libc/lib/process.js +24 -0
  30. package/skills/aipk_design/update-requirements-from-design/scripts/sharp-runtime/node_modules/detect-libc/package.json +44 -0
  31. package/skills/aipk_design/update-requirements-from-design/scripts/sharp-runtime/node_modules/semver/LICENSE +15 -0
  32. package/skills/aipk_design/update-requirements-from-design/scripts/sharp-runtime/node_modules/semver/README.md +664 -0
  33. package/skills/aipk_design/update-requirements-from-design/scripts/sharp-runtime/node_modules/semver/bin/semver.js +191 -0
  34. package/skills/aipk_design/update-requirements-from-design/scripts/sharp-runtime/node_modules/semver/classes/comparator.js +143 -0
  35. package/skills/aipk_design/update-requirements-from-design/scripts/sharp-runtime/node_modules/semver/classes/index.js +7 -0
  36. package/skills/aipk_design/update-requirements-from-design/scripts/sharp-runtime/node_modules/semver/classes/range.js +557 -0
  37. package/skills/aipk_design/update-requirements-from-design/scripts/sharp-runtime/node_modules/semver/classes/semver.js +333 -0
  38. package/skills/aipk_design/update-requirements-from-design/scripts/sharp-runtime/node_modules/semver/functions/clean.js +8 -0
  39. package/skills/aipk_design/update-requirements-from-design/scripts/sharp-runtime/node_modules/semver/functions/cmp.js +54 -0
  40. package/skills/aipk_design/update-requirements-from-design/scripts/sharp-runtime/node_modules/semver/functions/coerce.js +62 -0
  41. package/skills/aipk_design/update-requirements-from-design/scripts/sharp-runtime/node_modules/semver/functions/compare-build.js +9 -0
  42. package/skills/aipk_design/update-requirements-from-design/scripts/sharp-runtime/node_modules/semver/functions/compare-loose.js +5 -0
  43. package/skills/aipk_design/update-requirements-from-design/scripts/sharp-runtime/node_modules/semver/functions/compare.js +7 -0
  44. package/skills/aipk_design/update-requirements-from-design/scripts/sharp-runtime/node_modules/semver/functions/diff.js +60 -0
  45. package/skills/aipk_design/update-requirements-from-design/scripts/sharp-runtime/node_modules/semver/functions/eq.js +5 -0
  46. package/skills/aipk_design/update-requirements-from-design/scripts/sharp-runtime/node_modules/semver/functions/gt.js +5 -0
  47. package/skills/aipk_design/update-requirements-from-design/scripts/sharp-runtime/node_modules/semver/functions/gte.js +5 -0
  48. package/skills/aipk_design/update-requirements-from-design/scripts/sharp-runtime/node_modules/semver/functions/inc.js +21 -0
  49. package/skills/aipk_design/update-requirements-from-design/scripts/sharp-runtime/node_modules/semver/functions/lt.js +5 -0
  50. package/skills/aipk_design/update-requirements-from-design/scripts/sharp-runtime/node_modules/semver/functions/lte.js +5 -0
  51. package/skills/aipk_design/update-requirements-from-design/scripts/sharp-runtime/node_modules/semver/functions/major.js +5 -0
  52. package/skills/aipk_design/update-requirements-from-design/scripts/sharp-runtime/node_modules/semver/functions/minor.js +5 -0
  53. package/skills/aipk_design/update-requirements-from-design/scripts/sharp-runtime/node_modules/semver/functions/neq.js +5 -0
  54. package/skills/aipk_design/update-requirements-from-design/scripts/sharp-runtime/node_modules/semver/functions/parse.js +18 -0
  55. package/skills/aipk_design/update-requirements-from-design/scripts/sharp-runtime/node_modules/semver/functions/patch.js +5 -0
  56. package/skills/aipk_design/update-requirements-from-design/scripts/sharp-runtime/node_modules/semver/functions/prerelease.js +8 -0
  57. package/skills/aipk_design/update-requirements-from-design/scripts/sharp-runtime/node_modules/semver/functions/rcompare.js +5 -0
  58. package/skills/aipk_design/update-requirements-from-design/scripts/sharp-runtime/node_modules/semver/functions/rsort.js +5 -0
  59. package/skills/aipk_design/update-requirements-from-design/scripts/sharp-runtime/node_modules/semver/functions/satisfies.js +12 -0
  60. package/skills/aipk_design/update-requirements-from-design/scripts/sharp-runtime/node_modules/semver/functions/sort.js +5 -0
  61. package/skills/aipk_design/update-requirements-from-design/scripts/sharp-runtime/node_modules/semver/functions/valid.js +8 -0
  62. package/skills/aipk_design/update-requirements-from-design/scripts/sharp-runtime/node_modules/semver/index.js +91 -0
  63. package/skills/aipk_design/update-requirements-from-design/scripts/sharp-runtime/node_modules/semver/internal/constants.js +37 -0
  64. package/skills/aipk_design/update-requirements-from-design/scripts/sharp-runtime/node_modules/semver/internal/debug.js +11 -0
  65. package/skills/aipk_design/update-requirements-from-design/scripts/sharp-runtime/node_modules/semver/internal/identifiers.js +29 -0
  66. package/skills/aipk_design/update-requirements-from-design/scripts/sharp-runtime/node_modules/semver/internal/lrucache.js +42 -0
  67. package/skills/aipk_design/update-requirements-from-design/scripts/sharp-runtime/node_modules/semver/internal/parse-options.js +17 -0
  68. package/skills/aipk_design/update-requirements-from-design/scripts/sharp-runtime/node_modules/semver/internal/re.js +223 -0
  69. package/skills/aipk_design/update-requirements-from-design/scripts/sharp-runtime/node_modules/semver/package.json +78 -0
  70. package/skills/aipk_design/update-requirements-from-design/scripts/sharp-runtime/node_modules/semver/preload.js +4 -0
  71. package/skills/aipk_design/update-requirements-from-design/scripts/sharp-runtime/node_modules/semver/range.bnf +16 -0
  72. package/skills/aipk_design/update-requirements-from-design/scripts/sharp-runtime/node_modules/semver/ranges/gtr.js +6 -0
  73. package/skills/aipk_design/update-requirements-from-design/scripts/sharp-runtime/node_modules/semver/ranges/intersects.js +9 -0
  74. package/skills/aipk_design/update-requirements-from-design/scripts/sharp-runtime/node_modules/semver/ranges/ltr.js +6 -0
  75. package/skills/aipk_design/update-requirements-from-design/scripts/sharp-runtime/node_modules/semver/ranges/max-satisfying.js +27 -0
  76. package/skills/aipk_design/update-requirements-from-design/scripts/sharp-runtime/node_modules/semver/ranges/min-satisfying.js +26 -0
  77. package/skills/aipk_design/update-requirements-from-design/scripts/sharp-runtime/node_modules/semver/ranges/min-version.js +63 -0
  78. package/skills/aipk_design/update-requirements-from-design/scripts/sharp-runtime/node_modules/semver/ranges/outside.js +82 -0
  79. package/skills/aipk_design/update-requirements-from-design/scripts/sharp-runtime/node_modules/semver/ranges/simplify.js +49 -0
  80. package/skills/aipk_design/update-requirements-from-design/scripts/sharp-runtime/node_modules/semver/ranges/subset.js +249 -0
  81. package/skills/aipk_design/update-requirements-from-design/scripts/sharp-runtime/node_modules/semver/ranges/to-comparators.js +10 -0
  82. package/skills/aipk_design/update-requirements-from-design/scripts/sharp-runtime/node_modules/semver/ranges/valid.js +13 -0
  83. package/skills/aipk_design/update-requirements-from-design/scripts/sharp-runtime/node_modules/sharp/LICENSE +191 -0
  84. package/skills/aipk_design/update-requirements-from-design/scripts/sharp-runtime/node_modules/sharp/README.md +118 -0
  85. package/skills/aipk_design/update-requirements-from-design/scripts/sharp-runtime/node_modules/sharp/install/build.js +38 -0
  86. package/skills/aipk_design/update-requirements-from-design/scripts/sharp-runtime/node_modules/sharp/install/check.js +14 -0
  87. package/skills/aipk_design/update-requirements-from-design/scripts/sharp-runtime/node_modules/sharp/lib/channel.js +177 -0
  88. package/skills/aipk_design/update-requirements-from-design/scripts/sharp-runtime/node_modules/sharp/lib/colour.js +195 -0
  89. package/skills/aipk_design/update-requirements-from-design/scripts/sharp-runtime/node_modules/sharp/lib/composite.js +212 -0
  90. package/skills/aipk_design/update-requirements-from-design/scripts/sharp-runtime/node_modules/sharp/lib/constructor.js +499 -0
  91. package/skills/aipk_design/update-requirements-from-design/scripts/sharp-runtime/node_modules/sharp/lib/index.d.ts +1971 -0
  92. package/skills/aipk_design/update-requirements-from-design/scripts/sharp-runtime/node_modules/sharp/lib/index.js +16 -0
  93. package/skills/aipk_design/update-requirements-from-design/scripts/sharp-runtime/node_modules/sharp/lib/input.js +809 -0
  94. package/skills/aipk_design/update-requirements-from-design/scripts/sharp-runtime/node_modules/sharp/lib/is.js +143 -0
  95. package/skills/aipk_design/update-requirements-from-design/scripts/sharp-runtime/node_modules/sharp/lib/libvips.js +207 -0
  96. package/skills/aipk_design/update-requirements-from-design/scripts/sharp-runtime/node_modules/sharp/lib/operation.js +1016 -0
  97. package/skills/aipk_design/update-requirements-from-design/scripts/sharp-runtime/node_modules/sharp/lib/output.js +1666 -0
  98. package/skills/aipk_design/update-requirements-from-design/scripts/sharp-runtime/node_modules/sharp/lib/resize.js +595 -0
  99. package/skills/aipk_design/update-requirements-from-design/scripts/sharp-runtime/node_modules/sharp/lib/sharp.js +121 -0
  100. package/skills/aipk_design/update-requirements-from-design/scripts/sharp-runtime/node_modules/sharp/lib/utility.js +291 -0
  101. package/skills/aipk_design/update-requirements-from-design/scripts/sharp-runtime/node_modules/sharp/package.json +202 -0
  102. package/skills/aipk_design/update-requirements-from-design/scripts/sharp-runtime/node_modules/sharp/src/binding.gyp +298 -0
  103. package/skills/aipk_design/update-requirements-from-design/scripts/sharp-runtime/node_modules/sharp/src/common.cc +1130 -0
  104. package/skills/aipk_design/update-requirements-from-design/scripts/sharp-runtime/node_modules/sharp/src/common.h +402 -0
  105. package/skills/aipk_design/update-requirements-from-design/scripts/sharp-runtime/node_modules/sharp/src/metadata.cc +346 -0
  106. package/skills/aipk_design/update-requirements-from-design/scripts/sharp-runtime/node_modules/sharp/src/metadata.h +90 -0
  107. package/skills/aipk_design/update-requirements-from-design/scripts/sharp-runtime/node_modules/sharp/src/operations.cc +499 -0
  108. package/skills/aipk_design/update-requirements-from-design/scripts/sharp-runtime/node_modules/sharp/src/operations.h +137 -0
  109. package/skills/aipk_design/update-requirements-from-design/scripts/sharp-runtime/node_modules/sharp/src/pipeline.cc +1814 -0
  110. package/skills/aipk_design/update-requirements-from-design/scripts/sharp-runtime/node_modules/sharp/src/pipeline.h +408 -0
  111. package/skills/aipk_design/update-requirements-from-design/scripts/sharp-runtime/node_modules/sharp/src/sharp.cc +43 -0
  112. package/skills/aipk_design/update-requirements-from-design/scripts/sharp-runtime/node_modules/sharp/src/stats.cc +186 -0
  113. package/skills/aipk_design/update-requirements-from-design/scripts/sharp-runtime/node_modules/sharp/src/stats.h +62 -0
  114. package/skills/aipk_design/update-requirements-from-design/scripts/sharp-runtime/node_modules/sharp/src/utilities.cc +288 -0
  115. package/skills/aipk_design/update-requirements-from-design/scripts/sharp-runtime/node_modules/sharp/src/utilities.h +22 -0
  116. package/skills/aipk_design/update-requirements-from-design/scripts/sharp-runtime/package-lock.json +529 -0
  117. package/skills/aipk_design/update-requirements-from-design/scripts/sharp-runtime/package.json +5 -0
  118. package/skills/aipk_design/{auto_panel_splitter/scripts/auto_panel_splitter_bundle.js → update-requirements-from-design/scripts/split-design-boards-bundle.js} +10 -1
  119. package/skills/aipk_design/{auto_panel_splitter/scripts/panel_asset_mapper_bundle.js → update-requirements-from-design/scripts/sync-design-to-requirements-bundle.js} +10 -1
  120. package/skills/aipk_development/GURU_AI.md +1 -1
  121. package/skills/aipk_init_project/GURU_AI.md +2 -2
  122. package/skills/aipk_init_project/template/AGENTS_TEMPLATE.md +1 -1
  123. package/skills/aipk_operations/GURU_AI.md +1 -1
  124. package/skills/aipk_requirements/GURU_AI.md +2 -2
  125. package/skills/aipk_requirements/documentation/SKILL.md +23 -1
  126. package/skills/aipk_skill_generate/GURU_AI.md +1 -1
  127. package/skills/aipk_tool_prompts/GURU_AI.md +1 -1
  128. /package/skills/aipk_design/{auto_panel_splitter → update-requirements-from-design}/scripts/auto_panel_splitter.js +0 -0
  129. /package/skills/aipk_design/{auto_panel_splitter → update-requirements-from-design}/scripts/panel_asset_mapper.js +0 -0
@@ -0,0 +1,499 @@
1
+ /*!
2
+ Copyright 2013 Lovell Fuller and others.
3
+ SPDX-License-Identifier: Apache-2.0
4
+ */
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
+
16
+ using vips::VImage;
17
+ using vips::VError;
18
+
19
+ namespace sharp {
20
+ /*
21
+ * Tint an image using the provided RGB.
22
+ */
23
+ VImage Tint(VImage image, std::vector<double> const tint) {
24
+ std::vector<double> const tintLab = (VImage::black(1, 1) + tint)
25
+ .colourspace(VIPS_INTERPRETATION_LAB, VImage::option()->set("source_space", VIPS_INTERPRETATION_sRGB))
26
+ .getpoint(0, 0);
27
+ // LAB identity function
28
+ VImage identityLab = VImage::identity(VImage::option()->set("bands", 3))
29
+ .colourspace(VIPS_INTERPRETATION_LAB, VImage::option()->set("source_space", VIPS_INTERPRETATION_sRGB));
30
+ // Scale luminance range, 0.0 to 1.0
31
+ VImage l = identityLab[0] / 100;
32
+ // Weighting functions
33
+ VImage weightL = 1.0 - 4.0 * ((l - 0.5) * (l - 0.5));
34
+ VImage weightAB = (weightL * tintLab).extract_band(1, VImage::option()->set("n", 2));
35
+ identityLab = identityLab[0].bandjoin(weightAB);
36
+ // Convert lookup table to sRGB
37
+ VImage lut = identityLab.colourspace(VIPS_INTERPRETATION_sRGB,
38
+ VImage::option()->set("source_space", VIPS_INTERPRETATION_LAB));
39
+ // Original colourspace
40
+ VipsInterpretation typeBeforeTint = image.interpretation();
41
+ if (typeBeforeTint == VIPS_INTERPRETATION_RGB) {
42
+ typeBeforeTint = VIPS_INTERPRETATION_sRGB;
43
+ }
44
+ // Apply lookup table
45
+ if (image.has_alpha()) {
46
+ VImage alpha = image[image.bands() - 1];
47
+ image = RemoveAlpha(image)
48
+ .colourspace(VIPS_INTERPRETATION_B_W)
49
+ .maplut(lut)
50
+ .colourspace(typeBeforeTint)
51
+ .bandjoin(alpha);
52
+ } else {
53
+ image = image
54
+ .colourspace(VIPS_INTERPRETATION_B_W)
55
+ .maplut(lut)
56
+ .colourspace(typeBeforeTint);
57
+ }
58
+ return image;
59
+ }
60
+
61
+ /*
62
+ * Stretch luminance to cover full dynamic range.
63
+ */
64
+ VImage Normalise(VImage image, int const lower, int const upper) {
65
+ // Get original colourspace
66
+ VipsInterpretation typeBeforeNormalize = image.interpretation();
67
+ if (typeBeforeNormalize == VIPS_INTERPRETATION_RGB) {
68
+ typeBeforeNormalize = VIPS_INTERPRETATION_sRGB;
69
+ }
70
+ // Convert to LAB colourspace
71
+ VImage lab = image.colourspace(VIPS_INTERPRETATION_LAB);
72
+ // Extract luminance
73
+ VImage luminance = lab[0];
74
+
75
+ // Find luminance range
76
+ int const min = lower == 0 ? luminance.min() : luminance.percent(lower);
77
+ int const max = upper == 100 ? luminance.max() : luminance.percent(upper);
78
+
79
+ if (std::abs(max - min) > 1) {
80
+ // Extract chroma
81
+ VImage chroma = lab.extract_band(1, VImage::option()->set("n", 2));
82
+ // Calculate multiplication factor and addition
83
+ double f = 100.0 / (max - min);
84
+ double a = -(min * f);
85
+ // Scale luminance, join to chroma, convert back to original colourspace
86
+ VImage normalized = luminance.linear(f, a).bandjoin(chroma).colourspace(typeBeforeNormalize);
87
+ // Attach original alpha channel, if any
88
+ if (image.has_alpha()) {
89
+ // Extract original alpha channel
90
+ VImage alpha = image[image.bands() - 1];
91
+ // Join alpha channel to normalised image
92
+ return normalized.bandjoin(alpha);
93
+ } else {
94
+ return normalized;
95
+ }
96
+ }
97
+ return image;
98
+ }
99
+
100
+ /*
101
+ * Contrast limiting adapative histogram equalization (CLAHE)
102
+ */
103
+ VImage Clahe(VImage image, int const width, int const height, int const maxSlope) {
104
+ return image.hist_local(width, height, VImage::option()->set("max_slope", maxSlope));
105
+ }
106
+
107
+ /*
108
+ * Gamma encoding/decoding
109
+ */
110
+ VImage Gamma(VImage image, double const exponent) {
111
+ if (image.has_alpha()) {
112
+ // Separate alpha channel
113
+ VImage alpha = image[image.bands() - 1];
114
+ return RemoveAlpha(image).gamma(VImage::option()->set("exponent", exponent)).bandjoin(alpha);
115
+ } else {
116
+ return image.gamma(VImage::option()->set("exponent", exponent));
117
+ }
118
+ }
119
+
120
+ /*
121
+ * Flatten image to remove alpha channel
122
+ */
123
+ VImage Flatten(VImage image, std::vector<double> flattenBackground) {
124
+ double const multiplier = sharp::Is16Bit(image.interpretation()) ? 256.0 : 1.0;
125
+ std::vector<double> background {
126
+ flattenBackground[0] * multiplier,
127
+ flattenBackground[1] * multiplier,
128
+ flattenBackground[2] * multiplier
129
+ };
130
+ return image.flatten(VImage::option()->set("background", background));
131
+ }
132
+
133
+ /**
134
+ * Produce the "negative" of the image.
135
+ */
136
+ VImage Negate(VImage image, bool const negateAlpha) {
137
+ if (image.has_alpha() && !negateAlpha) {
138
+ // Separate alpha channel
139
+ VImage alpha = image[image.bands() - 1];
140
+ return RemoveAlpha(image).invert().bandjoin(alpha);
141
+ } else {
142
+ return image.invert();
143
+ }
144
+ }
145
+
146
+ /*
147
+ * Gaussian blur. Use sigma of -1.0 for fast blur.
148
+ */
149
+ VImage Blur(VImage image, double const sigma, VipsPrecision precision, double const minAmpl) {
150
+ if (sigma == -1.0) {
151
+ // Fast, mild blur - averages neighbouring pixels
152
+ VImage blur = VImage::new_matrixv(3, 3,
153
+ 1.0, 1.0, 1.0,
154
+ 1.0, 1.0, 1.0,
155
+ 1.0, 1.0, 1.0);
156
+ blur.set("scale", 9.0);
157
+ return image.conv(blur);
158
+ } else {
159
+ // Slower, accurate Gaussian blur
160
+ return StaySequential(image).gaussblur(sigma, VImage::option()
161
+ ->set("precision", precision)
162
+ ->set("min_ampl", minAmpl));
163
+ }
164
+ }
165
+
166
+ /*
167
+ * Convolution with a kernel.
168
+ */
169
+ VImage Convolve(VImage image, int const width, int const height,
170
+ double const scale, double const offset,
171
+ std::vector<double> const &kernel_v
172
+ ) {
173
+ VImage kernel = VImage::new_from_memory(
174
+ static_cast<void*>(const_cast<double*>(kernel_v.data())),
175
+ width * height * sizeof(double),
176
+ width,
177
+ height,
178
+ 1,
179
+ VIPS_FORMAT_DOUBLE);
180
+ kernel.set("scale", scale);
181
+ kernel.set("offset", offset);
182
+
183
+ return image.conv(kernel);
184
+ }
185
+
186
+ /*
187
+ * Recomb with a Matrix of the given bands/channel size.
188
+ * Eg. RGB will be a 3x3 matrix.
189
+ */
190
+ VImage Recomb(VImage image, std::vector<double> const& matrix) {
191
+ double* m = const_cast<double*>(matrix.data());
192
+ image = image.colourspace(VIPS_INTERPRETATION_sRGB);
193
+ if (matrix.size() == 9) {
194
+ return image
195
+ .recomb(image.bands() == 3
196
+ ? VImage::new_matrix(3, 3, m, 9)
197
+ : VImage::new_matrixv(4, 4,
198
+ m[0], m[1], m[2], 0.0,
199
+ m[3], m[4], m[5], 0.0,
200
+ m[6], m[7], m[8], 0.0,
201
+ 0.0, 0.0, 0.0, 1.0));
202
+ } else {
203
+ return image.recomb(VImage::new_matrix(4, 4, m, 16));
204
+ }
205
+ }
206
+
207
+ VImage Modulate(VImage image, double const brightness, double const saturation,
208
+ int const hue, double const lightness) {
209
+ VipsInterpretation colourspaceBeforeModulate = image.interpretation();
210
+ if (image.has_alpha()) {
211
+ // Separate alpha channel
212
+ VImage alpha = image[image.bands() - 1];
213
+ return RemoveAlpha(image)
214
+ .colourspace(VIPS_INTERPRETATION_LCH)
215
+ .linear(
216
+ { brightness, saturation, 1},
217
+ { lightness, 0.0, static_cast<double>(hue) }
218
+ )
219
+ .colourspace(colourspaceBeforeModulate)
220
+ .bandjoin(alpha);
221
+ } else {
222
+ return image
223
+ .colourspace(VIPS_INTERPRETATION_LCH)
224
+ .linear(
225
+ { brightness, saturation, 1 },
226
+ { lightness, 0.0, static_cast<double>(hue) }
227
+ )
228
+ .colourspace(colourspaceBeforeModulate);
229
+ }
230
+ }
231
+
232
+ /*
233
+ * Sharpen flat and jagged areas. Use sigma of -1.0 for fast sharpen.
234
+ */
235
+ VImage Sharpen(VImage image, double const sigma, double const m1, double const m2,
236
+ double const x1, double const y2, double const y3) {
237
+ if (sigma == -1.0) {
238
+ // Fast, mild sharpen
239
+ VImage sharpen = VImage::new_matrixv(3, 3,
240
+ -1.0, -1.0, -1.0,
241
+ -1.0, 32.0, -1.0,
242
+ -1.0, -1.0, -1.0);
243
+ sharpen.set("scale", 24.0);
244
+ return image.conv(sharpen);
245
+ } else {
246
+ // Slow, accurate sharpen in LAB colour space, with control over flat vs jagged areas
247
+ VipsInterpretation colourspaceBeforeSharpen = image.interpretation();
248
+ if (colourspaceBeforeSharpen == VIPS_INTERPRETATION_RGB) {
249
+ colourspaceBeforeSharpen = VIPS_INTERPRETATION_sRGB;
250
+ }
251
+ return image
252
+ .sharpen(VImage::option()
253
+ ->set("sigma", sigma)
254
+ ->set("m1", m1)
255
+ ->set("m2", m2)
256
+ ->set("x1", x1)
257
+ ->set("y2", y2)
258
+ ->set("y3", y3))
259
+ .colourspace(colourspaceBeforeSharpen);
260
+ }
261
+ }
262
+
263
+ VImage Threshold(VImage image, double const threshold, bool const thresholdGrayscale) {
264
+ if (!thresholdGrayscale) {
265
+ return image >= threshold;
266
+ }
267
+ return image.colourspace(VIPS_INTERPRETATION_B_W) >= threshold;
268
+ }
269
+
270
+ /*
271
+ Perform boolean/bitwise operation on image color channels - results in one channel image
272
+ */
273
+ VImage Bandbool(VImage image, VipsOperationBoolean const boolean) {
274
+ image = image.bandbool(boolean);
275
+ return image.copy(VImage::option()->set("interpretation", VIPS_INTERPRETATION_B_W));
276
+ }
277
+
278
+ /*
279
+ Perform bitwise boolean operation between images
280
+ */
281
+ VImage Boolean(VImage image, VImage imageR, VipsOperationBoolean const boolean) {
282
+ return image.boolean(imageR, boolean);
283
+ }
284
+
285
+ /*
286
+ Trim an image
287
+ */
288
+ VImage Trim(VImage image, std::vector<double> background, double threshold, bool const lineArt) {
289
+ if (image.width() < 3 && image.height() < 3) {
290
+ throw VError("Image to trim must be at least 3x3 pixels");
291
+ }
292
+ if (background.size() == 0) {
293
+ // Top-left pixel provides the default background colour if none is given
294
+ background = image.extract_area(0, 0, 1, 1)(0, 0);
295
+ } else if (sharp::Is16Bit(image.interpretation())) {
296
+ for (size_t i = 0; i < background.size(); i++) {
297
+ background[i] *= 256.0;
298
+ }
299
+ threshold *= 256.0;
300
+ }
301
+ std::vector<double> backgroundAlpha({ background.back() });
302
+ if (image.has_alpha()) {
303
+ background.pop_back();
304
+ } else {
305
+ background.resize(image.bands());
306
+ }
307
+ int left, top, width, height;
308
+ left = image.find_trim(&top, &width, &height, VImage::option()
309
+ ->set("background", background)
310
+ ->set("line_art", lineArt)
311
+ ->set("threshold", threshold));
312
+ if (image.has_alpha()) {
313
+ // Search alpha channel (A)
314
+ int leftA, topA, widthA, heightA;
315
+ VImage alpha = image[image.bands() - 1];
316
+ leftA = alpha.find_trim(&topA, &widthA, &heightA, VImage::option()
317
+ ->set("background", backgroundAlpha)
318
+ ->set("line_art", lineArt)
319
+ ->set("threshold", threshold));
320
+ if (widthA > 0 && heightA > 0) {
321
+ if (width > 0 && height > 0) {
322
+ // Combined bounding box (B)
323
+ int const leftB = std::min(left, leftA);
324
+ int const topB = std::min(top, topA);
325
+ int const widthB = std::max(left + width, leftA + widthA) - leftB;
326
+ int const heightB = std::max(top + height, topA + heightA) - topB;
327
+ return image.extract_area(leftB, topB, widthB, heightB);
328
+ } else {
329
+ // Use alpha only
330
+ return image.extract_area(leftA, topA, widthA, heightA);
331
+ }
332
+ }
333
+ }
334
+ if (width > 0 && height > 0) {
335
+ return image.extract_area(left, top, width, height);
336
+ }
337
+ return image;
338
+ }
339
+
340
+ /*
341
+ * Calculate (a * in + b)
342
+ */
343
+ VImage Linear(VImage image, std::vector<double> const a, std::vector<double> const b) {
344
+ size_t const bands = static_cast<size_t>(image.bands());
345
+ if (a.size() > bands) {
346
+ throw VError("Band expansion using linear is unsupported");
347
+ }
348
+ bool const uchar = !Is16Bit(image.interpretation());
349
+ if (image.has_alpha() && a.size() != bands && (a.size() == 1 || a.size() == bands - 1 || bands - 1 == 1)) {
350
+ // Separate alpha channel
351
+ VImage alpha = image[bands - 1];
352
+ return RemoveAlpha(image).linear(a, b, VImage::option()->set("uchar", uchar)).bandjoin(alpha);
353
+ } else {
354
+ return image.linear(a, b, VImage::option()->set("uchar", uchar));
355
+ }
356
+ }
357
+
358
+ /*
359
+ * Unflatten
360
+ */
361
+ VImage Unflatten(VImage image) {
362
+ if (image.has_alpha()) {
363
+ VImage alpha = image[image.bands() - 1];
364
+ VImage noAlpha = RemoveAlpha(image);
365
+ return noAlpha.bandjoin(alpha & (noAlpha.colourspace(VIPS_INTERPRETATION_B_W) < 255));
366
+ } else {
367
+ return image.bandjoin(image.colourspace(VIPS_INTERPRETATION_B_W) < 255);
368
+ }
369
+ }
370
+
371
+ /*
372
+ * Ensure the image is in a given colourspace
373
+ */
374
+ VImage EnsureColourspace(VImage image, VipsInterpretation colourspace) {
375
+ if (colourspace != VIPS_INTERPRETATION_LAST && image.interpretation() != colourspace) {
376
+ image = image.colourspace(colourspace,
377
+ VImage::option()->set("source_space", image.interpretation()));
378
+ }
379
+ return image;
380
+ }
381
+
382
+ /*
383
+ * Split and crop each frame, reassemble, and update pageHeight.
384
+ */
385
+ VImage CropMultiPage(VImage image, int left, int top, int width, int height,
386
+ int nPages, int *pageHeight) {
387
+ if (top == 0 && height == *pageHeight) {
388
+ // Fast path; no need to adjust the height of the multi-page image
389
+ return image.extract_area(left, 0, width, image.height());
390
+ } else {
391
+ std::vector<VImage> pages;
392
+ pages.reserve(nPages);
393
+
394
+ // Split the image into cropped frames
395
+ image = StaySequential(image);
396
+ for (int i = 0; i < nPages; i++) {
397
+ pages.push_back(
398
+ image.extract_area(left, *pageHeight * i + top, width, height));
399
+ }
400
+
401
+ // Reassemble the frames into a tall, thin image
402
+ VImage assembled = VImage::arrayjoin(pages,
403
+ VImage::option()->set("across", 1));
404
+
405
+ // Update the page height
406
+ *pageHeight = height;
407
+
408
+ return assembled;
409
+ }
410
+ }
411
+
412
+ /*
413
+ * Split into frames, embed each frame, reassemble, and update pageHeight.
414
+ */
415
+ VImage EmbedMultiPage(VImage image, int left, int top, int width, int height,
416
+ VipsExtend extendWith, std::vector<double> background, int nPages, int *pageHeight) {
417
+ if (top == 0 && height == *pageHeight) {
418
+ // Fast path; no need to adjust the height of the multi-page image
419
+ return image.embed(left, 0, width, image.height(), VImage::option()
420
+ ->set("extend", extendWith)
421
+ ->set("background", background));
422
+ } else if (left == 0 && width == image.width()) {
423
+ // Fast path; no need to adjust the width of the multi-page image
424
+ std::vector<VImage> pages;
425
+ pages.reserve(nPages);
426
+
427
+ // Rearrange the tall image into a vertical grid
428
+ image = image.grid(*pageHeight, nPages, 1);
429
+
430
+ // Do the embed on the wide image
431
+ image = image.embed(0, top, image.width(), height, VImage::option()
432
+ ->set("extend", extendWith)
433
+ ->set("background", background));
434
+
435
+ // Split the wide image into frames
436
+ for (int i = 0; i < nPages; i++) {
437
+ pages.push_back(
438
+ image.extract_area(width * i, 0, width, height));
439
+ }
440
+
441
+ // Reassemble the frames into a tall, thin image
442
+ VImage assembled = VImage::arrayjoin(pages,
443
+ VImage::option()->set("across", 1));
444
+
445
+ // Update the page height
446
+ *pageHeight = height;
447
+
448
+ return assembled;
449
+ } else {
450
+ std::vector<VImage> pages;
451
+ pages.reserve(nPages);
452
+
453
+ // Split the image into frames
454
+ for (int i = 0; i < nPages; i++) {
455
+ pages.push_back(
456
+ image.extract_area(0, *pageHeight * i, image.width(), *pageHeight));
457
+ }
458
+
459
+ // Embed each frame in the target size
460
+ for (int i = 0; i < nPages; i++) {
461
+ pages[i] = pages[i].embed(left, top, width, height, VImage::option()
462
+ ->set("extend", extendWith)
463
+ ->set("background", background));
464
+ }
465
+
466
+ // Reassemble the frames into a tall, thin image
467
+ VImage assembled = VImage::arrayjoin(pages,
468
+ VImage::option()->set("across", 1));
469
+
470
+ // Update the page height
471
+ *pageHeight = height;
472
+
473
+ return assembled;
474
+ }
475
+ }
476
+
477
+ /*
478
+ * Dilate an image
479
+ */
480
+ VImage Dilate(VImage image, int const width) {
481
+ int const maskWidth = 2 * width + 1;
482
+ VImage mask = VImage::new_matrix(maskWidth, maskWidth);
483
+ return image.morph(
484
+ mask,
485
+ VIPS_OPERATION_MORPHOLOGY_DILATE).invert();
486
+ }
487
+
488
+ /*
489
+ * Erode an image
490
+ */
491
+ VImage Erode(VImage image, int const width) {
492
+ int const maskWidth = 2 * width + 1;
493
+ VImage mask = VImage::new_matrix(maskWidth, maskWidth);
494
+ return image.morph(
495
+ mask,
496
+ VIPS_OPERATION_MORPHOLOGY_ERODE).invert();
497
+ }
498
+
499
+ } // namespace sharp
@@ -0,0 +1,137 @@
1
+ /*!
2
+ Copyright 2013 Lovell Fuller and others.
3
+ SPDX-License-Identifier: Apache-2.0
4
+ */
5
+
6
+ #ifndef SRC_OPERATIONS_H_
7
+ #define SRC_OPERATIONS_H_
8
+
9
+ #include <algorithm>
10
+ #include <functional>
11
+ #include <memory>
12
+ #include <tuple>
13
+ #include <vector>
14
+ #include <vips/vips8>
15
+
16
+ using vips::VImage;
17
+
18
+ namespace sharp {
19
+
20
+ /*
21
+ * Tint an image using the provided RGB.
22
+ */
23
+ VImage Tint(VImage image, std::vector<double> const tint);
24
+
25
+ /*
26
+ * Stretch luminance to cover full dynamic range.
27
+ */
28
+ VImage Normalise(VImage image, int const lower, int const upper);
29
+
30
+ /*
31
+ * Contrast limiting adapative histogram equalization (CLAHE)
32
+ */
33
+ VImage Clahe(VImage image, int const width, int const height, int const maxSlope);
34
+
35
+ /*
36
+ * Gamma encoding/decoding
37
+ */
38
+ VImage Gamma(VImage image, double const exponent);
39
+
40
+ /*
41
+ * Flatten image to remove alpha channel
42
+ */
43
+ VImage Flatten(VImage image, std::vector<double> flattenBackground);
44
+
45
+ /*
46
+ * Produce the "negative" of the image.
47
+ */
48
+ VImage Negate(VImage image, bool const negateAlpha);
49
+
50
+ /*
51
+ * Gaussian blur. Use sigma of -1.0 for fast blur.
52
+ */
53
+ VImage Blur(VImage image, double const sigma, VipsPrecision precision, double const minAmpl);
54
+
55
+ /*
56
+ * Convolution with a kernel.
57
+ */
58
+ VImage Convolve(VImage image, int const width, int const height,
59
+ double const scale, double const offset, std::vector<double> const &kernel_v);
60
+
61
+ /*
62
+ * Sharpen flat and jagged areas. Use sigma of -1.0 for fast sharpen.
63
+ */
64
+ VImage Sharpen(VImage image, double const sigma, double const m1, double const m2,
65
+ double const x1, double const y2, double const y3);
66
+
67
+ /*
68
+ Threshold an image
69
+ */
70
+ VImage Threshold(VImage image, double const threshold, bool const thresholdColor);
71
+
72
+ /*
73
+ Perform boolean/bitwise operation on image color channels - results in one channel image
74
+ */
75
+ VImage Bandbool(VImage image, VipsOperationBoolean const boolean);
76
+
77
+ /*
78
+ Perform bitwise boolean operation between images
79
+ */
80
+ VImage Boolean(VImage image, VImage imageR, VipsOperationBoolean const boolean);
81
+
82
+ /*
83
+ Trim an image
84
+ */
85
+ VImage Trim(VImage image, std::vector<double> background, double threshold, bool const lineArt);
86
+
87
+ /*
88
+ * Linear adjustment (a * in + b)
89
+ */
90
+ VImage Linear(VImage image, std::vector<double> const a, std::vector<double> const b);
91
+
92
+ /*
93
+ * Unflatten
94
+ */
95
+ VImage Unflatten(VImage image);
96
+
97
+ /*
98
+ * Recomb with a Matrix of the given bands/channel size.
99
+ * Eg. RGB will be a 3x3 matrix.
100
+ */
101
+ VImage Recomb(VImage image, std::vector<double> const &matrix);
102
+
103
+ /*
104
+ * Modulate brightness, saturation, hue and lightness
105
+ */
106
+ VImage Modulate(VImage image, double const brightness, double const saturation,
107
+ int const hue, double const lightness);
108
+
109
+ /*
110
+ * Ensure the image is in a given colourspace
111
+ */
112
+ VImage EnsureColourspace(VImage image, VipsInterpretation colourspace);
113
+
114
+ /*
115
+ * Split and crop each frame, reassemble, and update pageHeight.
116
+ */
117
+ VImage CropMultiPage(VImage image, int left, int top, int width, int height,
118
+ int nPages, int *pageHeight);
119
+
120
+ /*
121
+ * Split into frames, embed each frame, reassemble, and update pageHeight.
122
+ */
123
+ VImage EmbedMultiPage(VImage image, int left, int top, int width, int height,
124
+ VipsExtend extendWith, std::vector<double> background, int nPages, int *pageHeight);
125
+
126
+ /*
127
+ * Dilate an image
128
+ */
129
+ VImage Dilate(VImage image, int const maskWidth);
130
+
131
+ /*
132
+ * Erode an image
133
+ */
134
+ VImage Erode(VImage image, int const maskWidth);
135
+ } // namespace sharp
136
+
137
+ #endif // SRC_OPERATIONS_H_