@basemaps/lambda-tiler 6.40.0 → 6.43.0

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 (461) hide show
  1. package/CHANGELOG.md +44 -0
  2. package/build/__tests__/index.test.js +17 -5
  3. package/build/__tests__/index.test.js.map +1 -1
  4. package/build/__tests__/wmts.capability.test.js +98 -65
  5. package/build/__tests__/wmts.capability.test.js.map +1 -1
  6. package/build/cli/render.tile.js +28 -10
  7. package/build/cli/render.tile.js.map +1 -1
  8. package/build/routes/__tests__/attribution.test.js +2 -2
  9. package/build/routes/__tests__/attribution.test.js.map +1 -1
  10. package/build/routes/attribution.d.ts +1 -2
  11. package/build/routes/attribution.d.ts.map +1 -1
  12. package/build/routes/attribution.js +13 -13
  13. package/build/routes/attribution.js.map +1 -1
  14. package/build/routes/tile.wmts.d.ts.map +1 -1
  15. package/build/routes/tile.wmts.js +11 -8
  16. package/build/routes/tile.wmts.js.map +1 -1
  17. package/build/routes/tile.xyz.raster.d.ts.map +1 -1
  18. package/build/routes/tile.xyz.raster.js +0 -2
  19. package/build/routes/tile.xyz.raster.js.map +1 -1
  20. package/build/routes/version.d.ts.map +1 -1
  21. package/build/routes/version.js +17 -1
  22. package/build/routes/version.js.map +1 -1
  23. package/build/util/validate.d.ts.map +1 -1
  24. package/build/util/validate.js +4 -3
  25. package/build/util/validate.js.map +1 -1
  26. package/build/wmts.capability.d.ts +58 -28
  27. package/build/wmts.capability.d.ts.map +1 -1
  28. package/build/wmts.capability.js +167 -93
  29. package/build/wmts.capability.js.map +1 -1
  30. package/package.json +9 -10
  31. package/src/__tests__/index.test.ts +20 -5
  32. package/src/__tests__/wmts.capability.test.ts +110 -65
  33. package/src/cli/render.tile.ts +29 -10
  34. package/src/routes/__tests__/attribution.test.ts +2 -2
  35. package/src/routes/attribution.ts +13 -11
  36. package/src/routes/tile.wmts.ts +12 -7
  37. package/src/routes/tile.xyz.raster.ts +0 -1
  38. package/src/routes/version.ts +17 -1
  39. package/src/util/validate.ts +4 -3
  40. package/src/wmts.capability.ts +209 -121
  41. package/tsconfig.tsbuildinfo +1 -1
  42. package/dist/index.js +0 -201
  43. package/dist/node_modules/.package-lock.json +0 -491
  44. package/dist/node_modules/base64-js/LICENSE +0 -21
  45. package/dist/node_modules/base64-js/README.md +0 -34
  46. package/dist/node_modules/base64-js/base64js.min.js +0 -1
  47. package/dist/node_modules/base64-js/index.d.ts +0 -3
  48. package/dist/node_modules/base64-js/index.js +0 -150
  49. package/dist/node_modules/base64-js/package.json +0 -47
  50. package/dist/node_modules/bl/.travis.yml +0 -17
  51. package/dist/node_modules/bl/BufferList.js +0 -396
  52. package/dist/node_modules/bl/LICENSE.md +0 -13
  53. package/dist/node_modules/bl/README.md +0 -247
  54. package/dist/node_modules/bl/bl.js +0 -84
  55. package/dist/node_modules/bl/package.json +0 -37
  56. package/dist/node_modules/bl/test/convert.js +0 -21
  57. package/dist/node_modules/bl/test/indexOf.js +0 -492
  58. package/dist/node_modules/bl/test/isBufferList.js +0 -32
  59. package/dist/node_modules/bl/test/test.js +0 -869
  60. package/dist/node_modules/buffer/AUTHORS.md +0 -70
  61. package/dist/node_modules/buffer/LICENSE +0 -21
  62. package/dist/node_modules/buffer/README.md +0 -410
  63. package/dist/node_modules/buffer/index.d.ts +0 -186
  64. package/dist/node_modules/buffer/index.js +0 -1817
  65. package/dist/node_modules/buffer/package.json +0 -96
  66. package/dist/node_modules/chownr/LICENSE +0 -15
  67. package/dist/node_modules/chownr/README.md +0 -3
  68. package/dist/node_modules/chownr/chownr.js +0 -167
  69. package/dist/node_modules/chownr/package.json +0 -29
  70. package/dist/node_modules/color/LICENSE +0 -21
  71. package/dist/node_modules/color/README.md +0 -123
  72. package/dist/node_modules/color/index.js +0 -496
  73. package/dist/node_modules/color/package.json +0 -47
  74. package/dist/node_modules/color-convert/CHANGELOG.md +0 -54
  75. package/dist/node_modules/color-convert/LICENSE +0 -21
  76. package/dist/node_modules/color-convert/README.md +0 -68
  77. package/dist/node_modules/color-convert/conversions.js +0 -839
  78. package/dist/node_modules/color-convert/index.js +0 -81
  79. package/dist/node_modules/color-convert/package.json +0 -48
  80. package/dist/node_modules/color-convert/route.js +0 -97
  81. package/dist/node_modules/color-name/LICENSE +0 -8
  82. package/dist/node_modules/color-name/README.md +0 -11
  83. package/dist/node_modules/color-name/index.js +0 -152
  84. package/dist/node_modules/color-name/package.json +0 -28
  85. package/dist/node_modules/color-string/LICENSE +0 -21
  86. package/dist/node_modules/color-string/README.md +0 -62
  87. package/dist/node_modules/color-string/index.js +0 -242
  88. package/dist/node_modules/color-string/package.json +0 -39
  89. package/dist/node_modules/decompress-response/index.d.ts +0 -22
  90. package/dist/node_modules/decompress-response/index.js +0 -58
  91. package/dist/node_modules/decompress-response/license +0 -9
  92. package/dist/node_modules/decompress-response/package.json +0 -56
  93. package/dist/node_modules/decompress-response/readme.md +0 -48
  94. package/dist/node_modules/deep-extend/CHANGELOG.md +0 -46
  95. package/dist/node_modules/deep-extend/LICENSE +0 -20
  96. package/dist/node_modules/deep-extend/README.md +0 -91
  97. package/dist/node_modules/deep-extend/index.js +0 -1
  98. package/dist/node_modules/deep-extend/lib/deep-extend.js +0 -150
  99. package/dist/node_modules/deep-extend/package.json +0 -62
  100. package/dist/node_modules/detect-libc/LICENSE +0 -201
  101. package/dist/node_modules/detect-libc/README.md +0 -160
  102. package/dist/node_modules/detect-libc/index.d.ts +0 -11
  103. package/dist/node_modules/detect-libc/lib/detect-libc.js +0 -178
  104. package/dist/node_modules/detect-libc/lib/process.js +0 -16
  105. package/dist/node_modules/detect-libc/package.json +0 -36
  106. package/dist/node_modules/end-of-stream/LICENSE +0 -21
  107. package/dist/node_modules/end-of-stream/README.md +0 -54
  108. package/dist/node_modules/end-of-stream/index.js +0 -94
  109. package/dist/node_modules/end-of-stream/package.json +0 -37
  110. package/dist/node_modules/expand-template/.travis.yml +0 -6
  111. package/dist/node_modules/expand-template/LICENSE +0 -21
  112. package/dist/node_modules/expand-template/README.md +0 -43
  113. package/dist/node_modules/expand-template/index.js +0 -26
  114. package/dist/node_modules/expand-template/package.json +0 -29
  115. package/dist/node_modules/expand-template/test.js +0 -67
  116. package/dist/node_modules/fs-constants/LICENSE +0 -21
  117. package/dist/node_modules/fs-constants/README.md +0 -26
  118. package/dist/node_modules/fs-constants/browser.js +0 -1
  119. package/dist/node_modules/fs-constants/index.js +0 -1
  120. package/dist/node_modules/fs-constants/package.json +0 -19
  121. package/dist/node_modules/github-from-package/.travis.yml +0 -4
  122. package/dist/node_modules/github-from-package/LICENSE +0 -18
  123. package/dist/node_modules/github-from-package/example/package.json +0 -8
  124. package/dist/node_modules/github-from-package/example/url.js +0 -3
  125. package/dist/node_modules/github-from-package/index.js +0 -17
  126. package/dist/node_modules/github-from-package/package.json +0 -30
  127. package/dist/node_modules/github-from-package/readme.markdown +0 -53
  128. package/dist/node_modules/github-from-package/test/a.json +0 -8
  129. package/dist/node_modules/github-from-package/test/b.json +0 -5
  130. package/dist/node_modules/github-from-package/test/c.json +0 -5
  131. package/dist/node_modules/github-from-package/test/d.json +0 -7
  132. package/dist/node_modules/github-from-package/test/e.json +0 -5
  133. package/dist/node_modules/github-from-package/test/url.js +0 -19
  134. package/dist/node_modules/ieee754/LICENSE +0 -11
  135. package/dist/node_modules/ieee754/README.md +0 -51
  136. package/dist/node_modules/ieee754/index.d.ts +0 -10
  137. package/dist/node_modules/ieee754/index.js +0 -85
  138. package/dist/node_modules/ieee754/package.json +0 -52
  139. package/dist/node_modules/inherits/LICENSE +0 -16
  140. package/dist/node_modules/inherits/README.md +0 -42
  141. package/dist/node_modules/inherits/inherits.js +0 -9
  142. package/dist/node_modules/inherits/inherits_browser.js +0 -27
  143. package/dist/node_modules/inherits/package.json +0 -29
  144. package/dist/node_modules/ini/LICENSE +0 -15
  145. package/dist/node_modules/ini/README.md +0 -102
  146. package/dist/node_modules/ini/ini.js +0 -206
  147. package/dist/node_modules/ini/package.json +0 -33
  148. package/dist/node_modules/is-arrayish/LICENSE +0 -21
  149. package/dist/node_modules/is-arrayish/README.md +0 -16
  150. package/dist/node_modules/is-arrayish/index.js +0 -9
  151. package/dist/node_modules/is-arrayish/package.json +0 -45
  152. package/dist/node_modules/is-arrayish/yarn-error.log +0 -1443
  153. package/dist/node_modules/lru-cache/LICENSE +0 -15
  154. package/dist/node_modules/lru-cache/README.md +0 -166
  155. package/dist/node_modules/lru-cache/index.js +0 -334
  156. package/dist/node_modules/lru-cache/package.json +0 -34
  157. package/dist/node_modules/mimic-response/index.d.ts +0 -17
  158. package/dist/node_modules/mimic-response/index.js +0 -77
  159. package/dist/node_modules/mimic-response/license +0 -9
  160. package/dist/node_modules/mimic-response/package.json +0 -42
  161. package/dist/node_modules/mimic-response/readme.md +0 -78
  162. package/dist/node_modules/minimist/.eslintrc +0 -29
  163. package/dist/node_modules/minimist/.github/FUNDING.yml +0 -12
  164. package/dist/node_modules/minimist/.nycrc +0 -14
  165. package/dist/node_modules/minimist/CHANGELOG.md +0 -298
  166. package/dist/node_modules/minimist/LICENSE +0 -18
  167. package/dist/node_modules/minimist/README.md +0 -121
  168. package/dist/node_modules/minimist/example/parse.js +0 -4
  169. package/dist/node_modules/minimist/index.js +0 -263
  170. package/dist/node_modules/minimist/package.json +0 -75
  171. package/dist/node_modules/minimist/test/all_bool.js +0 -34
  172. package/dist/node_modules/minimist/test/bool.js +0 -177
  173. package/dist/node_modules/minimist/test/dash.js +0 -43
  174. package/dist/node_modules/minimist/test/default_bool.js +0 -37
  175. package/dist/node_modules/minimist/test/dotted.js +0 -24
  176. package/dist/node_modules/minimist/test/kv_short.js +0 -32
  177. package/dist/node_modules/minimist/test/long.js +0 -33
  178. package/dist/node_modules/minimist/test/num.js +0 -38
  179. package/dist/node_modules/minimist/test/parse.js +0 -209
  180. package/dist/node_modules/minimist/test/parse_modified.js +0 -11
  181. package/dist/node_modules/minimist/test/proto.js +0 -64
  182. package/dist/node_modules/minimist/test/short.js +0 -69
  183. package/dist/node_modules/minimist/test/stop_early.js +0 -17
  184. package/dist/node_modules/minimist/test/unknown.js +0 -104
  185. package/dist/node_modules/minimist/test/whitespace.js +0 -10
  186. package/dist/node_modules/mkdirp-classic/LICENSE +0 -21
  187. package/dist/node_modules/mkdirp-classic/README.md +0 -18
  188. package/dist/node_modules/mkdirp-classic/index.js +0 -98
  189. package/dist/node_modules/mkdirp-classic/package.json +0 -18
  190. package/dist/node_modules/napi-build-utils/LICENSE +0 -21
  191. package/dist/node_modules/napi-build-utils/README.md +0 -48
  192. package/dist/node_modules/napi-build-utils/index.js +0 -213
  193. package/dist/node_modules/napi-build-utils/index.md +0 -81
  194. package/dist/node_modules/napi-build-utils/package.json +0 -41
  195. package/dist/node_modules/node-abi/.circleci/config.yml +0 -45
  196. package/dist/node_modules/node-abi/.github/CODEOWNERS +0 -1
  197. package/dist/node_modules/node-abi/.github/workflows/update-abi.yml +0 -42
  198. package/dist/node_modules/node-abi/.releaserc.json +0 -9
  199. package/dist/node_modules/node-abi/CODE_OF_CONDUCT.md +0 -73
  200. package/dist/node_modules/node-abi/CONTRIBUTING.md +0 -62
  201. package/dist/node_modules/node-abi/LICENSE +0 -21
  202. package/dist/node_modules/node-abi/README.md +0 -52
  203. package/dist/node_modules/node-abi/abi_registry.json +0 -245
  204. package/dist/node_modules/node-abi/index.js +0 -179
  205. package/dist/node_modules/node-abi/package.json +0 -38
  206. package/dist/node_modules/node-abi/scripts/update-abi-registry.js +0 -119
  207. package/dist/node_modules/node-abi/test/index.js +0 -166
  208. package/dist/node_modules/node-addon-api/LICENSE.md +0 -13
  209. package/dist/node_modules/node-addon-api/README.md +0 -317
  210. package/dist/node_modules/node-addon-api/common.gypi +0 -21
  211. package/dist/node_modules/node-addon-api/except.gypi +0 -25
  212. package/dist/node_modules/node-addon-api/index.js +0 -11
  213. package/dist/node_modules/node-addon-api/napi-inl.deprecated.h +0 -186
  214. package/dist/node_modules/node-addon-api/napi-inl.h +0 -6303
  215. package/dist/node_modules/node-addon-api/napi.h +0 -3114
  216. package/dist/node_modules/node-addon-api/node_api.gyp +0 -9
  217. package/dist/node_modules/node-addon-api/noexcept.gypi +0 -26
  218. package/dist/node_modules/node-addon-api/nothing.c +0 -0
  219. package/dist/node_modules/node-addon-api/package-support.json +0 -21
  220. package/dist/node_modules/node-addon-api/package.json +0 -456
  221. package/dist/node_modules/node-addon-api/tools/README.md +0 -73
  222. package/dist/node_modules/node-addon-api/tools/check-napi.js +0 -99
  223. package/dist/node_modules/node-addon-api/tools/clang-format.js +0 -71
  224. package/dist/node_modules/node-addon-api/tools/conversion.js +0 -301
  225. package/dist/node_modules/node-addon-api/tools/eslint-format.js +0 -79
  226. package/dist/node_modules/once/LICENSE +0 -15
  227. package/dist/node_modules/once/README.md +0 -79
  228. package/dist/node_modules/once/once.js +0 -42
  229. package/dist/node_modules/once/package.json +0 -33
  230. package/dist/node_modules/prebuild-install/CHANGELOG.md +0 -116
  231. package/dist/node_modules/prebuild-install/CONTRIBUTING.md +0 -6
  232. package/dist/node_modules/prebuild-install/LICENSE +0 -21
  233. package/dist/node_modules/prebuild-install/README.md +0 -163
  234. package/dist/node_modules/prebuild-install/asset.js +0 -44
  235. package/dist/node_modules/prebuild-install/bin.js +0 -78
  236. package/dist/node_modules/prebuild-install/download.js +0 -142
  237. package/dist/node_modules/prebuild-install/error.js +0 -14
  238. package/dist/node_modules/prebuild-install/help.txt +0 -16
  239. package/dist/node_modules/prebuild-install/index.js +0 -1
  240. package/dist/node_modules/prebuild-install/log.js +0 -33
  241. package/dist/node_modules/prebuild-install/package.json +0 -67
  242. package/dist/node_modules/prebuild-install/proxy.js +0 -35
  243. package/dist/node_modules/prebuild-install/rc.js +0 -64
  244. package/dist/node_modules/prebuild-install/util.js +0 -143
  245. package/dist/node_modules/pump/.travis.yml +0 -5
  246. package/dist/node_modules/pump/LICENSE +0 -21
  247. package/dist/node_modules/pump/README.md +0 -65
  248. package/dist/node_modules/pump/index.js +0 -82
  249. package/dist/node_modules/pump/package.json +0 -24
  250. package/dist/node_modules/pump/test-browser.js +0 -66
  251. package/dist/node_modules/pump/test-node.js +0 -53
  252. package/dist/node_modules/rc/LICENSE.APACHE2 +0 -15
  253. package/dist/node_modules/rc/LICENSE.BSD +0 -26
  254. package/dist/node_modules/rc/LICENSE.MIT +0 -24
  255. package/dist/node_modules/rc/README.md +0 -227
  256. package/dist/node_modules/rc/browser.js +0 -7
  257. package/dist/node_modules/rc/cli.js +0 -4
  258. package/dist/node_modules/rc/index.js +0 -53
  259. package/dist/node_modules/rc/lib/utils.js +0 -104
  260. package/dist/node_modules/rc/package.json +0 -29
  261. package/dist/node_modules/rc/test/ini.js +0 -16
  262. package/dist/node_modules/rc/test/nested-env-vars.js +0 -50
  263. package/dist/node_modules/rc/test/test.js +0 -59
  264. package/dist/node_modules/readable-stream/CONTRIBUTING.md +0 -38
  265. package/dist/node_modules/readable-stream/GOVERNANCE.md +0 -136
  266. package/dist/node_modules/readable-stream/LICENSE +0 -47
  267. package/dist/node_modules/readable-stream/README.md +0 -106
  268. package/dist/node_modules/readable-stream/errors-browser.js +0 -127
  269. package/dist/node_modules/readable-stream/errors.js +0 -116
  270. package/dist/node_modules/readable-stream/experimentalWarning.js +0 -17
  271. package/dist/node_modules/readable-stream/lib/_stream_duplex.js +0 -126
  272. package/dist/node_modules/readable-stream/lib/_stream_passthrough.js +0 -37
  273. package/dist/node_modules/readable-stream/lib/_stream_readable.js +0 -1027
  274. package/dist/node_modules/readable-stream/lib/_stream_transform.js +0 -190
  275. package/dist/node_modules/readable-stream/lib/_stream_writable.js +0 -641
  276. package/dist/node_modules/readable-stream/lib/internal/streams/async_iterator.js +0 -180
  277. package/dist/node_modules/readable-stream/lib/internal/streams/buffer_list.js +0 -183
  278. package/dist/node_modules/readable-stream/lib/internal/streams/destroy.js +0 -96
  279. package/dist/node_modules/readable-stream/lib/internal/streams/end-of-stream.js +0 -86
  280. package/dist/node_modules/readable-stream/lib/internal/streams/from-browser.js +0 -3
  281. package/dist/node_modules/readable-stream/lib/internal/streams/from.js +0 -52
  282. package/dist/node_modules/readable-stream/lib/internal/streams/pipeline.js +0 -86
  283. package/dist/node_modules/readable-stream/lib/internal/streams/state.js +0 -22
  284. package/dist/node_modules/readable-stream/lib/internal/streams/stream-browser.js +0 -1
  285. package/dist/node_modules/readable-stream/lib/internal/streams/stream.js +0 -1
  286. package/dist/node_modules/readable-stream/package.json +0 -68
  287. package/dist/node_modules/readable-stream/readable-browser.js +0 -9
  288. package/dist/node_modules/readable-stream/readable.js +0 -16
  289. package/dist/node_modules/safe-buffer/LICENSE +0 -21
  290. package/dist/node_modules/safe-buffer/README.md +0 -584
  291. package/dist/node_modules/safe-buffer/index.d.ts +0 -187
  292. package/dist/node_modules/safe-buffer/index.js +0 -65
  293. package/dist/node_modules/safe-buffer/package.json +0 -51
  294. package/dist/node_modules/semver/LICENSE +0 -15
  295. package/dist/node_modules/semver/README.md +0 -568
  296. package/dist/node_modules/semver/bin/semver.js +0 -183
  297. package/dist/node_modules/semver/classes/comparator.js +0 -136
  298. package/dist/node_modules/semver/classes/index.js +0 -5
  299. package/dist/node_modules/semver/classes/range.js +0 -522
  300. package/dist/node_modules/semver/classes/semver.js +0 -287
  301. package/dist/node_modules/semver/functions/clean.js +0 -6
  302. package/dist/node_modules/semver/functions/cmp.js +0 -52
  303. package/dist/node_modules/semver/functions/coerce.js +0 -52
  304. package/dist/node_modules/semver/functions/compare-build.js +0 -7
  305. package/dist/node_modules/semver/functions/compare-loose.js +0 -3
  306. package/dist/node_modules/semver/functions/compare.js +0 -5
  307. package/dist/node_modules/semver/functions/diff.js +0 -23
  308. package/dist/node_modules/semver/functions/eq.js +0 -3
  309. package/dist/node_modules/semver/functions/gt.js +0 -3
  310. package/dist/node_modules/semver/functions/gte.js +0 -3
  311. package/dist/node_modules/semver/functions/inc.js +0 -18
  312. package/dist/node_modules/semver/functions/lt.js +0 -3
  313. package/dist/node_modules/semver/functions/lte.js +0 -3
  314. package/dist/node_modules/semver/functions/major.js +0 -3
  315. package/dist/node_modules/semver/functions/minor.js +0 -3
  316. package/dist/node_modules/semver/functions/neq.js +0 -3
  317. package/dist/node_modules/semver/functions/parse.js +0 -33
  318. package/dist/node_modules/semver/functions/patch.js +0 -3
  319. package/dist/node_modules/semver/functions/prerelease.js +0 -6
  320. package/dist/node_modules/semver/functions/rcompare.js +0 -3
  321. package/dist/node_modules/semver/functions/rsort.js +0 -3
  322. package/dist/node_modules/semver/functions/satisfies.js +0 -10
  323. package/dist/node_modules/semver/functions/sort.js +0 -3
  324. package/dist/node_modules/semver/functions/valid.js +0 -6
  325. package/dist/node_modules/semver/index.js +0 -88
  326. package/dist/node_modules/semver/internal/constants.js +0 -17
  327. package/dist/node_modules/semver/internal/debug.js +0 -9
  328. package/dist/node_modules/semver/internal/identifiers.js +0 -23
  329. package/dist/node_modules/semver/internal/parse-options.js +0 -11
  330. package/dist/node_modules/semver/internal/re.js +0 -182
  331. package/dist/node_modules/semver/package.json +0 -86
  332. package/dist/node_modules/semver/preload.js +0 -2
  333. package/dist/node_modules/semver/range.bnf +0 -16
  334. package/dist/node_modules/semver/ranges/gtr.js +0 -4
  335. package/dist/node_modules/semver/ranges/intersects.js +0 -7
  336. package/dist/node_modules/semver/ranges/ltr.js +0 -4
  337. package/dist/node_modules/semver/ranges/max-satisfying.js +0 -25
  338. package/dist/node_modules/semver/ranges/min-satisfying.js +0 -24
  339. package/dist/node_modules/semver/ranges/min-version.js +0 -61
  340. package/dist/node_modules/semver/ranges/outside.js +0 -80
  341. package/dist/node_modules/semver/ranges/simplify.js +0 -47
  342. package/dist/node_modules/semver/ranges/subset.js +0 -244
  343. package/dist/node_modules/semver/ranges/to-comparators.js +0 -8
  344. package/dist/node_modules/semver/ranges/valid.js +0 -11
  345. package/dist/node_modules/sharp/LICENSE +0 -191
  346. package/dist/node_modules/sharp/README.md +0 -117
  347. package/dist/node_modules/sharp/binding.gyp +0 -233
  348. package/dist/node_modules/sharp/build/Release/sharp-linux-x64.node +0 -0
  349. package/dist/node_modules/sharp/install/can-compile.js +0 -11
  350. package/dist/node_modules/sharp/install/dll-copy.js +0 -37
  351. package/dist/node_modules/sharp/install/libvips.js +0 -215
  352. package/dist/node_modules/sharp/lib/agent.js +0 -40
  353. package/dist/node_modules/sharp/lib/channel.js +0 -171
  354. package/dist/node_modules/sharp/lib/colour.js +0 -180
  355. package/dist/node_modules/sharp/lib/composite.js +0 -193
  356. package/dist/node_modules/sharp/lib/constructor.js +0 -386
  357. package/dist/node_modules/sharp/lib/index.js +0 -13
  358. package/dist/node_modules/sharp/lib/input.js +0 -507
  359. package/dist/node_modules/sharp/lib/is.js +0 -143
  360. package/dist/node_modules/sharp/lib/libvips.js +0 -136
  361. package/dist/node_modules/sharp/lib/operation.js +0 -803
  362. package/dist/node_modules/sharp/lib/output.js +0 -1231
  363. package/dist/node_modules/sharp/lib/platform.js +0 -27
  364. package/dist/node_modules/sharp/lib/resize.js +0 -473
  365. package/dist/node_modules/sharp/lib/sharp.js +0 -35
  366. package/dist/node_modules/sharp/lib/utility.js +0 -211
  367. package/dist/node_modules/sharp/package.json +0 -196
  368. package/dist/node_modules/sharp/src/common.cc +0 -966
  369. package/dist/node_modules/sharp/src/common.h +0 -352
  370. package/dist/node_modules/sharp/src/libvips/cplusplus/VConnection.cpp +0 -152
  371. package/dist/node_modules/sharp/src/libvips/cplusplus/VError.cpp +0 -50
  372. package/dist/node_modules/sharp/src/libvips/cplusplus/VImage.cpp +0 -1523
  373. package/dist/node_modules/sharp/src/libvips/cplusplus/VInterpolate.cpp +0 -63
  374. package/dist/node_modules/sharp/src/libvips/cplusplus/vips-operators.cpp +0 -3738
  375. package/dist/node_modules/sharp/src/metadata.cc +0 -291
  376. package/dist/node_modules/sharp/src/metadata.h +0 -92
  377. package/dist/node_modules/sharp/src/operations.cc +0 -412
  378. package/dist/node_modules/sharp/src/operations.h +0 -126
  379. package/dist/node_modules/sharp/src/pipeline.cc +0 -1624
  380. package/dist/node_modules/sharp/src/pipeline.h +0 -349
  381. package/dist/node_modules/sharp/src/sharp.cc +0 -52
  382. package/dist/node_modules/sharp/src/stats.cc +0 -193
  383. package/dist/node_modules/sharp/src/stats.h +0 -70
  384. package/dist/node_modules/sharp/src/utilities.cc +0 -243
  385. package/dist/node_modules/sharp/src/utilities.h +0 -29
  386. package/dist/node_modules/sharp/vendor/8.12.2/linux-x64/THIRD-PARTY-NOTICES.md +0 -43
  387. package/dist/node_modules/sharp/vendor/8.12.2/linux-x64/lib/libvips-cpp.so.42 +0 -0
  388. package/dist/node_modules/sharp/vendor/8.12.2/linux-x64/platform.json +0 -1
  389. package/dist/node_modules/sharp/vendor/8.12.2/linux-x64/versions.json +0 -31
  390. package/dist/node_modules/simple-concat/.travis.yml +0 -3
  391. package/dist/node_modules/simple-concat/LICENSE +0 -20
  392. package/dist/node_modules/simple-concat/README.md +0 -44
  393. package/dist/node_modules/simple-concat/index.js +0 -15
  394. package/dist/node_modules/simple-concat/package.json +0 -47
  395. package/dist/node_modules/simple-concat/test/basic.js +0 -41
  396. package/dist/node_modules/simple-get/.github/dependabot.yml +0 -15
  397. package/dist/node_modules/simple-get/.github/workflows/ci.yml +0 -23
  398. package/dist/node_modules/simple-get/LICENSE +0 -20
  399. package/dist/node_modules/simple-get/README.md +0 -333
  400. package/dist/node_modules/simple-get/index.js +0 -108
  401. package/dist/node_modules/simple-get/package.json +0 -67
  402. package/dist/node_modules/simple-swizzle/LICENSE +0 -21
  403. package/dist/node_modules/simple-swizzle/README.md +0 -39
  404. package/dist/node_modules/simple-swizzle/index.js +0 -29
  405. package/dist/node_modules/simple-swizzle/package.json +0 -36
  406. package/dist/node_modules/string_decoder/LICENSE +0 -48
  407. package/dist/node_modules/string_decoder/README.md +0 -47
  408. package/dist/node_modules/string_decoder/lib/string_decoder.js +0 -296
  409. package/dist/node_modules/string_decoder/package.json +0 -34
  410. package/dist/node_modules/strip-json-comments/index.js +0 -70
  411. package/dist/node_modules/strip-json-comments/license +0 -21
  412. package/dist/node_modules/strip-json-comments/package.json +0 -42
  413. package/dist/node_modules/strip-json-comments/readme.md +0 -64
  414. package/dist/node_modules/tar-fs/.travis.yml +0 -6
  415. package/dist/node_modules/tar-fs/LICENSE +0 -21
  416. package/dist/node_modules/tar-fs/README.md +0 -165
  417. package/dist/node_modules/tar-fs/index.js +0 -351
  418. package/dist/node_modules/tar-fs/package.json +0 -41
  419. package/dist/node_modules/tar-fs/test/fixtures/a/hello.txt +0 -1
  420. package/dist/node_modules/tar-fs/test/fixtures/b/a/test.txt +0 -1
  421. package/dist/node_modules/tar-fs/test/fixtures/d/file1 +0 -0
  422. package/dist/node_modules/tar-fs/test/fixtures/d/file2 +0 -0
  423. package/dist/node_modules/tar-fs/test/fixtures/d/sub-dir/file5 +0 -0
  424. package/dist/node_modules/tar-fs/test/fixtures/d/sub-files/file3 +0 -0
  425. package/dist/node_modules/tar-fs/test/fixtures/d/sub-files/file4 +0 -0
  426. package/dist/node_modules/tar-fs/test/fixtures/e/directory/.ignore +0 -0
  427. package/dist/node_modules/tar-fs/test/fixtures/e/file +0 -0
  428. package/dist/node_modules/tar-fs/test/fixtures/invalid.tar +0 -0
  429. package/dist/node_modules/tar-fs/test/index.js +0 -346
  430. package/dist/node_modules/tar-stream/LICENSE +0 -21
  431. package/dist/node_modules/tar-stream/README.md +0 -168
  432. package/dist/node_modules/tar-stream/extract.js +0 -257
  433. package/dist/node_modules/tar-stream/headers.js +0 -295
  434. package/dist/node_modules/tar-stream/index.js +0 -2
  435. package/dist/node_modules/tar-stream/pack.js +0 -255
  436. package/dist/node_modules/tar-stream/package.json +0 -58
  437. package/dist/node_modules/tar-stream/sandbox.js +0 -11
  438. package/dist/node_modules/tunnel-agent/LICENSE +0 -55
  439. package/dist/node_modules/tunnel-agent/README.md +0 -4
  440. package/dist/node_modules/tunnel-agent/index.js +0 -244
  441. package/dist/node_modules/tunnel-agent/package.json +0 -22
  442. package/dist/node_modules/util-deprecate/History.md +0 -16
  443. package/dist/node_modules/util-deprecate/LICENSE +0 -24
  444. package/dist/node_modules/util-deprecate/README.md +0 -53
  445. package/dist/node_modules/util-deprecate/browser.js +0 -67
  446. package/dist/node_modules/util-deprecate/node.js +0 -6
  447. package/dist/node_modules/util-deprecate/package.json +0 -27
  448. package/dist/node_modules/wrappy/LICENSE +0 -15
  449. package/dist/node_modules/wrappy/README.md +0 -36
  450. package/dist/node_modules/wrappy/package.json +0 -29
  451. package/dist/node_modules/wrappy/wrappy.js +0 -33
  452. package/dist/node_modules/yallist/LICENSE +0 -15
  453. package/dist/node_modules/yallist/README.md +0 -204
  454. package/dist/node_modules/yallist/iterator.js +0 -8
  455. package/dist/node_modules/yallist/package.json +0 -29
  456. package/dist/node_modules/yallist/yallist.js +0 -426
  457. package/dist/package-lock.json +0 -502
  458. package/dist/package.json +0 -39
  459. package/dist/static/expected_tile_2193_153_255_z7.png +0 -0
  460. package/dist/static/expected_tile_NZTM2000Quad_30_33_z6.png +0 -0
  461. package/dist/static/expected_tile_WebMercatorQuad_252_156_z8.png +0 -0
@@ -1,1624 +0,0 @@
1
- // Copyright 2013, 2014, 2015, 2016, 2017, 2018, 2019, 2020 Lovell Fuller and contributors.
2
- //
3
- // Licensed under the Apache License, Version 2.0 (the "License");
4
- // you may not use this file except in compliance with the License.
5
- // You may obtain a copy of the License at
6
- //
7
- // http://www.apache.org/licenses/LICENSE-2.0
8
- //
9
- // Unless required by applicable law or agreed to in writing, software
10
- // distributed under the License is distributed on an "AS IS" BASIS,
11
- // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12
- // See the License for the specific language governing permissions and
13
- // limitations under the License.
14
-
15
- #include <algorithm>
16
- #include <cmath>
17
- #include <map>
18
- #include <memory>
19
- #include <numeric>
20
- #include <string>
21
- #include <tuple>
22
- #include <utility>
23
- #include <vector>
24
- #include <sys/types.h>
25
- #include <sys/stat.h>
26
-
27
- #include <vips/vips8>
28
- #include <napi.h>
29
-
30
- #include "common.h"
31
- #include "operations.h"
32
- #include "pipeline.h"
33
-
34
- #if defined(WIN32)
35
- #define STAT64_STRUCT __stat64
36
- #define STAT64_FUNCTION _stat64
37
- #elif defined(__APPLE__)
38
- #define STAT64_STRUCT stat
39
- #define STAT64_FUNCTION stat
40
- #elif defined(__FreeBSD__) || defined(__OpenBSD__) || defined(__NetBSD__) || defined(__DragonFly__)
41
- #define STAT64_STRUCT stat
42
- #define STAT64_FUNCTION stat
43
- #else
44
- #define STAT64_STRUCT stat64
45
- #define STAT64_FUNCTION stat64
46
- #endif
47
-
48
- class PipelineWorker : public Napi::AsyncWorker {
49
- public:
50
- PipelineWorker(Napi::Function callback, PipelineBaton *baton,
51
- Napi::Function debuglog, Napi::Function queueListener) :
52
- Napi::AsyncWorker(callback),
53
- baton(baton),
54
- debuglog(Napi::Persistent(debuglog)),
55
- queueListener(Napi::Persistent(queueListener)) {}
56
- ~PipelineWorker() {}
57
-
58
- // libuv worker
59
- void Execute() {
60
- // Decrement queued task counter
61
- g_atomic_int_dec_and_test(&sharp::counterQueue);
62
- // Increment processing task counter
63
- g_atomic_int_inc(&sharp::counterProcess);
64
-
65
- try {
66
- // Open input
67
- vips::VImage image;
68
- sharp::ImageType inputImageType;
69
- std::tie(image, inputImageType) = sharp::OpenInput(baton->input);
70
- image = sharp::EnsureColourspace(image, baton->colourspaceInput);
71
-
72
- int nPages = baton->input->pages;
73
- if (nPages == -1) {
74
- // Resolve the number of pages if we need to render until the end of the document
75
- nPages = image.get_typeof(VIPS_META_N_PAGES) != 0
76
- ? image.get_int(VIPS_META_N_PAGES) - baton->input->page
77
- : 1;
78
- }
79
-
80
- // Get pre-resize page height
81
- int pageHeight = sharp::GetPageHeight(image);
82
-
83
- // Calculate angle of rotation
84
- VipsAngle rotation;
85
- bool flip = FALSE;
86
- bool flop = FALSE;
87
- if (baton->useExifOrientation) {
88
- // Rotate and flip image according to Exif orientation
89
- std::tie(rotation, flip, flop) = CalculateExifRotationAndFlip(sharp::ExifOrientation(image));
90
- } else {
91
- rotation = CalculateAngleRotation(baton->angle);
92
- }
93
-
94
- // Rotate pre-extract
95
- if (baton->rotateBeforePreExtract) {
96
- if (rotation != VIPS_ANGLE_D0) {
97
- image = image.rot(rotation);
98
- }
99
- if (flip) {
100
- image = image.flip(VIPS_DIRECTION_VERTICAL);
101
- }
102
- if (flop) {
103
- image = image.flip(VIPS_DIRECTION_HORIZONTAL);
104
- }
105
- if (rotation != VIPS_ANGLE_D0 || flip || flop) {
106
- image = sharp::RemoveExifOrientation(image);
107
- }
108
- flop = FALSE;
109
- flip = FALSE;
110
- if (baton->rotationAngle != 0.0) {
111
- MultiPageUnsupported(nPages, "Rotate");
112
- std::vector<double> background;
113
- std::tie(image, background) = sharp::ApplyAlpha(image, baton->rotationBackground, FALSE);
114
- image = image.rotate(baton->rotationAngle, VImage::option()->set("background", background));
115
- }
116
- }
117
-
118
- // Trim
119
- if (baton->trimThreshold > 0.0) {
120
- MultiPageUnsupported(nPages, "Trim");
121
- image = sharp::Trim(image, baton->trimThreshold);
122
- baton->trimOffsetLeft = image.xoffset();
123
- baton->trimOffsetTop = image.yoffset();
124
- }
125
-
126
- // Pre extraction
127
- if (baton->topOffsetPre != -1) {
128
- image = nPages > 1
129
- ? sharp::CropMultiPage(image,
130
- baton->leftOffsetPre, baton->topOffsetPre, baton->widthPre, baton->heightPre, nPages, &pageHeight)
131
- : image.extract_area(baton->leftOffsetPre, baton->topOffsetPre, baton->widthPre, baton->heightPre);
132
- }
133
-
134
- // Get pre-resize image width and height
135
- int inputWidth = image.width();
136
- int inputHeight = image.height();
137
-
138
- // Is there just one page? Shrink to inputHeight instead
139
- if (nPages == 1) {
140
- pageHeight = inputHeight;
141
- }
142
-
143
- // Scaling calculations
144
- double hshrink;
145
- double vshrink;
146
- int targetResizeWidth = baton->width;
147
- int targetResizeHeight = baton->height;
148
-
149
- // Swap input output width and height when rotating by 90 or 270 degrees
150
- bool swap = !baton->rotateBeforePreExtract && (rotation == VIPS_ANGLE_D90 || rotation == VIPS_ANGLE_D270);
151
-
152
- // Shrink to pageHeight, so we work for multi-page images
153
- std::tie(hshrink, vshrink) = sharp::ResolveShrink(
154
- inputWidth, pageHeight, targetResizeWidth, targetResizeHeight,
155
- baton->canvas, swap, baton->withoutEnlargement, baton->withoutReduction);
156
-
157
- // The jpeg preload shrink.
158
- int jpegShrinkOnLoad = 1;
159
-
160
- // WebP, PDF, SVG scale
161
- double scale = 1.0;
162
-
163
- // Try to reload input using shrink-on-load for JPEG, WebP, SVG and PDF, when:
164
- // - the width or height parameters are specified;
165
- // - gamma correction doesn't need to be applied;
166
- // - trimming or pre-resize extract isn't required;
167
- // - input colourspace is not specified;
168
- bool const shouldPreShrink = (targetResizeWidth > 0 || targetResizeHeight > 0) &&
169
- baton->gamma == 0 && baton->topOffsetPre == -1 && baton->trimThreshold == 0.0 &&
170
- baton->colourspaceInput == VIPS_INTERPRETATION_LAST;
171
-
172
- if (shouldPreShrink) {
173
- // The common part of the shrink: the bit by which both axes must be shrunk
174
- double shrink = std::min(hshrink, vshrink);
175
-
176
- if (inputImageType == sharp::ImageType::JPEG) {
177
- // Leave at least a factor of two for the final resize step, when fastShrinkOnLoad: false
178
- // for more consistent results and to avoid extra sharpness to the image
179
- int factor = baton->fastShrinkOnLoad ? 1 : 2;
180
- if (shrink >= 8 * factor) {
181
- jpegShrinkOnLoad = 8;
182
- } else if (shrink >= 4 * factor) {
183
- jpegShrinkOnLoad = 4;
184
- } else if (shrink >= 2 * factor) {
185
- jpegShrinkOnLoad = 2;
186
- }
187
- // Lower shrink-on-load for known libjpeg rounding errors
188
- if (jpegShrinkOnLoad > 1 && static_cast<int>(shrink) == jpegShrinkOnLoad) {
189
- jpegShrinkOnLoad /= 2;
190
- }
191
- } else if (inputImageType == sharp::ImageType::WEBP && shrink > 1.0) {
192
- // Avoid upscaling via webp
193
- scale = 1.0 / shrink;
194
- } else if (inputImageType == sharp::ImageType::SVG ||
195
- inputImageType == sharp::ImageType::PDF) {
196
- scale = 1.0 / shrink;
197
- }
198
- }
199
-
200
- // Reload input using shrink-on-load, it'll be an integer shrink
201
- // factor for jpegload*, a double scale factor for webpload*,
202
- // pdfload* and svgload*
203
- if (jpegShrinkOnLoad > 1) {
204
- vips::VOption *option = VImage::option()
205
- ->set("access", baton->input->access)
206
- ->set("shrink", jpegShrinkOnLoad)
207
- ->set("fail_on", baton->input->failOn);
208
- if (baton->input->buffer != nullptr) {
209
- // Reload JPEG buffer
210
- VipsBlob *blob = vips_blob_new(nullptr, baton->input->buffer, baton->input->bufferLength);
211
- image = VImage::jpegload_buffer(blob, option);
212
- vips_area_unref(reinterpret_cast<VipsArea*>(blob));
213
- } else {
214
- // Reload JPEG file
215
- image = VImage::jpegload(const_cast<char*>(baton->input->file.data()), option);
216
- }
217
- } else if (scale != 1.0) {
218
- vips::VOption *option = VImage::option()
219
- ->set("access", baton->input->access)
220
- ->set("scale", scale)
221
- ->set("fail_on", baton->input->failOn);
222
- if (inputImageType == sharp::ImageType::WEBP) {
223
- option->set("n", baton->input->pages);
224
- option->set("page", baton->input->page);
225
-
226
- if (baton->input->buffer != nullptr) {
227
- // Reload WebP buffer
228
- VipsBlob *blob = vips_blob_new(nullptr, baton->input->buffer, baton->input->bufferLength);
229
- image = VImage::webpload_buffer(blob, option);
230
- vips_area_unref(reinterpret_cast<VipsArea*>(blob));
231
- } else {
232
- // Reload WebP file
233
- image = VImage::webpload(const_cast<char*>(baton->input->file.data()), option);
234
- }
235
- } else if (inputImageType == sharp::ImageType::SVG) {
236
- option->set("unlimited", baton->input->unlimited);
237
- option->set("dpi", baton->input->density);
238
-
239
- if (baton->input->buffer != nullptr) {
240
- // Reload SVG buffer
241
- VipsBlob *blob = vips_blob_new(nullptr, baton->input->buffer, baton->input->bufferLength);
242
- image = VImage::svgload_buffer(blob, option);
243
- vips_area_unref(reinterpret_cast<VipsArea*>(blob));
244
- } else {
245
- // Reload SVG file
246
- image = VImage::svgload(const_cast<char*>(baton->input->file.data()), option);
247
- }
248
- sharp::SetDensity(image, baton->input->density);
249
- if (image.width() > 32767 || image.height() > 32767) {
250
- throw vips::VError("Input SVG image will exceed 32767x32767 pixel limit when scaled");
251
- }
252
- } else if (inputImageType == sharp::ImageType::PDF) {
253
- option->set("n", baton->input->pages);
254
- option->set("page", baton->input->page);
255
- option->set("dpi", baton->input->density);
256
-
257
- if (baton->input->buffer != nullptr) {
258
- // Reload PDF buffer
259
- VipsBlob *blob = vips_blob_new(nullptr, baton->input->buffer, baton->input->bufferLength);
260
- image = VImage::pdfload_buffer(blob, option);
261
- vips_area_unref(reinterpret_cast<VipsArea*>(blob));
262
- } else {
263
- // Reload PDF file
264
- image = VImage::pdfload(const_cast<char*>(baton->input->file.data()), option);
265
- }
266
-
267
- sharp::SetDensity(image, baton->input->density);
268
- }
269
- } else {
270
- if (inputImageType == sharp::ImageType::SVG && (image.width() > 32767 || image.height() > 32767)) {
271
- throw vips::VError("Input SVG image exceeds 32767x32767 pixel limit");
272
- }
273
- }
274
-
275
- // Any pre-shrinking may already have been done
276
- inputWidth = image.width();
277
- inputHeight = image.height();
278
-
279
- // After pre-shrink, but before the main shrink stage
280
- // Reuse the initial pageHeight if we didn't pre-shrink
281
- if (shouldPreShrink) {
282
- pageHeight = sharp::GetPageHeight(image);
283
- }
284
-
285
- // Shrink to pageHeight, so we work for multi-page images
286
- std::tie(hshrink, vshrink) = sharp::ResolveShrink(
287
- inputWidth, pageHeight, targetResizeWidth, targetResizeHeight,
288
- baton->canvas, swap, baton->withoutEnlargement, baton->withoutReduction);
289
-
290
- int targetHeight = static_cast<int>(std::rint(static_cast<double>(pageHeight) / vshrink));
291
- int targetPageHeight = targetHeight;
292
-
293
- // In toilet-roll mode, we must adjust vshrink so that we exactly hit
294
- // pageHeight or we'll have pixels straddling pixel boundaries
295
- if (inputHeight > pageHeight) {
296
- targetHeight *= nPages;
297
- vshrink = static_cast<double>(inputHeight) / targetHeight;
298
- }
299
-
300
- // Ensure we're using a device-independent colour space
301
- char const *processingProfile = image.interpretation() == VIPS_INTERPRETATION_RGB16 ? "p3" : "srgb";
302
- if (
303
- sharp::HasProfile(image) &&
304
- image.interpretation() != VIPS_INTERPRETATION_LABS &&
305
- image.interpretation() != VIPS_INTERPRETATION_GREY16 &&
306
- image.interpretation() != VIPS_INTERPRETATION_B_W
307
- ) {
308
- // Convert to sRGB/P3 using embedded profile
309
- try {
310
- image = image.icc_transform(processingProfile, VImage::option()
311
- ->set("embedded", TRUE)
312
- ->set("depth", image.interpretation() == VIPS_INTERPRETATION_RGB16 ? 16 : 8)
313
- ->set("intent", VIPS_INTENT_PERCEPTUAL));
314
- } catch(...) {
315
- // Ignore failure of embedded profile
316
- }
317
- } else if (image.interpretation() == VIPS_INTERPRETATION_CMYK) {
318
- image = image.icc_transform(processingProfile, VImage::option()
319
- ->set("input_profile", "cmyk")
320
- ->set("intent", VIPS_INTENT_PERCEPTUAL));
321
- }
322
-
323
- // Flatten image to remove alpha channel
324
- if (baton->flatten && sharp::HasAlpha(image)) {
325
- // Scale up 8-bit values to match 16-bit input image
326
- double const multiplier = sharp::Is16Bit(image.interpretation()) ? 256.0 : 1.0;
327
- // Background colour
328
- std::vector<double> background {
329
- baton->flattenBackground[0] * multiplier,
330
- baton->flattenBackground[1] * multiplier,
331
- baton->flattenBackground[2] * multiplier
332
- };
333
- image = image.flatten(VImage::option()
334
- ->set("background", background));
335
- }
336
-
337
- // Negate the colours in the image
338
- if (baton->negate) {
339
- image = sharp::Negate(image, baton->negateAlpha);
340
- }
341
-
342
- // Gamma encoding (darken)
343
- if (baton->gamma >= 1 && baton->gamma <= 3) {
344
- image = sharp::Gamma(image, 1.0 / baton->gamma);
345
- }
346
-
347
- // Convert to greyscale (linear, therefore after gamma encoding, if any)
348
- if (baton->greyscale) {
349
- image = image.colourspace(VIPS_INTERPRETATION_B_W);
350
- }
351
-
352
- bool const shouldResize = hshrink != 1.0 || vshrink != 1.0;
353
- bool const shouldBlur = baton->blurSigma != 0.0;
354
- bool const shouldConv = baton->convKernelWidth * baton->convKernelHeight > 0;
355
- bool const shouldSharpen = baton->sharpenSigma != 0.0;
356
- bool const shouldApplyMedian = baton->medianSize > 0;
357
- bool const shouldComposite = !baton->composite.empty();
358
- bool const shouldModulate = baton->brightness != 1.0 || baton->saturation != 1.0 ||
359
- baton->hue != 0.0 || baton->lightness != 0.0;
360
- bool const shouldApplyClahe = baton->claheWidth != 0 && baton->claheHeight != 0;
361
-
362
- if (shouldComposite && !sharp::HasAlpha(image)) {
363
- image = sharp::EnsureAlpha(image, 1);
364
- }
365
-
366
- bool const shouldPremultiplyAlpha = sharp::HasAlpha(image) &&
367
- (shouldResize || shouldBlur || shouldConv || shouldSharpen);
368
-
369
- // Premultiply image alpha channel before all transformations to avoid
370
- // dark fringing around bright pixels
371
- // See: http://entropymine.com/imageworsener/resizealpha/
372
- if (shouldPremultiplyAlpha) {
373
- image = image.premultiply();
374
- }
375
-
376
- // Resize
377
- if (shouldResize) {
378
- VipsKernel kernel = static_cast<VipsKernel>(
379
- vips_enum_from_nick(nullptr, VIPS_TYPE_KERNEL, baton->kernel.data()));
380
- if (
381
- kernel != VIPS_KERNEL_NEAREST && kernel != VIPS_KERNEL_CUBIC && kernel != VIPS_KERNEL_LANCZOS2 &&
382
- kernel != VIPS_KERNEL_LANCZOS3 && kernel != VIPS_KERNEL_MITCHELL
383
- ) {
384
- throw vips::VError("Unknown kernel");
385
- }
386
- image = image.resize(1.0 / hshrink, VImage::option()
387
- ->set("vscale", 1.0 / vshrink)
388
- ->set("kernel", kernel));
389
- }
390
-
391
- // Rotate post-extract 90-angle
392
- if (!baton->rotateBeforePreExtract && rotation != VIPS_ANGLE_D0) {
393
- image = image.rot(rotation);
394
- if (flip) {
395
- image = image.flip(VIPS_DIRECTION_VERTICAL);
396
- flip = FALSE;
397
- }
398
- if (flop) {
399
- image = image.flip(VIPS_DIRECTION_HORIZONTAL);
400
- flop = FALSE;
401
- }
402
- image = sharp::RemoveExifOrientation(image);
403
- }
404
-
405
- // Flip (mirror about Y axis)
406
- if (baton->flip || flip) {
407
- image = image.flip(VIPS_DIRECTION_VERTICAL);
408
- image = sharp::RemoveExifOrientation(image);
409
- }
410
-
411
- // Flop (mirror about X axis)
412
- if (baton->flop || flop) {
413
- image = image.flip(VIPS_DIRECTION_HORIZONTAL);
414
- image = sharp::RemoveExifOrientation(image);
415
- }
416
-
417
- // Join additional color channels to the image
418
- if (baton->joinChannelIn.size() > 0) {
419
- VImage joinImage;
420
- sharp::ImageType joinImageType = sharp::ImageType::UNKNOWN;
421
-
422
- for (unsigned int i = 0; i < baton->joinChannelIn.size(); i++) {
423
- std::tie(joinImage, joinImageType) = sharp::OpenInput(baton->joinChannelIn[i]);
424
- joinImage = sharp::EnsureColourspace(joinImage, baton->colourspaceInput);
425
- image = image.bandjoin(joinImage);
426
- }
427
- image = image.copy(VImage::option()->set("interpretation", baton->colourspace));
428
- }
429
-
430
- inputWidth = image.width();
431
- inputHeight = nPages > 1 ? targetPageHeight : image.height();
432
-
433
- // Resolve dimensions
434
- if (baton->width <= 0) {
435
- baton->width = inputWidth;
436
- }
437
- if (baton->height <= 0) {
438
- baton->height = inputHeight;
439
- }
440
-
441
- // Crop/embed
442
- if (inputWidth != baton->width || inputHeight != baton->height) {
443
- if (baton->canvas == sharp::Canvas::EMBED) {
444
- std::vector<double> background;
445
- std::tie(image, background) = sharp::ApplyAlpha(image, baton->resizeBackground, shouldPremultiplyAlpha);
446
-
447
- // Embed
448
-
449
- // Calculate where to position the embedded image if gravity specified, else center.
450
- int left;
451
- int top;
452
-
453
- left = static_cast<int>(round((baton->width - inputWidth) / 2));
454
- top = static_cast<int>(round((baton->height - inputHeight) / 2));
455
-
456
- int width = std::max(inputWidth, baton->width);
457
- int height = std::max(inputHeight, baton->height);
458
- std::tie(left, top) = sharp::CalculateEmbedPosition(
459
- inputWidth, inputHeight, baton->width, baton->height, baton->position);
460
-
461
- image = nPages > 1
462
- ? sharp::EmbedMultiPage(image,
463
- left, top, width, height, background, nPages, &targetPageHeight)
464
- : image.embed(left, top, width, height, VImage::option()
465
- ->set("extend", VIPS_EXTEND_BACKGROUND)
466
- ->set("background", background));
467
- } else if (baton->canvas == sharp::Canvas::CROP) {
468
- if (baton->width > inputWidth) {
469
- baton->width = inputWidth;
470
- }
471
- if (baton->height > inputHeight) {
472
- baton->height = inputHeight;
473
- }
474
-
475
- // Crop
476
- if (baton->position < 9) {
477
- // Gravity-based crop
478
- int left;
479
- int top;
480
- std::tie(left, top) = sharp::CalculateCrop(
481
- inputWidth, inputHeight, baton->width, baton->height, baton->position);
482
- int width = std::min(inputWidth, baton->width);
483
- int height = std::min(inputHeight, baton->height);
484
-
485
- image = nPages > 1
486
- ? sharp::CropMultiPage(image,
487
- left, top, width, height, nPages, &targetPageHeight)
488
- : image.extract_area(left, top, width, height);
489
- } else {
490
- // Attention-based or Entropy-based crop
491
- MultiPageUnsupported(nPages, "Resize strategy");
492
- image = image.tilecache(VImage::option()
493
- ->set("access", VIPS_ACCESS_RANDOM)
494
- ->set("threaded", TRUE));
495
- image = image.smartcrop(baton->width, baton->height, VImage::option()
496
- ->set("interesting", baton->position == 16 ? VIPS_INTERESTING_ENTROPY : VIPS_INTERESTING_ATTENTION));
497
- baton->hasCropOffset = true;
498
- baton->cropOffsetLeft = static_cast<int>(image.xoffset());
499
- baton->cropOffsetTop = static_cast<int>(image.yoffset());
500
- }
501
- }
502
- }
503
-
504
- // Rotate post-extract non-90 angle
505
- if (!baton->rotateBeforePreExtract && baton->rotationAngle != 0.0) {
506
- MultiPageUnsupported(nPages, "Rotate");
507
- std::vector<double> background;
508
- std::tie(image, background) = sharp::ApplyAlpha(image, baton->rotationBackground, shouldPremultiplyAlpha);
509
- image = image.rotate(baton->rotationAngle, VImage::option()->set("background", background));
510
- }
511
-
512
- // Post extraction
513
- if (baton->topOffsetPost != -1) {
514
- if (nPages > 1) {
515
- image = sharp::CropMultiPage(image,
516
- baton->leftOffsetPost, baton->topOffsetPost, baton->widthPost, baton->heightPost,
517
- nPages, &targetPageHeight);
518
-
519
- // heightPost is used in the info object, so update to reflect the number of pages
520
- baton->heightPost *= nPages;
521
- } else {
522
- image = image.extract_area(
523
- baton->leftOffsetPost, baton->topOffsetPost, baton->widthPost, baton->heightPost);
524
- }
525
- }
526
-
527
- // Affine transform
528
- if (baton->affineMatrix.size() > 0) {
529
- MultiPageUnsupported(nPages, "Affine");
530
- std::vector<double> background;
531
- std::tie(image, background) = sharp::ApplyAlpha(image, baton->affineBackground, shouldPremultiplyAlpha);
532
- vips::VInterpolate interp = vips::VInterpolate::new_from_name(
533
- const_cast<char*>(baton->affineInterpolator.data()));
534
- image = image.affine(baton->affineMatrix, VImage::option()->set("background", background)
535
- ->set("idx", baton->affineIdx)
536
- ->set("idy", baton->affineIdy)
537
- ->set("odx", baton->affineOdx)
538
- ->set("ody", baton->affineOdy)
539
- ->set("interpolate", interp));
540
- }
541
-
542
- // Extend edges
543
- if (baton->extendTop > 0 || baton->extendBottom > 0 || baton->extendLeft > 0 || baton->extendRight > 0) {
544
- std::vector<double> background;
545
- std::tie(image, background) = sharp::ApplyAlpha(image, baton->extendBackground, shouldPremultiplyAlpha);
546
-
547
- // Embed
548
- baton->width = image.width() + baton->extendLeft + baton->extendRight;
549
- baton->height = (nPages > 1 ? targetPageHeight : image.height()) + baton->extendTop + baton->extendBottom;
550
-
551
- image = nPages > 1
552
- ? sharp::EmbedMultiPage(image,
553
- baton->extendLeft, baton->extendTop, baton->width, baton->height, background, nPages, &targetPageHeight)
554
- : image.embed(baton->extendLeft, baton->extendTop, baton->width, baton->height,
555
- VImage::option()->set("extend", VIPS_EXTEND_BACKGROUND)->set("background", background));
556
- }
557
- // Median - must happen before blurring, due to the utility of blurring after thresholding
558
- if (shouldApplyMedian) {
559
- image = image.median(baton->medianSize);
560
- }
561
- // Threshold - must happen before blurring, due to the utility of blurring after thresholding
562
- if (baton->threshold != 0) {
563
- image = sharp::Threshold(image, baton->threshold, baton->thresholdGrayscale);
564
- }
565
-
566
- // Blur
567
- if (shouldBlur) {
568
- image = sharp::Blur(image, baton->blurSigma);
569
- }
570
-
571
- // Convolve
572
- if (shouldConv) {
573
- image = sharp::Convolve(image,
574
- baton->convKernelWidth, baton->convKernelHeight,
575
- baton->convKernelScale, baton->convKernelOffset,
576
- baton->convKernel);
577
- }
578
-
579
- // Recomb
580
- if (baton->recombMatrix != NULL) {
581
- image = sharp::Recomb(image, baton->recombMatrix);
582
- }
583
-
584
- if (shouldModulate) {
585
- image = sharp::Modulate(image, baton->brightness, baton->saturation, baton->hue, baton->lightness);
586
- }
587
-
588
- // Sharpen
589
- if (shouldSharpen) {
590
- image = sharp::Sharpen(image, baton->sharpenSigma, baton->sharpenM1, baton->sharpenM2,
591
- baton->sharpenX1, baton->sharpenY2, baton->sharpenY3);
592
- }
593
-
594
- // Composite
595
- if (shouldComposite) {
596
- std::vector<VImage> images = { image };
597
- std::vector<int> modes, xs, ys;
598
- for (Composite *composite : baton->composite) {
599
- VImage compositeImage;
600
- sharp::ImageType compositeImageType = sharp::ImageType::UNKNOWN;
601
- std::tie(compositeImage, compositeImageType) = sharp::OpenInput(composite->input);
602
- compositeImage = sharp::EnsureColourspace(compositeImage, baton->colourspaceInput);
603
- // Verify within current dimensions
604
- if (compositeImage.width() > image.width() || compositeImage.height() > image.height()) {
605
- throw vips::VError("Image to composite must have same dimensions or smaller");
606
- }
607
- // Check if overlay is tiled
608
- if (composite->tile) {
609
- int across = 0;
610
- int down = 0;
611
- // Use gravity in overlay
612
- if (compositeImage.width() <= image.width()) {
613
- across = static_cast<int>(ceil(static_cast<double>(image.width()) / compositeImage.width()));
614
- // Ensure odd number of tiles across when gravity is centre, north or south
615
- if (composite->gravity == 0 || composite->gravity == 1 || composite->gravity == 3) {
616
- across |= 1;
617
- }
618
- }
619
- if (compositeImage.height() <= image.height()) {
620
- down = static_cast<int>(ceil(static_cast<double>(image.height()) / compositeImage.height()));
621
- // Ensure odd number of tiles down when gravity is centre, east or west
622
- if (composite->gravity == 0 || composite->gravity == 2 || composite->gravity == 4) {
623
- down |= 1;
624
- }
625
- }
626
- if (across != 0 || down != 0) {
627
- int left;
628
- int top;
629
- compositeImage = compositeImage.replicate(across, down);
630
- if (composite->hasOffset) {
631
- std::tie(left, top) = sharp::CalculateCrop(
632
- compositeImage.width(), compositeImage.height(), image.width(), image.height(),
633
- composite->left, composite->top);
634
- } else {
635
- std::tie(left, top) = sharp::CalculateCrop(
636
- compositeImage.width(), compositeImage.height(), image.width(), image.height(), composite->gravity);
637
- }
638
- compositeImage = compositeImage.extract_area(left, top, image.width(), image.height());
639
- }
640
- // gravity was used for extract_area, set it back to its default value of 0
641
- composite->gravity = 0;
642
- }
643
- // Ensure image to composite is sRGB with unpremultiplied alpha
644
- compositeImage = compositeImage.colourspace(VIPS_INTERPRETATION_sRGB);
645
- if (!sharp::HasAlpha(compositeImage)) {
646
- compositeImage = sharp::EnsureAlpha(compositeImage, 1);
647
- }
648
- if (composite->premultiplied) compositeImage = compositeImage.unpremultiply();
649
- // Calculate position
650
- int left;
651
- int top;
652
- if (composite->hasOffset) {
653
- // Composite image at given offsets
654
- if (composite->tile) {
655
- std::tie(left, top) = sharp::CalculateCrop(image.width(), image.height(),
656
- compositeImage.width(), compositeImage.height(), composite->left, composite->top);
657
- } else {
658
- left = composite->left;
659
- top = composite->top;
660
- }
661
- } else {
662
- // Composite image with given gravity
663
- std::tie(left, top) = sharp::CalculateCrop(image.width(), image.height(),
664
- compositeImage.width(), compositeImage.height(), composite->gravity);
665
- }
666
- images.push_back(compositeImage);
667
- modes.push_back(composite->mode);
668
- xs.push_back(left);
669
- ys.push_back(top);
670
- }
671
- image = image.composite(images, modes, VImage::option()->set("x", xs)->set("y", ys));
672
- }
673
-
674
- // Reverse premultiplication after all transformations:
675
- if (shouldPremultiplyAlpha) {
676
- image = image.unpremultiply();
677
- // Cast pixel values to integer
678
- if (sharp::Is16Bit(image.interpretation())) {
679
- image = image.cast(VIPS_FORMAT_USHORT);
680
- } else {
681
- image = image.cast(VIPS_FORMAT_UCHAR);
682
- }
683
- }
684
- baton->premultiplied = shouldPremultiplyAlpha;
685
-
686
- // Gamma decoding (brighten)
687
- if (baton->gammaOut >= 1 && baton->gammaOut <= 3) {
688
- image = sharp::Gamma(image, baton->gammaOut);
689
- }
690
-
691
- // Linear adjustment (a * in + b)
692
- if (baton->linearA != 1.0 || baton->linearB != 0.0) {
693
- image = sharp::Linear(image, baton->linearA, baton->linearB);
694
- }
695
-
696
- // Apply normalisation - stretch luminance to cover full dynamic range
697
- if (baton->normalise) {
698
- image = sharp::Normalise(image);
699
- }
700
-
701
- // Apply contrast limiting adaptive histogram equalization (CLAHE)
702
- if (shouldApplyClahe) {
703
- image = sharp::Clahe(image, baton->claheWidth, baton->claheHeight, baton->claheMaxSlope);
704
- }
705
-
706
- // Apply bitwise boolean operation between images
707
- if (baton->boolean != nullptr) {
708
- VImage booleanImage;
709
- sharp::ImageType booleanImageType = sharp::ImageType::UNKNOWN;
710
- std::tie(booleanImage, booleanImageType) = sharp::OpenInput(baton->boolean);
711
- booleanImage = sharp::EnsureColourspace(booleanImage, baton->colourspaceInput);
712
- image = sharp::Boolean(image, booleanImage, baton->booleanOp);
713
- }
714
-
715
- // Apply per-channel Bandbool bitwise operations after all other operations
716
- if (baton->bandBoolOp >= VIPS_OPERATION_BOOLEAN_AND && baton->bandBoolOp < VIPS_OPERATION_BOOLEAN_LAST) {
717
- image = sharp::Bandbool(image, baton->bandBoolOp);
718
- }
719
-
720
- // Tint the image
721
- if (baton->tintA < 128.0 || baton->tintB < 128.0) {
722
- image = sharp::Tint(image, baton->tintA, baton->tintB);
723
- }
724
-
725
- // Extract an image channel (aka vips band)
726
- if (baton->extractChannel > -1) {
727
- if (baton->extractChannel >= image.bands()) {
728
- if (baton->extractChannel == 3 && sharp::HasAlpha(image)) {
729
- baton->extractChannel = image.bands() - 1;
730
- } else {
731
- (baton->err).append("Cannot extract channel from image. Too few channels in image.");
732
- return Error();
733
- }
734
- }
735
- VipsInterpretation const interpretation = sharp::Is16Bit(image.interpretation())
736
- ? VIPS_INTERPRETATION_GREY16
737
- : VIPS_INTERPRETATION_B_W;
738
- image = image
739
- .extract_band(baton->extractChannel)
740
- .copy(VImage::option()->set("interpretation", interpretation));
741
- }
742
-
743
- // Remove alpha channel, if any
744
- if (baton->removeAlpha) {
745
- image = sharp::RemoveAlpha(image);
746
- }
747
-
748
- // Ensure alpha channel, if missing
749
- if (baton->ensureAlpha != -1) {
750
- image = sharp::EnsureAlpha(image, baton->ensureAlpha);
751
- }
752
-
753
- // Convert image to sRGB, if not already
754
- if (sharp::Is16Bit(image.interpretation())) {
755
- image = image.cast(VIPS_FORMAT_USHORT);
756
- }
757
- if (image.interpretation() != baton->colourspace) {
758
- // Convert colourspace, pass the current known interpretation so libvips doesn't have to guess
759
- image = image.colourspace(baton->colourspace, VImage::option()->set("source_space", image.interpretation()));
760
- // Transform colours from embedded profile to output profile
761
- if (baton->withMetadata && sharp::HasProfile(image) && baton->withMetadataIcc.empty()) {
762
- image = image.icc_transform("srgb", VImage::option()
763
- ->set("embedded", TRUE)
764
- ->set("intent", VIPS_INTENT_PERCEPTUAL));
765
- }
766
- }
767
-
768
- // Apply output ICC profile
769
- if (!baton->withMetadataIcc.empty()) {
770
- image = image.icc_transform(
771
- const_cast<char*>(baton->withMetadataIcc.data()),
772
- VImage::option()
773
- ->set("input_profile", processingProfile)
774
- ->set("embedded", TRUE)
775
- ->set("intent", VIPS_INTENT_PERCEPTUAL));
776
- }
777
- // Override EXIF Orientation tag
778
- if (baton->withMetadata && baton->withMetadataOrientation != -1) {
779
- image = sharp::SetExifOrientation(image, baton->withMetadataOrientation);
780
- }
781
- // Override pixel density
782
- if (baton->withMetadataDensity > 0) {
783
- image = sharp::SetDensity(image, baton->withMetadataDensity);
784
- }
785
- // Metadata key/value pairs, e.g. EXIF
786
- if (!baton->withMetadataStrs.empty()) {
787
- image = image.copy();
788
- for (const auto& s : baton->withMetadataStrs) {
789
- image.set(s.first.data(), s.second.data());
790
- }
791
- }
792
-
793
- // Number of channels used in output image
794
- baton->channels = image.bands();
795
- baton->width = image.width();
796
- baton->height = image.height();
797
-
798
- image = sharp::SetAnimationProperties(
799
- image, nPages, targetPageHeight, baton->delay, baton->loop);
800
-
801
- // Output
802
- sharp::SetTimeout(image, baton->timeoutSeconds);
803
- if (baton->fileOut.empty()) {
804
- // Buffer output
805
- if (baton->formatOut == "jpeg" || (baton->formatOut == "input" && inputImageType == sharp::ImageType::JPEG)) {
806
- // Write JPEG to buffer
807
- sharp::AssertImageTypeDimensions(image, sharp::ImageType::JPEG);
808
- VipsArea *area = reinterpret_cast<VipsArea*>(image.jpegsave_buffer(VImage::option()
809
- ->set("strip", !baton->withMetadata)
810
- ->set("Q", baton->jpegQuality)
811
- ->set("interlace", baton->jpegProgressive)
812
- ->set("subsample_mode", baton->jpegChromaSubsampling == "4:4:4"
813
- ? VIPS_FOREIGN_SUBSAMPLE_OFF
814
- : VIPS_FOREIGN_SUBSAMPLE_ON)
815
- ->set("trellis_quant", baton->jpegTrellisQuantisation)
816
- ->set("quant_table", baton->jpegQuantisationTable)
817
- ->set("overshoot_deringing", baton->jpegOvershootDeringing)
818
- ->set("optimize_scans", baton->jpegOptimiseScans)
819
- ->set("optimize_coding", baton->jpegOptimiseCoding)));
820
- baton->bufferOut = static_cast<char*>(area->data);
821
- baton->bufferOutLength = area->length;
822
- area->free_fn = nullptr;
823
- vips_area_unref(area);
824
- baton->formatOut = "jpeg";
825
- if (baton->colourspace == VIPS_INTERPRETATION_CMYK) {
826
- baton->channels = std::min(baton->channels, 4);
827
- } else {
828
- baton->channels = std::min(baton->channels, 3);
829
- }
830
- } else if (baton->formatOut == "jp2" || (baton->formatOut == "input"
831
- && inputImageType == sharp::ImageType::JP2)) {
832
- // Write JP2 to Buffer
833
- sharp::AssertImageTypeDimensions(image, sharp::ImageType::JP2);
834
- VipsArea *area = reinterpret_cast<VipsArea*>(image.jp2ksave_buffer(VImage::option()
835
- ->set("Q", baton->jp2Quality)
836
- ->set("lossless", baton->jp2Lossless)
837
- ->set("subsample_mode", baton->jp2ChromaSubsampling == "4:4:4"
838
- ? VIPS_FOREIGN_SUBSAMPLE_OFF : VIPS_FOREIGN_SUBSAMPLE_ON)
839
- ->set("tile_height", baton->jp2TileHeight)
840
- ->set("tile_width", baton->jp2TileWidth)));
841
- baton->bufferOut = static_cast<char*>(area->data);
842
- baton->bufferOutLength = area->length;
843
- area->free_fn = nullptr;
844
- vips_area_unref(area);
845
- baton->formatOut = "jp2";
846
- } else if (baton->formatOut == "png" || (baton->formatOut == "input" &&
847
- (inputImageType == sharp::ImageType::PNG || inputImageType == sharp::ImageType::SVG))) {
848
- // Write PNG to buffer
849
- sharp::AssertImageTypeDimensions(image, sharp::ImageType::PNG);
850
- VipsArea *area = reinterpret_cast<VipsArea*>(image.pngsave_buffer(VImage::option()
851
- ->set("strip", !baton->withMetadata)
852
- ->set("interlace", baton->pngProgressive)
853
- ->set("compression", baton->pngCompressionLevel)
854
- ->set("filter", baton->pngAdaptiveFiltering ? VIPS_FOREIGN_PNG_FILTER_ALL : VIPS_FOREIGN_PNG_FILTER_NONE)
855
- ->set("palette", baton->pngPalette)
856
- ->set("Q", baton->pngQuality)
857
- ->set("effort", baton->pngEffort)
858
- ->set("bitdepth", sharp::Is16Bit(image.interpretation()) ? 16 : baton->pngBitdepth)
859
- ->set("dither", baton->pngDither)));
860
- baton->bufferOut = static_cast<char*>(area->data);
861
- baton->bufferOutLength = area->length;
862
- area->free_fn = nullptr;
863
- vips_area_unref(area);
864
- baton->formatOut = "png";
865
- } else if (baton->formatOut == "webp" ||
866
- (baton->formatOut == "input" && inputImageType == sharp::ImageType::WEBP)) {
867
- // Write WEBP to buffer
868
- sharp::AssertImageTypeDimensions(image, sharp::ImageType::WEBP);
869
- VipsArea *area = reinterpret_cast<VipsArea*>(image.webpsave_buffer(VImage::option()
870
- ->set("strip", !baton->withMetadata)
871
- ->set("Q", baton->webpQuality)
872
- ->set("lossless", baton->webpLossless)
873
- ->set("near_lossless", baton->webpNearLossless)
874
- ->set("smart_subsample", baton->webpSmartSubsample)
875
- ->set("effort", baton->webpEffort)
876
- ->set("alpha_q", baton->webpAlphaQuality)));
877
- baton->bufferOut = static_cast<char*>(area->data);
878
- baton->bufferOutLength = area->length;
879
- area->free_fn = nullptr;
880
- vips_area_unref(area);
881
- baton->formatOut = "webp";
882
- } else if (baton->formatOut == "gif" ||
883
- (baton->formatOut == "input" && inputImageType == sharp::ImageType::GIF)) {
884
- // Write GIF to buffer
885
- sharp::AssertImageTypeDimensions(image, sharp::ImageType::GIF);
886
- VipsArea *area = reinterpret_cast<VipsArea*>(image.gifsave_buffer(VImage::option()
887
- ->set("strip", !baton->withMetadata)
888
- ->set("bitdepth", baton->gifBitdepth)
889
- ->set("effort", baton->gifEffort)
890
- ->set("dither", baton->gifDither)));
891
- baton->bufferOut = static_cast<char*>(area->data);
892
- baton->bufferOutLength = area->length;
893
- area->free_fn = nullptr;
894
- vips_area_unref(area);
895
- baton->formatOut = "gif";
896
- } else if (baton->formatOut == "tiff" ||
897
- (baton->formatOut == "input" && inputImageType == sharp::ImageType::TIFF)) {
898
- // Write TIFF to buffer
899
- if (baton->tiffCompression == VIPS_FOREIGN_TIFF_COMPRESSION_JPEG) {
900
- sharp::AssertImageTypeDimensions(image, sharp::ImageType::JPEG);
901
- baton->channels = std::min(baton->channels, 3);
902
- }
903
- // Cast pixel values to float, if required
904
- if (baton->tiffPredictor == VIPS_FOREIGN_TIFF_PREDICTOR_FLOAT) {
905
- image = image.cast(VIPS_FORMAT_FLOAT);
906
- }
907
- VipsArea *area = reinterpret_cast<VipsArea*>(image.tiffsave_buffer(VImage::option()
908
- ->set("strip", !baton->withMetadata)
909
- ->set("Q", baton->tiffQuality)
910
- ->set("bitdepth", baton->tiffBitdepth)
911
- ->set("compression", baton->tiffCompression)
912
- ->set("predictor", baton->tiffPredictor)
913
- ->set("pyramid", baton->tiffPyramid)
914
- ->set("tile", baton->tiffTile)
915
- ->set("tile_height", baton->tiffTileHeight)
916
- ->set("tile_width", baton->tiffTileWidth)
917
- ->set("xres", baton->tiffXres)
918
- ->set("yres", baton->tiffYres)
919
- ->set("resunit", baton->tiffResolutionUnit)));
920
- baton->bufferOut = static_cast<char*>(area->data);
921
- baton->bufferOutLength = area->length;
922
- area->free_fn = nullptr;
923
- vips_area_unref(area);
924
- baton->formatOut = "tiff";
925
- } else if (baton->formatOut == "heif" ||
926
- (baton->formatOut == "input" && inputImageType == sharp::ImageType::HEIF)) {
927
- // Write HEIF to buffer
928
- image = sharp::RemoveAnimationProperties(image);
929
- VipsArea *area = reinterpret_cast<VipsArea*>(image.heifsave_buffer(VImage::option()
930
- ->set("strip", !baton->withMetadata)
931
- ->set("Q", baton->heifQuality)
932
- ->set("compression", baton->heifCompression)
933
- ->set("effort", baton->heifEffort)
934
- ->set("subsample_mode", baton->heifChromaSubsampling == "4:4:4"
935
- ? VIPS_FOREIGN_SUBSAMPLE_OFF : VIPS_FOREIGN_SUBSAMPLE_ON)
936
- ->set("lossless", baton->heifLossless)));
937
- baton->bufferOut = static_cast<char*>(area->data);
938
- baton->bufferOutLength = area->length;
939
- area->free_fn = nullptr;
940
- vips_area_unref(area);
941
- baton->formatOut = "heif";
942
- } else if (baton->formatOut == "raw" ||
943
- (baton->formatOut == "input" && inputImageType == sharp::ImageType::RAW)) {
944
- // Write raw, uncompressed image data to buffer
945
- if (baton->greyscale || image.interpretation() == VIPS_INTERPRETATION_B_W) {
946
- // Extract first band for greyscale image
947
- image = image[0];
948
- baton->channels = 1;
949
- }
950
- if (image.format() != baton->rawDepth) {
951
- // Cast pixels to requested format
952
- image = image.cast(baton->rawDepth);
953
- }
954
- // Get raw image data
955
- baton->bufferOut = static_cast<char*>(image.write_to_memory(&baton->bufferOutLength));
956
- if (baton->bufferOut == nullptr) {
957
- (baton->err).append("Could not allocate enough memory for raw output");
958
- return Error();
959
- }
960
- baton->formatOut = "raw";
961
- } else {
962
- // Unsupported output format
963
- (baton->err).append("Unsupported output format ");
964
- if (baton->formatOut == "input") {
965
- (baton->err).append(ImageTypeId(inputImageType));
966
- } else {
967
- (baton->err).append(baton->formatOut);
968
- }
969
- return Error();
970
- }
971
- } else {
972
- // File output
973
- bool const isJpeg = sharp::IsJpeg(baton->fileOut);
974
- bool const isPng = sharp::IsPng(baton->fileOut);
975
- bool const isWebp = sharp::IsWebp(baton->fileOut);
976
- bool const isGif = sharp::IsGif(baton->fileOut);
977
- bool const isTiff = sharp::IsTiff(baton->fileOut);
978
- bool const isJp2 = sharp::IsJp2(baton->fileOut);
979
- bool const isHeif = sharp::IsHeif(baton->fileOut);
980
- bool const isDz = sharp::IsDz(baton->fileOut);
981
- bool const isDzZip = sharp::IsDzZip(baton->fileOut);
982
- bool const isV = sharp::IsV(baton->fileOut);
983
- bool const mightMatchInput = baton->formatOut == "input";
984
- bool const willMatchInput = mightMatchInput &&
985
- !(isJpeg || isPng || isWebp || isGif || isTiff || isJp2 || isHeif || isDz || isDzZip || isV);
986
-
987
- if (baton->formatOut == "jpeg" || (mightMatchInput && isJpeg) ||
988
- (willMatchInput && inputImageType == sharp::ImageType::JPEG)) {
989
- // Write JPEG to file
990
- sharp::AssertImageTypeDimensions(image, sharp::ImageType::JPEG);
991
- image.jpegsave(const_cast<char*>(baton->fileOut.data()), VImage::option()
992
- ->set("strip", !baton->withMetadata)
993
- ->set("Q", baton->jpegQuality)
994
- ->set("interlace", baton->jpegProgressive)
995
- ->set("subsample_mode", baton->jpegChromaSubsampling == "4:4:4"
996
- ? VIPS_FOREIGN_SUBSAMPLE_OFF
997
- : VIPS_FOREIGN_SUBSAMPLE_ON)
998
- ->set("trellis_quant", baton->jpegTrellisQuantisation)
999
- ->set("quant_table", baton->jpegQuantisationTable)
1000
- ->set("overshoot_deringing", baton->jpegOvershootDeringing)
1001
- ->set("optimize_scans", baton->jpegOptimiseScans)
1002
- ->set("optimize_coding", baton->jpegOptimiseCoding));
1003
- baton->formatOut = "jpeg";
1004
- baton->channels = std::min(baton->channels, 3);
1005
- } else if (baton->formatOut == "jp2" || (mightMatchInput && isJp2) ||
1006
- (willMatchInput && (inputImageType == sharp::ImageType::JP2))) {
1007
- // Write JP2 to file
1008
- sharp::AssertImageTypeDimensions(image, sharp::ImageType::JP2);
1009
- image.jp2ksave(const_cast<char*>(baton->fileOut.data()), VImage::option()
1010
- ->set("Q", baton->jp2Quality)
1011
- ->set("lossless", baton->jp2Lossless)
1012
- ->set("subsample_mode", baton->jp2ChromaSubsampling == "4:4:4"
1013
- ? VIPS_FOREIGN_SUBSAMPLE_OFF : VIPS_FOREIGN_SUBSAMPLE_ON)
1014
- ->set("tile_height", baton->jp2TileHeight)
1015
- ->set("tile_width", baton->jp2TileWidth));
1016
- baton->formatOut = "jp2";
1017
- } else if (baton->formatOut == "png" || (mightMatchInput && isPng) || (willMatchInput &&
1018
- (inputImageType == sharp::ImageType::PNG || inputImageType == sharp::ImageType::SVG))) {
1019
- // Write PNG to file
1020
- sharp::AssertImageTypeDimensions(image, sharp::ImageType::PNG);
1021
- image.pngsave(const_cast<char*>(baton->fileOut.data()), VImage::option()
1022
- ->set("strip", !baton->withMetadata)
1023
- ->set("interlace", baton->pngProgressive)
1024
- ->set("compression", baton->pngCompressionLevel)
1025
- ->set("filter", baton->pngAdaptiveFiltering ? VIPS_FOREIGN_PNG_FILTER_ALL : VIPS_FOREIGN_PNG_FILTER_NONE)
1026
- ->set("palette", baton->pngPalette)
1027
- ->set("Q", baton->pngQuality)
1028
- ->set("bitdepth", sharp::Is16Bit(image.interpretation()) ? 16 : baton->pngBitdepth)
1029
- ->set("effort", baton->pngEffort)
1030
- ->set("dither", baton->pngDither));
1031
- baton->formatOut = "png";
1032
- } else if (baton->formatOut == "webp" || (mightMatchInput && isWebp) ||
1033
- (willMatchInput && inputImageType == sharp::ImageType::WEBP)) {
1034
- // Write WEBP to file
1035
- sharp::AssertImageTypeDimensions(image, sharp::ImageType::WEBP);
1036
- image.webpsave(const_cast<char*>(baton->fileOut.data()), VImage::option()
1037
- ->set("strip", !baton->withMetadata)
1038
- ->set("Q", baton->webpQuality)
1039
- ->set("lossless", baton->webpLossless)
1040
- ->set("near_lossless", baton->webpNearLossless)
1041
- ->set("smart_subsample", baton->webpSmartSubsample)
1042
- ->set("effort", baton->webpEffort)
1043
- ->set("alpha_q", baton->webpAlphaQuality));
1044
- baton->formatOut = "webp";
1045
- } else if (baton->formatOut == "gif" || (mightMatchInput && isGif) ||
1046
- (willMatchInput && inputImageType == sharp::ImageType::GIF)) {
1047
- // Write GIF to file
1048
- sharp::AssertImageTypeDimensions(image, sharp::ImageType::GIF);
1049
- image.gifsave(const_cast<char*>(baton->fileOut.data()), VImage::option()
1050
- ->set("strip", !baton->withMetadata)
1051
- ->set("bitdepth", baton->gifBitdepth)
1052
- ->set("effort", baton->gifEffort)
1053
- ->set("dither", baton->gifDither));
1054
- baton->formatOut = "gif";
1055
- } else if (baton->formatOut == "tiff" || (mightMatchInput && isTiff) ||
1056
- (willMatchInput && inputImageType == sharp::ImageType::TIFF)) {
1057
- // Write TIFF to file
1058
- if (baton->tiffCompression == VIPS_FOREIGN_TIFF_COMPRESSION_JPEG) {
1059
- sharp::AssertImageTypeDimensions(image, sharp::ImageType::JPEG);
1060
- baton->channels = std::min(baton->channels, 3);
1061
- }
1062
- // Cast pixel values to float, if required
1063
- if (baton->tiffPredictor == VIPS_FOREIGN_TIFF_PREDICTOR_FLOAT) {
1064
- image = image.cast(VIPS_FORMAT_FLOAT);
1065
- }
1066
- image.tiffsave(const_cast<char*>(baton->fileOut.data()), VImage::option()
1067
- ->set("strip", !baton->withMetadata)
1068
- ->set("Q", baton->tiffQuality)
1069
- ->set("bitdepth", baton->tiffBitdepth)
1070
- ->set("compression", baton->tiffCompression)
1071
- ->set("predictor", baton->tiffPredictor)
1072
- ->set("pyramid", baton->tiffPyramid)
1073
- ->set("tile", baton->tiffTile)
1074
- ->set("tile_height", baton->tiffTileHeight)
1075
- ->set("tile_width", baton->tiffTileWidth)
1076
- ->set("xres", baton->tiffXres)
1077
- ->set("yres", baton->tiffYres)
1078
- ->set("resunit", baton->tiffResolutionUnit));
1079
- baton->formatOut = "tiff";
1080
- } else if (baton->formatOut == "heif" || (mightMatchInput && isHeif) ||
1081
- (willMatchInput && inputImageType == sharp::ImageType::HEIF)) {
1082
- // Write HEIF to file
1083
- image = sharp::RemoveAnimationProperties(image);
1084
- image.heifsave(const_cast<char*>(baton->fileOut.data()), VImage::option()
1085
- ->set("strip", !baton->withMetadata)
1086
- ->set("Q", baton->heifQuality)
1087
- ->set("compression", baton->heifCompression)
1088
- ->set("effort", baton->heifEffort)
1089
- ->set("subsample_mode", baton->heifChromaSubsampling == "4:4:4"
1090
- ? VIPS_FOREIGN_SUBSAMPLE_OFF : VIPS_FOREIGN_SUBSAMPLE_ON)
1091
- ->set("lossless", baton->heifLossless));
1092
- baton->formatOut = "heif";
1093
- } else if (baton->formatOut == "dz" || isDz || isDzZip) {
1094
- if (isDzZip) {
1095
- baton->tileContainer = VIPS_FOREIGN_DZ_CONTAINER_ZIP;
1096
- }
1097
- // Forward format options through suffix
1098
- std::string suffix;
1099
- if (baton->tileFormat == "png") {
1100
- std::vector<std::pair<std::string, std::string>> options {
1101
- {"interlace", baton->pngProgressive ? "TRUE" : "FALSE"},
1102
- {"compression", std::to_string(baton->pngCompressionLevel)},
1103
- {"filter", baton->pngAdaptiveFiltering ? "all" : "none"}
1104
- };
1105
- suffix = AssembleSuffixString(".png", options);
1106
- } else if (baton->tileFormat == "webp") {
1107
- std::vector<std::pair<std::string, std::string>> options {
1108
- {"Q", std::to_string(baton->webpQuality)},
1109
- {"alpha_q", std::to_string(baton->webpAlphaQuality)},
1110
- {"lossless", baton->webpLossless ? "TRUE" : "FALSE"},
1111
- {"near_lossless", baton->webpNearLossless ? "TRUE" : "FALSE"},
1112
- {"smart_subsample", baton->webpSmartSubsample ? "TRUE" : "FALSE"},
1113
- {"effort", std::to_string(baton->webpEffort)}
1114
- };
1115
- suffix = AssembleSuffixString(".webp", options);
1116
- } else {
1117
- std::vector<std::pair<std::string, std::string>> options {
1118
- {"Q", std::to_string(baton->jpegQuality)},
1119
- {"interlace", baton->jpegProgressive ? "TRUE" : "FALSE"},
1120
- {"subsample_mode", baton->jpegChromaSubsampling == "4:4:4" ? "off" : "on"},
1121
- {"trellis_quant", baton->jpegTrellisQuantisation ? "TRUE" : "FALSE"},
1122
- {"quant_table", std::to_string(baton->jpegQuantisationTable)},
1123
- {"overshoot_deringing", baton->jpegOvershootDeringing ? "TRUE": "FALSE"},
1124
- {"optimize_scans", baton->jpegOptimiseScans ? "TRUE": "FALSE"},
1125
- {"optimize_coding", baton->jpegOptimiseCoding ? "TRUE": "FALSE"}
1126
- };
1127
- std::string extname = baton->tileLayout == VIPS_FOREIGN_DZ_LAYOUT_DZ ? ".jpeg" : ".jpg";
1128
- suffix = AssembleSuffixString(extname, options);
1129
- }
1130
- // Remove alpha channel from tile background if image does not contain an alpha channel
1131
- if (!sharp::HasAlpha(image)) {
1132
- baton->tileBackground.pop_back();
1133
- }
1134
- // Write DZ to file
1135
- vips::VOption *options = VImage::option()
1136
- ->set("strip", !baton->withMetadata)
1137
- ->set("tile_size", baton->tileSize)
1138
- ->set("overlap", baton->tileOverlap)
1139
- ->set("container", baton->tileContainer)
1140
- ->set("layout", baton->tileLayout)
1141
- ->set("suffix", const_cast<char*>(suffix.data()))
1142
- ->set("angle", CalculateAngleRotation(baton->tileAngle))
1143
- ->set("background", baton->tileBackground)
1144
- ->set("centre", baton->tileCentre)
1145
- ->set("id", const_cast<char*>(baton->tileId.data()))
1146
- ->set("skip_blanks", baton->tileSkipBlanks);
1147
- // libvips chooses a default depth based on layout. Instead of replicating that logic here by
1148
- // not passing anything - libvips will handle choice
1149
- if (baton->tileDepth < VIPS_FOREIGN_DZ_DEPTH_LAST) {
1150
- options->set("depth", baton->tileDepth);
1151
- }
1152
- image.dzsave(const_cast<char*>(baton->fileOut.data()), options);
1153
- baton->formatOut = "dz";
1154
- } else if (baton->formatOut == "v" || (mightMatchInput && isV) ||
1155
- (willMatchInput && inputImageType == sharp::ImageType::VIPS)) {
1156
- // Write V to file
1157
- image.vipssave(const_cast<char*>(baton->fileOut.data()), VImage::option()
1158
- ->set("strip", !baton->withMetadata));
1159
- baton->formatOut = "v";
1160
- } else {
1161
- // Unsupported output format
1162
- (baton->err).append("Unsupported output format " + baton->fileOut);
1163
- return Error();
1164
- }
1165
- }
1166
- } catch (vips::VError const &err) {
1167
- char const *what = err.what();
1168
- if (what && what[0]) {
1169
- (baton->err).append(what);
1170
- } else {
1171
- (baton->err).append("Unknown error");
1172
- }
1173
- }
1174
- // Clean up libvips' per-request data and threads
1175
- vips_error_clear();
1176
- vips_thread_shutdown();
1177
- }
1178
-
1179
- void OnOK() {
1180
- Napi::Env env = Env();
1181
- Napi::HandleScope scope(env);
1182
-
1183
- // Handle warnings
1184
- std::string warning = sharp::VipsWarningPop();
1185
- while (!warning.empty()) {
1186
- debuglog.Call({ Napi::String::New(env, warning) });
1187
- warning = sharp::VipsWarningPop();
1188
- }
1189
-
1190
- if (baton->err.empty()) {
1191
- int width = baton->width;
1192
- int height = baton->height;
1193
- if (baton->topOffsetPre != -1 && (baton->width == -1 || baton->height == -1)) {
1194
- width = baton->widthPre;
1195
- height = baton->heightPre;
1196
- }
1197
- if (baton->topOffsetPost != -1) {
1198
- width = baton->widthPost;
1199
- height = baton->heightPost;
1200
- }
1201
- // Info Object
1202
- Napi::Object info = Napi::Object::New(env);
1203
- info.Set("format", baton->formatOut);
1204
- info.Set("width", static_cast<uint32_t>(width));
1205
- info.Set("height", static_cast<uint32_t>(height));
1206
- info.Set("channels", static_cast<uint32_t>(baton->channels));
1207
- if (baton->formatOut == "raw") {
1208
- info.Set("depth", vips_enum_nick(VIPS_TYPE_BAND_FORMAT, baton->rawDepth));
1209
- }
1210
- info.Set("premultiplied", baton->premultiplied);
1211
- if (baton->hasCropOffset) {
1212
- info.Set("cropOffsetLeft", static_cast<int32_t>(baton->cropOffsetLeft));
1213
- info.Set("cropOffsetTop", static_cast<int32_t>(baton->cropOffsetTop));
1214
- }
1215
- if (baton->trimThreshold > 0.0) {
1216
- info.Set("trimOffsetLeft", static_cast<int32_t>(baton->trimOffsetLeft));
1217
- info.Set("trimOffsetTop", static_cast<int32_t>(baton->trimOffsetTop));
1218
- }
1219
-
1220
- if (baton->bufferOutLength > 0) {
1221
- // Add buffer size to info
1222
- info.Set("size", static_cast<uint32_t>(baton->bufferOutLength));
1223
- // Pass ownership of output data to Buffer instance
1224
- Napi::Buffer<char> data = Napi::Buffer<char>::New(env, static_cast<char*>(baton->bufferOut),
1225
- baton->bufferOutLength, sharp::FreeCallback);
1226
- Callback().MakeCallback(Receiver().Value(), { env.Null(), data, info });
1227
- } else {
1228
- // Add file size to info
1229
- struct STAT64_STRUCT st;
1230
- if (STAT64_FUNCTION(baton->fileOut.data(), &st) == 0) {
1231
- info.Set("size", static_cast<uint32_t>(st.st_size));
1232
- }
1233
- Callback().MakeCallback(Receiver().Value(), { env.Null(), info });
1234
- }
1235
- } else {
1236
- Callback().MakeCallback(Receiver().Value(), { Napi::Error::New(env, baton->err).Value() });
1237
- }
1238
-
1239
- // Delete baton
1240
- delete baton->input;
1241
- delete baton->boolean;
1242
- for (Composite *composite : baton->composite) {
1243
- delete composite->input;
1244
- delete composite;
1245
- }
1246
- for (sharp::InputDescriptor *input : baton->joinChannelIn) {
1247
- delete input;
1248
- }
1249
- delete baton;
1250
-
1251
- // Decrement processing task counter
1252
- g_atomic_int_dec_and_test(&sharp::counterProcess);
1253
- Napi::Number queueLength = Napi::Number::New(env, static_cast<double>(sharp::counterQueue));
1254
- queueListener.Call(Receiver().Value(), { queueLength });
1255
- }
1256
-
1257
- private:
1258
- PipelineBaton *baton;
1259
- Napi::FunctionReference debuglog;
1260
- Napi::FunctionReference queueListener;
1261
-
1262
- void MultiPageUnsupported(int const pages, std::string op) {
1263
- if (pages > 1) {
1264
- throw vips::VError(op + " is not supported for multi-page images");
1265
- }
1266
- }
1267
-
1268
- /*
1269
- Calculate the angle of rotation and need-to-flip for the given Exif orientation
1270
- By default, returns zero, i.e. no rotation.
1271
- */
1272
- std::tuple<VipsAngle, bool, bool>
1273
- CalculateExifRotationAndFlip(int const exifOrientation) {
1274
- VipsAngle rotate = VIPS_ANGLE_D0;
1275
- bool flip = FALSE;
1276
- bool flop = FALSE;
1277
- switch (exifOrientation) {
1278
- case 6: rotate = VIPS_ANGLE_D90; break;
1279
- case 3: rotate = VIPS_ANGLE_D180; break;
1280
- case 8: rotate = VIPS_ANGLE_D270; break;
1281
- case 2: flop = TRUE; break; // flop 1
1282
- case 7: flip = TRUE; rotate = VIPS_ANGLE_D90; break; // flip 6
1283
- case 4: flop = TRUE; rotate = VIPS_ANGLE_D180; break; // flop 3
1284
- case 5: flip = TRUE; rotate = VIPS_ANGLE_D270; break; // flip 8
1285
- }
1286
- return std::make_tuple(rotate, flip, flop);
1287
- }
1288
-
1289
- /*
1290
- Calculate the rotation for the given angle.
1291
- Supports any positive or negative angle that is a multiple of 90.
1292
- */
1293
- VipsAngle
1294
- CalculateAngleRotation(int angle) {
1295
- angle = angle % 360;
1296
- if (angle < 0)
1297
- angle = 360 + angle;
1298
- switch (angle) {
1299
- case 90: return VIPS_ANGLE_D90;
1300
- case 180: return VIPS_ANGLE_D180;
1301
- case 270: return VIPS_ANGLE_D270;
1302
- }
1303
- return VIPS_ANGLE_D0;
1304
- }
1305
-
1306
- /*
1307
- Assemble the suffix argument to dzsave, which is the format (by extname)
1308
- alongisde comma-separated arguments to the corresponding `formatsave` vips
1309
- action.
1310
- */
1311
- std::string
1312
- AssembleSuffixString(std::string extname, std::vector<std::pair<std::string, std::string>> options) {
1313
- std::string argument;
1314
- for (auto const &option : options) {
1315
- if (!argument.empty()) {
1316
- argument += ",";
1317
- }
1318
- argument += option.first + "=" + option.second;
1319
- }
1320
- return extname + "[" + argument + "]";
1321
- }
1322
-
1323
- /*
1324
- Clear all thread-local data.
1325
- */
1326
- void Error() {
1327
- // Clean up libvips' per-request data and threads
1328
- vips_error_clear();
1329
- vips_thread_shutdown();
1330
- }
1331
- };
1332
-
1333
- /*
1334
- pipeline(options, output, callback)
1335
- */
1336
- Napi::Value pipeline(const Napi::CallbackInfo& info) {
1337
- // V8 objects are converted to non-V8 types held in the baton struct
1338
- PipelineBaton *baton = new PipelineBaton;
1339
- Napi::Object options = info[0].As<Napi::Object>();
1340
-
1341
- // Input
1342
- baton->input = sharp::CreateInputDescriptor(options.Get("input").As<Napi::Object>());
1343
- // Extract image options
1344
- baton->topOffsetPre = sharp::AttrAsInt32(options, "topOffsetPre");
1345
- baton->leftOffsetPre = sharp::AttrAsInt32(options, "leftOffsetPre");
1346
- baton->widthPre = sharp::AttrAsInt32(options, "widthPre");
1347
- baton->heightPre = sharp::AttrAsInt32(options, "heightPre");
1348
- baton->topOffsetPost = sharp::AttrAsInt32(options, "topOffsetPost");
1349
- baton->leftOffsetPost = sharp::AttrAsInt32(options, "leftOffsetPost");
1350
- baton->widthPost = sharp::AttrAsInt32(options, "widthPost");
1351
- baton->heightPost = sharp::AttrAsInt32(options, "heightPost");
1352
- // Output image dimensions
1353
- baton->width = sharp::AttrAsInt32(options, "width");
1354
- baton->height = sharp::AttrAsInt32(options, "height");
1355
- // Canvas option
1356
- std::string canvas = sharp::AttrAsStr(options, "canvas");
1357
- if (canvas == "crop") {
1358
- baton->canvas = sharp::Canvas::CROP;
1359
- } else if (canvas == "embed") {
1360
- baton->canvas = sharp::Canvas::EMBED;
1361
- } else if (canvas == "max") {
1362
- baton->canvas = sharp::Canvas::MAX;
1363
- } else if (canvas == "min") {
1364
- baton->canvas = sharp::Canvas::MIN;
1365
- } else if (canvas == "ignore_aspect") {
1366
- baton->canvas = sharp::Canvas::IGNORE_ASPECT;
1367
- }
1368
- // Tint chroma
1369
- baton->tintA = sharp::AttrAsDouble(options, "tintA");
1370
- baton->tintB = sharp::AttrAsDouble(options, "tintB");
1371
- // Composite
1372
- Napi::Array compositeArray = options.Get("composite").As<Napi::Array>();
1373
- for (unsigned int i = 0; i < compositeArray.Length(); i++) {
1374
- Napi::Object compositeObject = compositeArray.Get(i).As<Napi::Object>();
1375
- Composite *composite = new Composite;
1376
- composite->input = sharp::CreateInputDescriptor(compositeObject.Get("input").As<Napi::Object>());
1377
- composite->mode = static_cast<VipsBlendMode>(
1378
- vips_enum_from_nick(nullptr, VIPS_TYPE_BLEND_MODE, sharp::AttrAsStr(compositeObject, "blend").data()));
1379
- composite->gravity = sharp::AttrAsUint32(compositeObject, "gravity");
1380
- composite->left = sharp::AttrAsInt32(compositeObject, "left");
1381
- composite->top = sharp::AttrAsInt32(compositeObject, "top");
1382
- composite->hasOffset = sharp::AttrAsBool(compositeObject, "hasOffset");
1383
- composite->tile = sharp::AttrAsBool(compositeObject, "tile");
1384
- composite->premultiplied = sharp::AttrAsBool(compositeObject, "premultiplied");
1385
- baton->composite.push_back(composite);
1386
- }
1387
- // Resize options
1388
- baton->withoutEnlargement = sharp::AttrAsBool(options, "withoutEnlargement");
1389
- baton->withoutReduction = sharp::AttrAsBool(options, "withoutReduction");
1390
- baton->position = sharp::AttrAsInt32(options, "position");
1391
- baton->resizeBackground = sharp::AttrAsVectorOfDouble(options, "resizeBackground");
1392
- baton->kernel = sharp::AttrAsStr(options, "kernel");
1393
- baton->fastShrinkOnLoad = sharp::AttrAsBool(options, "fastShrinkOnLoad");
1394
- // Join Channel Options
1395
- if (options.Has("joinChannelIn")) {
1396
- Napi::Array joinChannelArray = options.Get("joinChannelIn").As<Napi::Array>();
1397
- for (unsigned int i = 0; i < joinChannelArray.Length(); i++) {
1398
- baton->joinChannelIn.push_back(
1399
- sharp::CreateInputDescriptor(joinChannelArray.Get(i).As<Napi::Object>()));
1400
- }
1401
- }
1402
- // Operators
1403
- baton->flatten = sharp::AttrAsBool(options, "flatten");
1404
- baton->flattenBackground = sharp::AttrAsVectorOfDouble(options, "flattenBackground");
1405
- baton->negate = sharp::AttrAsBool(options, "negate");
1406
- baton->negateAlpha = sharp::AttrAsBool(options, "negateAlpha");
1407
- baton->blurSigma = sharp::AttrAsDouble(options, "blurSigma");
1408
- baton->brightness = sharp::AttrAsDouble(options, "brightness");
1409
- baton->saturation = sharp::AttrAsDouble(options, "saturation");
1410
- baton->hue = sharp::AttrAsInt32(options, "hue");
1411
- baton->lightness = sharp::AttrAsDouble(options, "lightness");
1412
- baton->medianSize = sharp::AttrAsUint32(options, "medianSize");
1413
- baton->sharpenSigma = sharp::AttrAsDouble(options, "sharpenSigma");
1414
- baton->sharpenM1 = sharp::AttrAsDouble(options, "sharpenM1");
1415
- baton->sharpenM2 = sharp::AttrAsDouble(options, "sharpenM2");
1416
- baton->sharpenX1 = sharp::AttrAsDouble(options, "sharpenX1");
1417
- baton->sharpenY2 = sharp::AttrAsDouble(options, "sharpenY2");
1418
- baton->sharpenY3 = sharp::AttrAsDouble(options, "sharpenY3");
1419
- baton->threshold = sharp::AttrAsInt32(options, "threshold");
1420
- baton->thresholdGrayscale = sharp::AttrAsBool(options, "thresholdGrayscale");
1421
- baton->trimThreshold = sharp::AttrAsDouble(options, "trimThreshold");
1422
- baton->gamma = sharp::AttrAsDouble(options, "gamma");
1423
- baton->gammaOut = sharp::AttrAsDouble(options, "gammaOut");
1424
- baton->linearA = sharp::AttrAsDouble(options, "linearA");
1425
- baton->linearB = sharp::AttrAsDouble(options, "linearB");
1426
- baton->greyscale = sharp::AttrAsBool(options, "greyscale");
1427
- baton->normalise = sharp::AttrAsBool(options, "normalise");
1428
- baton->claheWidth = sharp::AttrAsUint32(options, "claheWidth");
1429
- baton->claheHeight = sharp::AttrAsUint32(options, "claheHeight");
1430
- baton->claheMaxSlope = sharp::AttrAsUint32(options, "claheMaxSlope");
1431
- baton->useExifOrientation = sharp::AttrAsBool(options, "useExifOrientation");
1432
- baton->angle = sharp::AttrAsInt32(options, "angle");
1433
- baton->rotationAngle = sharp::AttrAsDouble(options, "rotationAngle");
1434
- baton->rotationBackground = sharp::AttrAsVectorOfDouble(options, "rotationBackground");
1435
- baton->rotateBeforePreExtract = sharp::AttrAsBool(options, "rotateBeforePreExtract");
1436
- baton->flip = sharp::AttrAsBool(options, "flip");
1437
- baton->flop = sharp::AttrAsBool(options, "flop");
1438
- baton->extendTop = sharp::AttrAsInt32(options, "extendTop");
1439
- baton->extendBottom = sharp::AttrAsInt32(options, "extendBottom");
1440
- baton->extendLeft = sharp::AttrAsInt32(options, "extendLeft");
1441
- baton->extendRight = sharp::AttrAsInt32(options, "extendRight");
1442
- baton->extendBackground = sharp::AttrAsVectorOfDouble(options, "extendBackground");
1443
- baton->extractChannel = sharp::AttrAsInt32(options, "extractChannel");
1444
- baton->affineMatrix = sharp::AttrAsVectorOfDouble(options, "affineMatrix");
1445
- baton->affineBackground = sharp::AttrAsVectorOfDouble(options, "affineBackground");
1446
- baton->affineIdx = sharp::AttrAsDouble(options, "affineIdx");
1447
- baton->affineIdy = sharp::AttrAsDouble(options, "affineIdy");
1448
- baton->affineOdx = sharp::AttrAsDouble(options, "affineOdx");
1449
- baton->affineOdy = sharp::AttrAsDouble(options, "affineOdy");
1450
- baton->affineInterpolator = sharp::AttrAsStr(options, "affineInterpolator");
1451
- baton->removeAlpha = sharp::AttrAsBool(options, "removeAlpha");
1452
- baton->ensureAlpha = sharp::AttrAsDouble(options, "ensureAlpha");
1453
- if (options.Has("boolean")) {
1454
- baton->boolean = sharp::CreateInputDescriptor(options.Get("boolean").As<Napi::Object>());
1455
- baton->booleanOp = sharp::GetBooleanOperation(sharp::AttrAsStr(options, "booleanOp"));
1456
- }
1457
- if (options.Has("bandBoolOp")) {
1458
- baton->bandBoolOp = sharp::GetBooleanOperation(sharp::AttrAsStr(options, "bandBoolOp"));
1459
- }
1460
- if (options.Has("convKernel")) {
1461
- Napi::Object kernel = options.Get("convKernel").As<Napi::Object>();
1462
- baton->convKernelWidth = sharp::AttrAsUint32(kernel, "width");
1463
- baton->convKernelHeight = sharp::AttrAsUint32(kernel, "height");
1464
- baton->convKernelScale = sharp::AttrAsDouble(kernel, "scale");
1465
- baton->convKernelOffset = sharp::AttrAsDouble(kernel, "offset");
1466
- size_t const kernelSize = static_cast<size_t>(baton->convKernelWidth * baton->convKernelHeight);
1467
- baton->convKernel = std::unique_ptr<double[]>(new double[kernelSize]);
1468
- Napi::Array kdata = kernel.Get("kernel").As<Napi::Array>();
1469
- for (unsigned int i = 0; i < kernelSize; i++) {
1470
- baton->convKernel[i] = sharp::AttrAsDouble(kdata, i);
1471
- }
1472
- }
1473
- if (options.Has("recombMatrix")) {
1474
- baton->recombMatrix = std::unique_ptr<double[]>(new double[9]);
1475
- Napi::Array recombMatrix = options.Get("recombMatrix").As<Napi::Array>();
1476
- for (unsigned int i = 0; i < 9; i++) {
1477
- baton->recombMatrix[i] = sharp::AttrAsDouble(recombMatrix, i);
1478
- }
1479
- }
1480
- baton->colourspaceInput = sharp::GetInterpretation(sharp::AttrAsStr(options, "colourspaceInput"));
1481
- if (baton->colourspaceInput == VIPS_INTERPRETATION_ERROR) {
1482
- baton->colourspaceInput = VIPS_INTERPRETATION_LAST;
1483
- }
1484
- baton->colourspace = sharp::GetInterpretation(sharp::AttrAsStr(options, "colourspace"));
1485
- if (baton->colourspace == VIPS_INTERPRETATION_ERROR) {
1486
- baton->colourspace = VIPS_INTERPRETATION_sRGB;
1487
- }
1488
- // Output
1489
- baton->formatOut = sharp::AttrAsStr(options, "formatOut");
1490
- baton->fileOut = sharp::AttrAsStr(options, "fileOut");
1491
- baton->withMetadata = sharp::AttrAsBool(options, "withMetadata");
1492
- baton->withMetadataOrientation = sharp::AttrAsUint32(options, "withMetadataOrientation");
1493
- baton->withMetadataDensity = sharp::AttrAsDouble(options, "withMetadataDensity");
1494
- baton->withMetadataIcc = sharp::AttrAsStr(options, "withMetadataIcc");
1495
- Napi::Object mdStrs = options.Get("withMetadataStrs").As<Napi::Object>();
1496
- Napi::Array mdStrKeys = mdStrs.GetPropertyNames();
1497
- for (unsigned int i = 0; i < mdStrKeys.Length(); i++) {
1498
- std::string k = sharp::AttrAsStr(mdStrKeys, i);
1499
- baton->withMetadataStrs.insert(std::make_pair(k, sharp::AttrAsStr(mdStrs, k)));
1500
- }
1501
- baton->timeoutSeconds = sharp::AttrAsUint32(options, "timeoutSeconds");
1502
- // Format-specific
1503
- baton->jpegQuality = sharp::AttrAsUint32(options, "jpegQuality");
1504
- baton->jpegProgressive = sharp::AttrAsBool(options, "jpegProgressive");
1505
- baton->jpegChromaSubsampling = sharp::AttrAsStr(options, "jpegChromaSubsampling");
1506
- baton->jpegTrellisQuantisation = sharp::AttrAsBool(options, "jpegTrellisQuantisation");
1507
- baton->jpegQuantisationTable = sharp::AttrAsUint32(options, "jpegQuantisationTable");
1508
- baton->jpegOvershootDeringing = sharp::AttrAsBool(options, "jpegOvershootDeringing");
1509
- baton->jpegOptimiseScans = sharp::AttrAsBool(options, "jpegOptimiseScans");
1510
- baton->jpegOptimiseCoding = sharp::AttrAsBool(options, "jpegOptimiseCoding");
1511
- baton->pngProgressive = sharp::AttrAsBool(options, "pngProgressive");
1512
- baton->pngCompressionLevel = sharp::AttrAsUint32(options, "pngCompressionLevel");
1513
- baton->pngAdaptiveFiltering = sharp::AttrAsBool(options, "pngAdaptiveFiltering");
1514
- baton->pngPalette = sharp::AttrAsBool(options, "pngPalette");
1515
- baton->pngQuality = sharp::AttrAsUint32(options, "pngQuality");
1516
- baton->pngEffort = sharp::AttrAsUint32(options, "pngEffort");
1517
- baton->pngBitdepth = sharp::AttrAsUint32(options, "pngBitdepth");
1518
- baton->pngDither = sharp::AttrAsDouble(options, "pngDither");
1519
- baton->jp2Quality = sharp::AttrAsUint32(options, "jp2Quality");
1520
- baton->jp2Lossless = sharp::AttrAsBool(options, "jp2Lossless");
1521
- baton->jp2TileHeight = sharp::AttrAsUint32(options, "jp2TileHeight");
1522
- baton->jp2TileWidth = sharp::AttrAsUint32(options, "jp2TileWidth");
1523
- baton->jp2ChromaSubsampling = sharp::AttrAsStr(options, "jp2ChromaSubsampling");
1524
- baton->webpQuality = sharp::AttrAsUint32(options, "webpQuality");
1525
- baton->webpAlphaQuality = sharp::AttrAsUint32(options, "webpAlphaQuality");
1526
- baton->webpLossless = sharp::AttrAsBool(options, "webpLossless");
1527
- baton->webpNearLossless = sharp::AttrAsBool(options, "webpNearLossless");
1528
- baton->webpSmartSubsample = sharp::AttrAsBool(options, "webpSmartSubsample");
1529
- baton->webpEffort = sharp::AttrAsUint32(options, "webpEffort");
1530
- baton->gifBitdepth = sharp::AttrAsUint32(options, "gifBitdepth");
1531
- baton->gifEffort = sharp::AttrAsUint32(options, "gifEffort");
1532
- baton->gifDither = sharp::AttrAsDouble(options, "gifDither");
1533
- baton->tiffQuality = sharp::AttrAsUint32(options, "tiffQuality");
1534
- baton->tiffPyramid = sharp::AttrAsBool(options, "tiffPyramid");
1535
- baton->tiffBitdepth = sharp::AttrAsUint32(options, "tiffBitdepth");
1536
- baton->tiffTile = sharp::AttrAsBool(options, "tiffTile");
1537
- baton->tiffTileWidth = sharp::AttrAsUint32(options, "tiffTileWidth");
1538
- baton->tiffTileHeight = sharp::AttrAsUint32(options, "tiffTileHeight");
1539
- baton->tiffXres = sharp::AttrAsDouble(options, "tiffXres");
1540
- baton->tiffYres = sharp::AttrAsDouble(options, "tiffYres");
1541
- if (baton->tiffXres == 1.0 && baton->tiffYres == 1.0 && baton->withMetadataDensity > 0) {
1542
- baton->tiffXres = baton->tiffYres = baton->withMetadataDensity / 25.4;
1543
- }
1544
- // tiff compression options
1545
- baton->tiffCompression = static_cast<VipsForeignTiffCompression>(
1546
- vips_enum_from_nick(nullptr, VIPS_TYPE_FOREIGN_TIFF_COMPRESSION,
1547
- sharp::AttrAsStr(options, "tiffCompression").data()));
1548
- baton->tiffPredictor = static_cast<VipsForeignTiffPredictor>(
1549
- vips_enum_from_nick(nullptr, VIPS_TYPE_FOREIGN_TIFF_PREDICTOR,
1550
- sharp::AttrAsStr(options, "tiffPredictor").data()));
1551
- baton->tiffResolutionUnit = static_cast<VipsForeignTiffResunit>(
1552
- vips_enum_from_nick(nullptr, VIPS_TYPE_FOREIGN_TIFF_RESUNIT,
1553
- sharp::AttrAsStr(options, "tiffResolutionUnit").data()));
1554
-
1555
- baton->heifQuality = sharp::AttrAsUint32(options, "heifQuality");
1556
- baton->heifLossless = sharp::AttrAsBool(options, "heifLossless");
1557
- baton->heifCompression = static_cast<VipsForeignHeifCompression>(
1558
- vips_enum_from_nick(nullptr, VIPS_TYPE_FOREIGN_HEIF_COMPRESSION,
1559
- sharp::AttrAsStr(options, "heifCompression").data()));
1560
- baton->heifEffort = sharp::AttrAsUint32(options, "heifEffort");
1561
- baton->heifChromaSubsampling = sharp::AttrAsStr(options, "heifChromaSubsampling");
1562
- // Raw output
1563
- baton->rawDepth = static_cast<VipsBandFormat>(
1564
- vips_enum_from_nick(nullptr, VIPS_TYPE_BAND_FORMAT,
1565
- sharp::AttrAsStr(options, "rawDepth").data()));
1566
- // Animated output properties
1567
- if (sharp::HasAttr(options, "loop")) {
1568
- baton->loop = sharp::AttrAsUint32(options, "loop");
1569
- }
1570
- if (sharp::HasAttr(options, "delay")) {
1571
- baton->delay = sharp::AttrAsInt32Vector(options, "delay");
1572
- }
1573
- // Tile output
1574
- baton->tileSize = sharp::AttrAsUint32(options, "tileSize");
1575
- baton->tileOverlap = sharp::AttrAsUint32(options, "tileOverlap");
1576
- baton->tileAngle = sharp::AttrAsInt32(options, "tileAngle");
1577
- baton->tileBackground = sharp::AttrAsVectorOfDouble(options, "tileBackground");
1578
- baton->tileSkipBlanks = sharp::AttrAsInt32(options, "tileSkipBlanks");
1579
- baton->tileContainer = static_cast<VipsForeignDzContainer>(
1580
- vips_enum_from_nick(nullptr, VIPS_TYPE_FOREIGN_DZ_CONTAINER,
1581
- sharp::AttrAsStr(options, "tileContainer").data()));
1582
- baton->tileLayout = static_cast<VipsForeignDzLayout>(
1583
- vips_enum_from_nick(nullptr, VIPS_TYPE_FOREIGN_DZ_LAYOUT,
1584
- sharp::AttrAsStr(options, "tileLayout").data()));
1585
- baton->tileFormat = sharp::AttrAsStr(options, "tileFormat");
1586
- baton->tileDepth = static_cast<VipsForeignDzDepth>(
1587
- vips_enum_from_nick(nullptr, VIPS_TYPE_FOREIGN_DZ_DEPTH,
1588
- sharp::AttrAsStr(options, "tileDepth").data()));
1589
- baton->tileCentre = sharp::AttrAsBool(options, "tileCentre");
1590
- baton->tileId = sharp::AttrAsStr(options, "tileId");
1591
-
1592
- // Force random access for certain operations
1593
- if (baton->input->access == VIPS_ACCESS_SEQUENTIAL) {
1594
- if (
1595
- baton->trimThreshold > 0.0 ||
1596
- baton->normalise ||
1597
- baton->position == 16 || baton->position == 17 ||
1598
- baton->angle % 360 != 0 ||
1599
- fmod(baton->rotationAngle, 360.0) != 0.0 ||
1600
- baton->useExifOrientation
1601
- ) {
1602
- baton->input->access = VIPS_ACCESS_RANDOM;
1603
- }
1604
- }
1605
-
1606
- // Function to notify of libvips warnings
1607
- Napi::Function debuglog = options.Get("debuglog").As<Napi::Function>();
1608
-
1609
- // Function to notify of queue length changes
1610
- Napi::Function queueListener = options.Get("queueListener").As<Napi::Function>();
1611
-
1612
- // Join queue for worker thread
1613
- Napi::Function callback = info[1].As<Napi::Function>();
1614
- PipelineWorker *worker = new PipelineWorker(callback, baton, debuglog, queueListener);
1615
- worker->Receiver().Set("options", options);
1616
- worker->Queue();
1617
-
1618
- // Increment queued task counter
1619
- g_atomic_int_inc(&sharp::counterQueue);
1620
- Napi::Number queueLength = Napi::Number::New(info.Env(), static_cast<double>(sharp::counterQueue));
1621
- queueListener.Call(info.This(), { queueLength });
1622
-
1623
- return info.Env().Undefined();
1624
- }