UNPKG

image-js

Version:

Image processing and manipulation in JavaScript

119 lines (115 loc) 4.99 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.default = fromMask; var _RoiMap = _interopRequireDefault(require("../RoiMap")); function _interopRequireDefault(e) { return e && e.__esModule ? e : { default: e }; } /** * @memberof RoiManager * @instance * @param {Image} mask * @param {object} [options] * @return {RoiMap} */ function fromMask(mask, options = {}) { const { allowCorners = false } = options; const MAX_ARRAY = 0x00ffff; // 65535 should be enough for most of the cases // based on a binary image we will create plenty of small images let data = new Int16Array(mask.size); // maxValue: 32767, minValue: -32768 // split will always return an array of images let positiveID = 0; let negativeID = 0; let xToProcess = new Uint16Array(MAX_ARRAY + 1); // assign dynamically ???? let yToProcess = new Uint16Array(MAX_ARRAY + 1); // mask +1 is of course mandatory !!! for (let x = 0; x < mask.width; x++) { for (let y = 0; y < mask.height; y++) { if (data[y * mask.width + x] === 0) { // need to process the whole surface analyseSurface(x, y); } } } function analyseSurface(x, y) { let from = 0; let to = 0; let targetState = mask.getBitXY(x, y); let id = targetState ? ++positiveID : --negativeID; if (positiveID > 32767 || negativeID < -32768) { throw new Error('Too many regions of interest'); } xToProcess[0] = x; yToProcess[0] = y; while (from <= to) { let currentX = xToProcess[from & MAX_ARRAY]; let currentY = yToProcess[from & MAX_ARRAY]; data[currentY * mask.width + currentX] = id; // need to check all around mask pixel if (currentX > 0 && data[currentY * mask.width + currentX - 1] === 0 && mask.getBitXY(currentX - 1, currentY) === targetState) { // LEFT to++; xToProcess[to & MAX_ARRAY] = currentX - 1; yToProcess[to & MAX_ARRAY] = currentY; data[currentY * mask.width + currentX - 1] = -32768; } if (currentY > 0 && data[(currentY - 1) * mask.width + currentX] === 0 && mask.getBitXY(currentX, currentY - 1) === targetState) { // TOP to++; xToProcess[to & MAX_ARRAY] = currentX; yToProcess[to & MAX_ARRAY] = currentY - 1; data[(currentY - 1) * mask.width + currentX] = -32768; } if (currentX < mask.width - 1 && data[currentY * mask.width + currentX + 1] === 0 && mask.getBitXY(currentX + 1, currentY) === targetState) { // RIGHT to++; xToProcess[to & MAX_ARRAY] = currentX + 1; yToProcess[to & MAX_ARRAY] = currentY; data[currentY * mask.width + currentX + 1] = -32768; } if (currentY < mask.height - 1 && data[(currentY + 1) * mask.width + currentX] === 0 && mask.getBitXY(currentX, currentY + 1) === targetState) { // BOTTOM to++; xToProcess[to & MAX_ARRAY] = currentX; yToProcess[to & MAX_ARRAY] = currentY + 1; data[(currentY + 1) * mask.width + currentX] = -32768; } if (allowCorners) { if (currentX > 0 && currentY > 0 && data[(currentY - 1) * mask.width + currentX - 1] === 0 && mask.getBitXY(currentX - 1, currentY - 1) === targetState) { // TOP LEFT to++; xToProcess[to & MAX_ARRAY] = currentX - 1; yToProcess[to & MAX_ARRAY] = currentY - 1; data[(currentY - 1) * mask.width + currentX - 1] = -32768; } if (currentX < mask.width - 1 && currentY > 0 && data[(currentY - 1) * mask.width + currentX + 1] === 0 && mask.getBitXY(currentX + 1, currentY - 1) === targetState) { // TOP RIGHT to++; xToProcess[to & MAX_ARRAY] = currentX + 1; yToProcess[to & MAX_ARRAY] = currentY - 1; data[(currentY - 1) * mask.width + currentX + 1] = -32768; } if (currentX > 0 && currentY < mask.height - 1 && data[(currentY + 1) * mask.width + currentX - 1] === 0 && mask.getBitXY(currentX - 1, currentY + 1) === targetState) { // BOTTOM LEFT to++; xToProcess[to & MAX_ARRAY] = currentX - 1; yToProcess[to & MAX_ARRAY] = currentY + 1; data[(currentY + 1) * mask.width + currentX - 1] = -32768; } if (currentX < mask.width - 1 && currentY < mask.height - 1 && data[(currentY + 1) * mask.width + currentX + 1] === 0 && mask.getBitXY(currentX + 1, currentY + 1) === targetState) { // BOTTOM RIGHT to++; xToProcess[to & MAX_ARRAY] = currentX + 1; yToProcess[to & MAX_ARRAY] = currentY + 1; data[(currentY + 1) * mask.width + currentX + 1] = -32768; } } from++; if (to - from > MAX_ARRAY) { throw new Error('analyseMask can not finish, the array to manage internal data is not big enough.' + 'You could improve mask by changing MAX_ARRAY'); } } } return new _RoiMap.default(mask, data); }