Add bitwse mode to Generate Image operation

This commit is contained in:
Thomas Pointhuber 2019-10-12 17:35:46 +02:00
parent d025c8bd9a
commit a2780ca056

View file

@ -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) => {});
if (isWorkerEnvironment())
self.sendStatusMessage("Generate image from data...");
let i = 0; if (mode === "Bits") {
while (i < input.length) { let index = 0;
const index = i/bytesPerPixel; for (let j = 0; j < input.length; j++) {
const x = index % width; const curByte = Utils.bin(input[j]);
const y = Math.floor(index / width); for (let k = 0; k < 8; k++, index++) {
const x = index % width;
const y = Math.floor(index / width);
let red = 0x00; const value = curByte[k] === "0" ? 0xFF : 0x00;
let green = 0x00; const pixel = jimp.rgbaToInt(value, value, value, 0xFF);
let blue = 0x00; image.setPixelColor(pixel, x, y);
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})`);
} }
} else {
let i = 0;
while (i < input.length) {
const index = i / bytesPerPixel;
const x = index % width;
const y = Math.floor(index / width);
try { let red = 0x00;
const pixel = jimp.rgbaToInt(red, green, blue, alpha); let green = 0x00;
image.setPixelColor(pixel, x, y); let blue = 0x00;
} catch (err) { let alpha = 0xFF;
throw new OperationError(`Error while generating image from pixel values. (${err})`);
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);
} }