|
@@ -6,9 +6,11 @@
|
|
|
|
|
|
import Operation from "../Operation.mjs";
|
|
import Operation from "../Operation.mjs";
|
|
import OperationError from "../errors/OperationError.mjs";
|
|
import OperationError from "../errors/OperationError.mjs";
|
|
|
|
+import Utils from "../Utils.mjs";
|
|
import {isImage} from "../lib/FileType";
|
|
import {isImage} from "../lib/FileType";
|
|
import {toBase64} from "../lib/Base64";
|
|
import {toBase64} from "../lib/Base64";
|
|
import jimp from "jimp";
|
|
import jimp from "jimp";
|
|
|
|
+import {isWorkerEnvironment} from "../Utils";
|
|
|
|
|
|
/**
|
|
/**
|
|
* Generate Image operation
|
|
* Generate Image operation
|
|
@@ -32,7 +34,7 @@ class GenerateImage extends Operation {
|
|
{
|
|
{
|
|
"name": "Mode",
|
|
"name": "Mode",
|
|
"type": "option",
|
|
"type": "option",
|
|
- "value": ["Greyscale", "RG", "RGB", "RGBA"]
|
|
|
|
|
|
+ "value": ["Greyscale", "RG", "RGB", "RGBA", "Bits"]
|
|
},
|
|
},
|
|
{
|
|
{
|
|
"name": "Pixel Scale Factor",
|
|
"name": "Pixel Scale Factor",
|
|
@@ -70,65 +72,86 @@ class GenerateImage extends Operation {
|
|
"RG": 2,
|
|
"RG": 2,
|
|
"RGB": 3,
|
|
"RGB": 3,
|
|
"RGBA": 4,
|
|
"RGBA": 4,
|
|
|
|
+ "Bits": 1/8,
|
|
};
|
|
};
|
|
|
|
|
|
const bytesPerPixel = bytePerPixelMap[mode];
|
|
const bytesPerPixel = bytePerPixelMap[mode];
|
|
|
|
|
|
- if (input.length % bytesPerPixel !== 0) {
|
|
|
|
|
|
+ if (bytesPerPixel > 0 && input.length % bytesPerPixel !== 0) {
|
|
throw new OperationError(`Number of bytes is not a divisor of ${bytesPerPixel}`);
|
|
throw new OperationError(`Number of bytes is not a divisor of ${bytesPerPixel}`);
|
|
}
|
|
}
|
|
|
|
|
|
const height = Math.ceil(input.length / bytesPerPixel / width);
|
|
const height = Math.ceil(input.length / bytesPerPixel / width);
|
|
const image = await new jimp(width, height, (err, image) => {});
|
|
const image = await new jimp(width, height, (err, image) => {});
|
|
|
|
|
|
-
|
|
|
|
- let i = 0;
|
|
|
|
- while (i < input.length) {
|
|
|
|
- const index = i/bytesPerPixel;
|
|
|
|
- const x = index % width;
|
|
|
|
- const y = Math.floor(index / width);
|
|
|
|
-
|
|
|
|
- let red = 0x00;
|
|
|
|
- let green = 0x00;
|
|
|
|
- let blue = 0x00;
|
|
|
|
- let alpha = 0xFF;
|
|
|
|
-
|
|
|
|
- switch (mode) {
|
|
|
|
- case "Greyscale":
|
|
|
|
- red = green = blue = input[i++];
|
|
|
|
- break;
|
|
|
|
-
|
|
|
|
- case "RG":
|
|
|
|
- red = input[i++];
|
|
|
|
- green = input[i++];
|
|
|
|
- break;
|
|
|
|
-
|
|
|
|
- case "RGB":
|
|
|
|
- red = input[i++];
|
|
|
|
- green = input[i++];
|
|
|
|
- blue = input[i++];
|
|
|
|
- break;
|
|
|
|
-
|
|
|
|
- case "RGBA":
|
|
|
|
- red = input[i++];
|
|
|
|
- green = input[i++];
|
|
|
|
- blue = input[i++];
|
|
|
|
- alpha = input[i++];
|
|
|
|
- break;
|
|
|
|
-
|
|
|
|
- default:
|
|
|
|
- throw new OperationError(`Unsupported Mode: (${mode})`);
|
|
|
|
|
|
+ if (isWorkerEnvironment())
|
|
|
|
+ self.sendStatusMessage("Generate image from data...");
|
|
|
|
+
|
|
|
|
+ if (mode === "Bits") {
|
|
|
|
+ let index = 0;
|
|
|
|
+ for (let j = 0; j < input.length; j++) {
|
|
|
|
+ const curByte = Utils.bin(input[j]);
|
|
|
|
+ for (let k = 0; k < 8; k++, index++) {
|
|
|
|
+ const x = index % width;
|
|
|
|
+ const y = Math.floor(index / width);
|
|
|
|
+
|
|
|
|
+ const value = curByte[k] === "0" ? 0xFF : 0x00;
|
|
|
|
+ const pixel = jimp.rgbaToInt(value, value, value, 0xFF);
|
|
|
|
+ image.setPixelColor(pixel, x, y);
|
|
|
|
+ }
|
|
}
|
|
}
|
|
-
|
|
|
|
- try {
|
|
|
|
- const pixel = jimp.rgbaToInt(red, green, blue, alpha);
|
|
|
|
- image.setPixelColor(pixel, x, y);
|
|
|
|
- } catch (err) {
|
|
|
|
- throw new OperationError(`Error while generating image from pixel values. (${err})`);
|
|
|
|
|
|
+ } else {
|
|
|
|
+ let i = 0;
|
|
|
|
+ while (i < input.length) {
|
|
|
|
+ const index = i / bytesPerPixel;
|
|
|
|
+ const x = index % width;
|
|
|
|
+ const y = Math.floor(index / width);
|
|
|
|
+
|
|
|
|
+ let red = 0x00;
|
|
|
|
+ let green = 0x00;
|
|
|
|
+ let blue = 0x00;
|
|
|
|
+ let alpha = 0xFF;
|
|
|
|
+
|
|
|
|
+ switch (mode) {
|
|
|
|
+ case "Greyscale":
|
|
|
|
+ red = green = blue = input[i++];
|
|
|
|
+ break;
|
|
|
|
+
|
|
|
|
+ case "RG":
|
|
|
|
+ red = input[i++];
|
|
|
|
+ green = input[i++];
|
|
|
|
+ break;
|
|
|
|
+
|
|
|
|
+ case "RGB":
|
|
|
|
+ red = input[i++];
|
|
|
|
+ green = input[i++];
|
|
|
|
+ blue = input[i++];
|
|
|
|
+ break;
|
|
|
|
+
|
|
|
|
+ case "RGBA":
|
|
|
|
+ red = input[i++];
|
|
|
|
+ green = input[i++];
|
|
|
|
+ blue = input[i++];
|
|
|
|
+ alpha = input[i++];
|
|
|
|
+ break;
|
|
|
|
+
|
|
|
|
+ default:
|
|
|
|
+ throw new OperationError(`Unsupported Mode: (${mode})`);
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ try {
|
|
|
|
+ const pixel = jimp.rgbaToInt(red, green, blue, alpha);
|
|
|
|
+ image.setPixelColor(pixel, x, y);
|
|
|
|
+ } catch (err) {
|
|
|
|
+ throw new OperationError(`Error while generating image from pixel values. (${err})`);
|
|
|
|
+ }
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
if (scale !== 1) {
|
|
if (scale !== 1) {
|
|
|
|
+ if (isWorkerEnvironment())
|
|
|
|
+ self.sendStatusMessage("Scale image...");
|
|
|
|
+
|
|
image.scaleToFit(width*scale, height*scale, jimp.RESIZE_NEAREST_NEIGHBOR);
|
|
image.scaleToFit(width*scale, height*scale, jimp.RESIZE_NEAREST_NEIGHBOR);
|
|
}
|
|
}
|
|
|
|
|