SplitColourChannels.mjs 3.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102
  1. /**
  2. * @author Matt C [matt@artemisbot.uk]
  3. * @copyright Crown Copyright 2018
  4. * @license Apache-2.0
  5. */
  6. import Operation from "../Operation";
  7. import OperationError from "../errors/OperationError";
  8. import Utils from "../Utils";
  9. import {isImage} from "../lib/FileType";
  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 = "byteArray";
  25. this.outputType = "List<File>";
  26. this.presentType = "html";
  27. this.args = [];
  28. }
  29. /**
  30. * @param {byteArray} input
  31. * @param {Object[]} args
  32. * @returns {List<File>}
  33. */
  34. async run(input, args) {
  35. // Make sure that the input is an image
  36. if (!isImage(input)) throw new OperationError("Invalid file type.");
  37. const parsedImage = await jimp.read(Buffer.from(input));
  38. const red = new Promise(async (resolve, reject) => {
  39. try {
  40. const split = parsedImage
  41. .clone()
  42. .color([
  43. {apply: "blue", params: [-255]},
  44. {apply: "green", params: [-255]}
  45. ])
  46. .getBufferAsync(jimp.MIME_PNG);
  47. resolve(new File([new Uint8Array((await split).values())], "red.png", {type: "image/png"}));
  48. } catch (err) {
  49. reject(new OperationError(`Could not split red channel: ${err}`));
  50. }
  51. });
  52. const green = new Promise(async (resolve, reject) => {
  53. try {
  54. const split = parsedImage.clone()
  55. .color([
  56. {apply: "red", params: [-255]},
  57. {apply: "blue", params: [-255]},
  58. ]).getBufferAsync(jimp.MIME_PNG);
  59. resolve(new File([new Uint8Array((await split).values())], "green.png", {type: "image/png"}));
  60. } catch (err) {
  61. reject(new OperationError(`Could not split green channel: ${err}`));
  62. }
  63. });
  64. const blue = new Promise(async (resolve, reject) => {
  65. try {
  66. const split = parsedImage
  67. .color([
  68. {apply: "red", params: [-255]},
  69. {apply: "green", params: [-255]},
  70. ]).getBufferAsync(jimp.MIME_PNG);
  71. resolve(new File([new Uint8Array((await split).values())], "blue.png", {type: "image/png"}));
  72. } catch (err) {
  73. reject(new OperationError(`Could not split blue channel: ${err}`));
  74. }
  75. });
  76. return await Promise.all([red, green, blue]);
  77. }
  78. /**
  79. * Displays the files in HTML for web apps.
  80. *
  81. * @param {File[]} files
  82. * @returns {html}
  83. */
  84. async present(files) {
  85. return await Utils.displayFilesAsHTML(files);
  86. }
  87. }
  88. export default SplitColourChannels;