ResizeImage.mjs 3.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138
  1. /**
  2. * @author j433866 [j433866@gmail.com]
  3. * @copyright Crown Copyright 2019
  4. * @license Apache-2.0
  5. */
  6. import Operation from "../Operation";
  7. import OperationError from "../errors/OperationError";
  8. import { isImage } from "../lib/FileType";
  9. import { toBase64 } from "../lib/Base64.mjs";
  10. import jimp from "jimp";
  11. /**
  12. * Resize Image operation
  13. */
  14. class ResizeImage extends Operation {
  15. /**
  16. * ResizeImage constructor
  17. */
  18. constructor() {
  19. super();
  20. this.name = "Resize Image";
  21. this.module = "Image";
  22. this.description = "Resizes an image to the specified width and height values.";
  23. this.infoURL = "https://wikipedia.org/wiki/Image_scaling";
  24. this.inputType = "byteArray";
  25. this.outputType = "byteArray";
  26. this.presentType = "html";
  27. this.args = [
  28. {
  29. name: "Width",
  30. type: "number",
  31. value: 100,
  32. min: 1
  33. },
  34. {
  35. name: "Height",
  36. type: "number",
  37. value: 100,
  38. min: 1
  39. },
  40. {
  41. name: "Unit type",
  42. type: "option",
  43. value: ["Pixels", "Percent"]
  44. },
  45. {
  46. name: "Maintain aspect ratio",
  47. type: "boolean",
  48. value: false
  49. },
  50. {
  51. name: "Resizing algorithm",
  52. type: "option",
  53. value: [
  54. "Nearest Neighbour",
  55. "Bilinear",
  56. "Bicubic",
  57. "Hermite",
  58. "Bezier"
  59. ],
  60. defaultIndex: 1
  61. }
  62. ];
  63. }
  64. /**
  65. * @param {byteArray} input
  66. * @param {Object[]} args
  67. * @returns {byteArray}
  68. */
  69. async run(input, args) {
  70. let width = args[0],
  71. height = args[1];
  72. const unit = args[2],
  73. aspect = args[3],
  74. resizeAlg = args[4];
  75. const resizeMap = {
  76. "Nearest Neighbour": jimp.RESIZE_NEAREST_NEIGHBOR,
  77. "Bilinear": jimp.RESIZE_BILINEAR,
  78. "Bicubic": jimp.RESIZE_BICUBIC,
  79. "Hermite": jimp.RESIZE_HERMITE,
  80. "Bezier": jimp.RESIZE_BEZIER
  81. };
  82. if (!isImage(input)) {
  83. throw new OperationError("Invalid file type.");
  84. }
  85. let image;
  86. try {
  87. image = await jimp.read(Buffer.from(input));
  88. } catch (err) {
  89. throw new OperationError(`Error loading image. (${err})`);
  90. }
  91. try {
  92. if (unit === "Percent") {
  93. width = image.getWidth() * (width / 100);
  94. height = image.getHeight() * (height / 100);
  95. }
  96. if (ENVIRONMENT_IS_WORKER())
  97. self.sendStatusMessage("Resizing image...");
  98. if (aspect) {
  99. image.scaleToFit(width, height, resizeMap[resizeAlg]);
  100. } else {
  101. image.resize(width, height, resizeMap[resizeAlg]);
  102. }
  103. const imageBuffer = await image.getBufferAsync(jimp.AUTO);
  104. return [...imageBuffer];
  105. } catch (err) {
  106. throw new OperationError(`Error resizing image. (${err})`);
  107. }
  108. }
  109. /**
  110. * Displays the resized image using HTML for web apps
  111. * @param {byteArray} data
  112. * @returns {html}
  113. */
  114. present(data) {
  115. if (!data.length) return "";
  116. const type = isImage(data);
  117. if (!type) {
  118. throw new OperationError("Invalid file type.");
  119. }
  120. return `<img src="data:${type};base64,${toBase64(data)}">`;
  121. }
  122. }
  123. export default ResizeImage;