Merge branch 'features/colour-channel' of https://github.com/artemisbot/CyberChef into artemisbot-features/colour-channel

master
n1474335 2018-12-26 16:10:44 +00:00
commit 02b92c7977
5 changed files with 156 additions and 2 deletions

View File

@ -5,7 +5,7 @@
*/ */
import utf8 from "utf8"; import utf8 from "utf8";
import {fromBase64} from "./lib/Base64"; import {fromBase64, toBase64} from "./lib/Base64";
import {fromHex} from "./lib/Hex"; import {fromHex} from "./lib/Hex";
import {fromDecimal} from "./lib/Decimal"; import {fromDecimal} from "./lib/Decimal";
import {fromBinary} from "./lib/Binary"; import {fromBinary} from "./lib/Binary";
@ -817,6 +817,17 @@ class Utils {
return html; return html;
}; };
const formatContent = function (buff, type) {
if (type.startsWith("image")) {
let dataURI = "data:";
dataURI += type + ";";
dataURI += "base64," + toBase64(buff);
return "<img style='max-width: 100%;' src='" + dataURI + "'>";
} else {
return `<pre>${Utils.escapeHtml(Utils.arrayBufferToStr(buff.buffer))}</pre>`;
}
};
const formatFile = async function(file, i) { const formatFile = async function(file, i) {
const buff = await Utils.readFile(file); const buff = await Utils.readFile(file);
const blob = new Blob( const blob = new Blob(
@ -846,7 +857,7 @@ class Utils {
</div> </div>
<div id='collapse${i}' class='collapse' aria-labelledby='heading${i}' data-parent="#files"> <div id='collapse${i}' class='collapse' aria-labelledby='heading${i}' data-parent="#files">
<div class='card-body'> <div class='card-body'>
<pre>${Utils.escapeHtml(Utils.arrayBufferToStr(buff.buffer))}</pre> ${formatContent(buff, file.type)}
</div> </div>
</div> </div>
</div>`; </div>`;

View File

@ -366,6 +366,10 @@
"Generate QR Code", "Generate QR Code",
"Parse QR Code", "Parse QR Code",
"Haversine distance", "Haversine distance",
"Render Image",
"Remove EXIF",
"Extract EXIF",
"Split Colour Channels",
"Numberwang", "Numberwang",
"XKCD Random Number" "XKCD Random Number"
] ]

View File

@ -0,0 +1,112 @@
/**
* @author Matt C [matt@artemisbot.uk]
* @copyright Crown Copyright 2018
* @license Apache-2.0
*/
import Operation from "../Operation";
import OperationError from "../errors/OperationError";
import Utils from "../Utils";
import Magic from "../lib/Magic";
import jimp from "jimp";
/**
* Split Colour Channels operation
*/
class SplitColourChannels extends Operation {
/**
* SplitColourChannels constructor
*/
constructor() {
super();
this.name = "Split Colour Channels";
this.module = "Image";
this.description = "Splits given image into its red, green and blue colour channels.";
this.infoURL = "https://en.wikipedia.org/wiki/Channel_(digital_image)";
this.inputType = "byteArray";
this.outputType = "List<File>";
this.presentType = "html";
this.args = [
/* Example arguments. See the project wiki for full details.
{
name: "First arg",
type: "string",
value: "Don't Panic"
},
{
name: "Second arg",
type: "number",
value: 42
}
*/
];
}
/**
* @param {byteArray} input
* @param {Object[]} args
* @returns {List<File>}
*/
async run(input, args) {
const type = Magic.magicFileType(input);
// Make sure that the input is an image
if (type && type.mime.indexOf("image") === 0) {
const parsedImage = await jimp.read(Buffer.from(input));
const red = new Promise(async (resolve, reject) => {
try {
const split = parsedImage.clone()
.color([
{apply: "blue", params: [-255]},
{apply: "green", params: [-255]}
]).getBufferAsync(jimp.MIME_PNG);
resolve(new File([new Uint8Array((await split).values())], "red.png", {type: "image/png"}));
} catch (err) {
reject(new OperationError(`Could not split red channel: ${err}`));
}
});
const green = new Promise(async (resolve, reject) => {
try {
const split = parsedImage.clone()
.color([
{apply: "red", params: [-255]},
{apply: "blue", params: [-255]},
]).getBufferAsync(jimp.MIME_PNG);
resolve(new File([new Uint8Array((await split).values())], "green.png", {type: "image/png"}));
} catch (err) {
reject(new OperationError(`Could not split green channel: ${err}`));
}
});
const blue = new Promise(async (resolve, reject) => {
try {
const split = parsedImage
.color([
{apply: "red", params: [-255]},
{apply: "green", params: [-255]},
]).getBufferAsync(jimp.MIME_PNG);
resolve(new File([new Uint8Array((await split).values())], "blue.png", {type: "image/png"}));
} catch (err) {
reject(new OperationError(`Could not split blue channel: ${err}`));
}
});
return await Promise.all([red, green, blue]);
} else {
throw new OperationError("Invalid file type.");
}
}
/**
* Displays the files in HTML for web apps.
*
* @param {File[]} files
* @returns {html}
*/
async present(files) {
return await Utils.displayFilesAsHTML(files);
}
}
export default SplitColourChannels;

View File

@ -74,6 +74,7 @@ import "./tests/operations/SeqUtils";
import "./tests/operations/SetDifference"; import "./tests/operations/SetDifference";
import "./tests/operations/SetIntersection"; import "./tests/operations/SetIntersection";
import "./tests/operations/SetUnion"; import "./tests/operations/SetUnion";
//import "./tests/operations/SplitColourChannels";
import "./tests/operations/StrUtils"; import "./tests/operations/StrUtils";
import "./tests/operations/SymmetricDifference"; import "./tests/operations/SymmetricDifference";
import "./tests/operations/TextEncodingBruteForce"; import "./tests/operations/TextEncodingBruteForce";

File diff suppressed because one or more lines are too long