SplitColourChannels.mjs 3.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103
  1. /**
  2. * @author Matt C [matt@artemisbot.uk]
  3. * @copyright Crown Copyright 2018
  4. * @license Apache-2.0
  5. */
  6. import Operation from "../Operation.mjs";
  7. import OperationError from "../errors/OperationError.mjs";
  8. import Utils from "../Utils.mjs";
  9. import {isImage} from "../lib/FileType.mjs";
  10. import jimp from "jimp";
  11. /**
  12. * Split Colour Channels operation
  13. */
  14. class SplitColourChannels extends Operation {
  15. /**
  16. * SplitColourChannels constructor
  17. */
  18. constructor() {
  19. super();
  20. this.name = "Split Colour Channels";
  21. this.module = "Image";
  22. this.description = "Splits the given image into its red, green and blue colour channels.";
  23. this.infoURL = "https://wikipedia.org/wiki/Channel_(digital_image)";
  24. this.inputType = "ArrayBuffer";
  25. this.outputType = "List<File>";
  26. this.presentType = "html";
  27. this.args = [];
  28. }
  29. /**
  30. * @param {ArrayBuffer} input
  31. * @param {Object[]} args
  32. * @returns {List<File>}
  33. */
  34. async run(input, args) {
  35. input = new Uint8Array(input);
  36. // Make sure that the input is an image
  37. if (!isImage(input)) throw new OperationError("Invalid file type.");
  38. const parsedImage = await jimp.read(Buffer.from(input));
  39. const red = new Promise(async (resolve, reject) => {
  40. try {
  41. const split = parsedImage
  42. .clone()
  43. .color([
  44. {apply: "blue", params: [-255]},
  45. {apply: "green", params: [-255]}
  46. ])
  47. .getBufferAsync(jimp.MIME_PNG);
  48. resolve(new File([new Uint8Array((await split).values())], "red.png", {type: "image/png"}));
  49. } catch (err) {
  50. reject(new OperationError(`Could not split red channel: ${err}`));
  51. }
  52. });
  53. const green = new Promise(async (resolve, reject) => {
  54. try {
  55. const split = parsedImage.clone()
  56. .color([
  57. {apply: "red", params: [-255]},
  58. {apply: "blue", params: [-255]},
  59. ]).getBufferAsync(jimp.MIME_PNG);
  60. resolve(new File([new Uint8Array((await split).values())], "green.png", {type: "image/png"}));
  61. } catch (err) {
  62. reject(new OperationError(`Could not split green channel: ${err}`));
  63. }
  64. });
  65. const blue = new Promise(async (resolve, reject) => {
  66. try {
  67. const split = parsedImage
  68. .color([
  69. {apply: "red", params: [-255]},
  70. {apply: "green", params: [-255]},
  71. ]).getBufferAsync(jimp.MIME_PNG);
  72. resolve(new File([new Uint8Array((await split).values())], "blue.png", {type: "image/png"}));
  73. } catch (err) {
  74. reject(new OperationError(`Could not split blue channel: ${err}`));
  75. }
  76. });
  77. return await Promise.all([red, green, blue]);
  78. }
  79. /**
  80. * Displays the files in HTML for web apps.
  81. *
  82. * @param {File[]} files
  83. * @returns {html}
  84. */
  85. async present(files) {
  86. return await Utils.displayFilesAsHTML(files);
  87. }
  88. }
  89. export default SplitColourChannels;