Tidied up Steganography operations. FileType and toBase64 functions now accept ArrayBuffers.

This commit is contained in:
n1474335 2019-09-04 13:54:59 +01:00
parent 5bc5c0df90
commit eb769c7fb4
28 changed files with 81 additions and 75 deletions

View file

@ -121,7 +121,7 @@ class AddTextToImage extends Operation {
let xPos = args[3],
yPos = args[4];
if (!isImage(new Uint8Array(input))) {
if (!isImage(input)) {
throw new OperationError("Invalid file type.");
}

View file

@ -53,7 +53,7 @@ class BlurImage extends Operation {
async run(input, args) {
const [blurAmount, blurType] = args;
if (!isImage(new Uint8Array(input))) {
if (!isImage(input)) {
throw new OperationError("Invalid file type.");
}

View file

@ -107,7 +107,7 @@ class ContainImage extends Operation {
"Bottom": jimp.VERTICAL_ALIGN_BOTTOM
};
if (!isImage(new Uint8Array(input))) {
if (!isImage(input)) {
throw new OperationError("Invalid file type.");
}

View file

@ -93,7 +93,7 @@ class ConvertImageFormat extends Operation {
const mime = formatMap[format];
if (!isImage(new Uint8Array(input))) {
if (!isImage(input)) {
throw new OperationError("Invalid file format.");
}
let image;

View file

@ -102,7 +102,7 @@ class CoverImage extends Operation {
"Bottom": jimp.VERTICAL_ALIGN_BOTTOM
};
if (!isImage(new Uint8Array(input))) {
if (!isImage(input)) {
throw new OperationError("Invalid file type.");
}

View file

@ -93,7 +93,7 @@ class CropImage extends Operation {
*/
async run(input, args) {
const [xPos, yPos, width, height, autocrop, autoTolerance, autoFrames, autoSymmetric, autoBorder] = args;
if (!isImage(new Uint8Array(input))) {
if (!isImage(input)) {
throw new OperationError("Invalid file type.");
}

View file

@ -38,7 +38,7 @@ class DitherImage extends Operation {
* @returns {byteArray}
*/
async run(input, args) {
if (!isImage(new Uint8Array(input))) {
if (!isImage(input)) {
throw new OperationError("Invalid file type.");
}

View file

@ -6,8 +6,9 @@
import Operation from "../Operation.mjs";
import OperationError from "../errors/OperationError.mjs";
import Utils from "../Utils";
import { isImage } from "../lib/FileType";
import Utils from "../Utils.mjs";
import { fromBinary } from "../lib/Binary.mjs";
import { isImage } from "../lib/FileType.mjs";
import jimp from "jimp";
/**
@ -24,8 +25,8 @@ class ExtractLSB extends Operation {
this.name = "Extract LSB";
this.module = "Image";
this.description = "Extracts the Least Significant Bit data from each pixel in an image. This is a common way to hide data in Steganography.";
this.infoURL = "https://en.wikipedia.org/wiki/Bit_numbering#Least_significant_bit_in_digital_steganography";
this.inputType = "byteArray";
this.infoURL = "https://wikipedia.org/wiki/Bit_numbering#Least_significant_bit_in_digital_steganography";
this.inputType = "ArrayBuffer";
this.outputType = "byteArray";
this.args = [
{
@ -62,9 +63,9 @@ class ExtractLSB extends Operation {
}
/**
* @param {File} input
* @param {ArrayBuffer} input
* @param {Object[]} args
* @returns {File}
* @returns {byteArray}
*/
async run(input, args) {
if (!isImage(input)) throw new OperationError("Please enter a valid image file.");
@ -72,7 +73,7 @@ class ExtractLSB extends Operation {
const bit = 7 - args.pop(),
pixelOrder = args.pop(),
colours = args.filter(option => option !== "").map(option => COLOUR_OPTIONS.indexOf(option)),
parsedImage = await jimp.read(Buffer.from(input)),
parsedImage = await jimp.read(input),
width = parsedImage.bitmap.width,
height = parsedImage.bitmap.height,
rgba = parsedImage.bitmap.data;
@ -103,8 +104,7 @@ class ExtractLSB extends Operation {
}
}
return Utils.convertToByteArray(combinedBinary, "binary");
return fromBinary(combinedBinary);
}
}

View file

@ -6,7 +6,7 @@
import Operation from "../Operation.mjs";
import OperationError from "../errors/OperationError.mjs";
import { isImage } from "../lib/FileType";
import { isImage } from "../lib/FileType.mjs";
import jimp from "jimp";
import {RGBA_DELIM_OPTIONS} from "../lib/Delim.mjs";
@ -25,8 +25,8 @@ class ExtractRGBA extends Operation {
this.name = "Extract RGBA";
this.module = "Image";
this.description = "Extracts each pixel's RGBA value in an image. These are sometimes used in Steganography to hide text or data.";
this.infoURL = "https://en.wikipedia.org/wiki/RGBA_color_space";
this.inputType = "byteArray";
this.infoURL = "https://wikipedia.org/wiki/RGBA_color_space";
this.inputType = "ArrayBuffer";
this.outputType = "string";
this.args = [
{
@ -43,7 +43,7 @@ class ExtractRGBA extends Operation {
}
/**
* @param {byteArray} input
* @param {ArrayBuffer} input
* @param {Object[]} args
* @returns {string}
*/
@ -52,7 +52,7 @@ class ExtractRGBA extends Operation {
const delimiter = args[0],
includeAlpha = args[1],
parsedImage = await jimp.read(Buffer.from(input));
parsedImage = await jimp.read(input);
let bitmap = parsedImage.bitmap.data;
bitmap = includeAlpha ? bitmap : bitmap.filter((val, idx) => idx % 4 !== 3);

View file

@ -45,7 +45,7 @@ class FlipImage extends Operation {
*/
async run(input, args) {
const [flipAxis] = args;
if (!isImage(new Uint8Array(input))) {
if (!isImage(input)) {
throw new OperationError("Invalid input file type.");
}

View file

@ -54,7 +54,7 @@ class ImageBrightnessContrast extends Operation {
*/
async run(input, args) {
const [brightness, contrast] = args;
if (!isImage(new Uint8Array(input))) {
if (!isImage(input)) {
throw new OperationError("Invalid file type.");
}

View file

@ -48,7 +48,7 @@ class ImageFilter extends Operation {
*/
async run(input, args) {
const [filterType] = args;
if (!isImage(new Uint8Array(input))) {
if (!isImage(input)) {
throw new OperationError("Invalid file type.");
}

View file

@ -62,7 +62,7 @@ class ImageHueSaturationLightness extends Operation {
async run(input, args) {
const [hue, saturation, lightness] = args;
if (!isImage(new Uint8Array(input))) {
if (!isImage(input)) {
throw new OperationError("Invalid file type.");
}

View file

@ -47,7 +47,7 @@ class ImageOpacity extends Operation {
*/
async run(input, args) {
const [opacity] = args;
if (!isImage(new Uint8Array(input))) {
if (!isImage(input)) {
throw new OperationError("Invalid file type.");
}

View file

@ -38,7 +38,7 @@ class InvertImage extends Operation {
* @returns {byteArray}
*/
async run(input, args) {
if (!isImage(new Uint8Array(input))) {
if (!isImage(input)) {
throw new OperationError("Invalid input file format.");
}

View file

@ -37,7 +37,7 @@ class NormaliseImage extends Operation {
* @returns {byteArray}
*/
async run(input, args) {
if (!isImage(new Uint8Array(input))) {
if (!isImage(input)) {
throw new OperationError("Invalid file type.");
}

View file

@ -51,7 +51,7 @@ class ParseQRCode extends Operation {
async run(input, args) {
const [normalise] = args;
if (!isImage(new Uint8Array(input))) {
if (!isImage(input)) {
throw new OperationError("Invalid file type.");
}
return await parseQrCode(input, normalise);

View file

@ -6,12 +6,12 @@
import Operation from "../Operation.mjs";
import OperationError from "../errors/OperationError.mjs";
import Utils from "../Utils";
import PseudoRandomNumberGenerator from "./PseudoRandomNumberGenerator.mjs";
import { isImage } from "../lib/FileType";
import Utils from "../Utils.mjs";
import { isImage } from "../lib/FileType.mjs";
import { runHash } from "../lib/Hash.mjs";
import { toBase64 } from "../lib/Base64";
import { toBase64 } from "../lib/Base64.mjs";
import jimp from "jimp";
import { toHex } from "../lib/Hex.mjs";
/**
* Randomize Colour Palette operation
@ -26,10 +26,10 @@ class RandomizeColourPalette extends Operation {
this.name = "Randomize Colour Palette";
this.module = "Image";
this.description = "Randomize's each colour in an image's colour palette. This can often reveal text or symbols that were previously a very similar colour to their surroundings.";
this.infoURL = "https://en.wikipedia.org/wiki/Indexed_color";
this.inputType = "byteArray";
this.outputType = "byteArray";
this.description = "Randomizes each colour in an image's colour palette. This can often reveal text or symbols that were previously a very similar colour to their surroundings, a technique sometimes used in Steganography.";
this.infoURL = "https://wikipedia.org/wiki/Indexed_color";
this.inputType = "ArrayBuffer";
this.outputType = "ArrayBuffer";
this.presentType = "html";
this.args = [
{
@ -41,15 +41,15 @@ class RandomizeColourPalette extends Operation {
}
/**
* @param {byteArray} input
* @param {ArrayBuffer} input
* @param {Object[]} args
* @returns {byteArray}
* @returns {ArrayBuffer}
*/
async run(input, args) {
if (!isImage(input)) throw new OperationError("Please enter a valid image file.");
const seed = args[0] || (new PseudoRandomNumberGenerator()).run("", [5, "Hex"]),
parsedImage = await jimp.read(Buffer.from(input)),
const seed = args[0] || (Math.random().toString().substr(2)),
parsedImage = await jimp.read(input),
width = parsedImage.bitmap.width,
height = parsedImage.bitmap.height;
@ -64,16 +64,16 @@ class RandomizeColourPalette extends Operation {
const imageBuffer = await parsedImage.getBufferAsync(jimp.AUTO);
return Array.from(imageBuffer);
return new Uint8Array(imageBuffer).buffer;
}
/**
* Displays the extracted data as an image for web apps.
* @param {byteArray} data
* @param {ArrayBuffer} data
* @returns {html}
*/
present(data) {
if (!data.length) return "";
if (!data.byteLength) return "";
const type = isImage(data);
return `<img src="data:${type};base64,${toBase64(data)}">`;

View file

@ -87,7 +87,7 @@ class ResizeImage extends Operation {
"Bezier": jimp.RESIZE_BEZIER
};
if (!isImage(new Uint8Array(input))) {
if (!isImage(input)) {
throw new OperationError("Invalid file type.");
}

View file

@ -46,7 +46,7 @@ class RotateImage extends Operation {
async run(input, args) {
const [degrees] = args;
if (!isImage(new Uint8Array(input))) {
if (!isImage(input)) {
throw new OperationError("Invalid file type.");
}

View file

@ -62,7 +62,7 @@ class SharpenImage extends Operation {
async run(input, args) {
const [radius, amount, threshold] = args;
if (!isImage(new Uint8Array(input))) {
if (!isImage(input)) {
throw new OperationError("Invalid file type.");
}

View file

@ -40,7 +40,7 @@ class ToBase64 extends Operation {
*/
run(input, args) {
const alphabet = args[0];
return toBase64(new Uint8Array(input), alphabet);
return toBase64(input, alphabet);
}
/**

View file

@ -4,11 +4,11 @@
* @license Apache-2.0
*/
import Operation from "../Operation";
import OperationError from "../errors/OperationError";
import Utils from "../Utils";
import { isImage } from "../lib/FileType";
import { toBase64 } from "../lib/Base64";
import Operation from "../Operation.mjs";
import OperationError from "../errors/OperationError.mjs";
import Utils from "../Utils.mjs";
import { isImage } from "../lib/FileType.mjs";
import { toBase64 } from "../lib/Base64.mjs";
import jimp from "jimp";
/**
@ -24,10 +24,10 @@ class ViewBitPlane extends Operation {
this.name = "View Bit Plane";
this.module = "Image";
this.description = "Extracts and displays a bit plane of any given image. These show only a single bit from each pixel, and so are often used to hide messages in Steganography.";
this.description = "Extracts and displays a bit plane of any given image. These show only a single bit from each pixel, and can be used to hide messages in Steganography.";
this.infoURL = "https://wikipedia.org/wiki/Bit_plane";
this.inputType = "byteArray";
this.outputType = "byteArray";
this.inputType = "ArrayBuffer";
this.outputType = "ArrayBuffer";
this.presentType = "html";
this.args = [
{
@ -44,15 +44,15 @@ class ViewBitPlane extends Operation {
}
/**
* @param {File} input
* @param {ArrayBuffer} input
* @param {Object[]} args
* @returns {File}
* @returns {ArrayBuffer}
*/
async run(input, args) {
if (!isImage(input)) throw new OperationError("Please enter a valid image file.");
const [colour, bit] = args,
parsedImage = await jimp.read(Buffer.from(input)),
parsedImage = await jimp.read(input),
width = parsedImage.bitmap.width,
height = parsedImage.bitmap.height,
colourIndex = COLOUR_OPTIONS.indexOf(colour),
@ -62,7 +62,6 @@ class ViewBitPlane extends Operation {
throw new OperationError("Error: Bit argument must be between 0 and 7");
}
let pixel, bin, newPixelValue;
parsedImage.scan(0, 0, width, height, function(x, y, idx) {
@ -81,12 +80,12 @@ class ViewBitPlane extends Operation {
const imageBuffer = await parsedImage.getBufferAsync(jimp.AUTO);
return Array.from(imageBuffer);
return new Uint8Array(imageBuffer).buffer;
}
/**
* Displays the extracted data as an image for web apps.
* @param {byteArray} data
* @param {ArrayBuffer} data
* @returns {html}
*/
present(data) {