New Case Study:See how Anthropic automated 95% of dependency reviews with Socket.Learn More
Socket
Sign inDemoInstall
Socket

@midscene/shared

Package Overview
Dependencies
Maintainers
0
Versions
198
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

@midscene/shared - npm Package Compare versions

Comparing version 0.7.2 to 0.7.3-beta-20241029030944.0

dist/browser/constants.d.ts

31

dist/es/fs.js
// src/fs/index.ts
import assert from "assert";
import { existsSync, readFileSync } from "fs";
import { dirname, join } from "path";
var pkg;
function getMidscenePkgInfo(dir) {
if (pkg) {
return pkg;
var pkgCacheMap = {};
var ifInBrowser = typeof window !== "undefined";
function getRunningPkgInfo(dir) {
if (ifInBrowser) {
return null;
}
const pkgDir = findNearestPackageJson(dir || process.cwd());
assert(pkgDir, "package.json not found");
const pkgJsonFile = join(pkgDir, "package.json");
if (pkgJsonFile) {
const dirToCheck = dir || process.cwd();
if (pkgCacheMap[dirToCheck]) {
return pkgCacheMap[dirToCheck];
}
const pkgDir = findNearestPackageJson(dirToCheck);
const pkgJsonFile = pkgDir ? join(pkgDir, "package.json") : null;
if (pkgDir && pkgJsonFile) {
const { name, version } = JSON.parse(readFileSync(pkgJsonFile, "utf-8"));
pkg = { name, version, dir: pkgDir };
return pkg;
pkgCacheMap[dirToCheck] = { name, version, dir: pkgDir };
return pkgCacheMap[dirToCheck];
}
return {
name: "midscene-unknown-page-name",
name: "midscene-unknown-package-name",
version: "0.0.0",
dir: pkgDir
dir: dirToCheck
};

@@ -37,3 +40,3 @@ }

findNearestPackageJson,
getMidscenePkgInfo
getRunningPkgInfo
};

@@ -0,26 +1,73 @@

var __async = (__this, __arguments, generator) => {
return new Promise((resolve, reject) => {
var fulfilled = (value) => {
try {
step(generator.next(value));
} catch (e) {
reject(e);
}
};
var rejected = (value) => {
try {
step(generator.throw(value));
} catch (e) {
reject(e);
}
};
var step = (x) => x.done ? resolve(x.value) : Promise.resolve(x.value).then(fulfilled, rejected);
step((generator = generator.apply(__this, __arguments)).next());
});
};
// src/img/info.ts
import assert from "assert";
import { Buffer } from "buffer";
import { Buffer as Buffer2 } from "buffer";
import { readFileSync } from "fs";
import Jimp from "jimp";
async function imageInfo(image) {
let jimpImage;
if (typeof image === "string") {
jimpImage = await Jimp.read(image);
} else if (Buffer.isBuffer(image)) {
jimpImage = await Jimp.read(image);
} else {
throw new Error("Invalid image input: must be a string path or a Buffer");
}
const { width, height } = jimpImage.bitmap;
assert(
width && height,
`Invalid image: ${typeof image === "string" ? image : "Buffer"}`
);
return { width, height };
// src/img/get-jimp.ts
var ifInBrowser = typeof window !== "undefined";
function getJimp() {
return __async(this, null, function* () {
if (ifInBrowser) {
yield import("jimp/browser/lib/jimp.js");
return window.Jimp;
}
return (yield import("jimp")).default;
});
}
async function imageInfoOfBase64(imageBase64) {
const base64Data = imageBase64.replace(/^data:image\/\w+;base64,/, "");
return imageInfo(Buffer.from(base64Data, "base64"));
// src/img/info.ts
function imageInfo(image) {
return __async(this, null, function* () {
const Jimp = yield getJimp();
let jimpImage;
if (typeof image === "string") {
jimpImage = yield Jimp.read(image);
} else if (Buffer2.isBuffer(image)) {
jimpImage = yield Jimp.read(image);
} else if (image instanceof Jimp) {
jimpImage = image;
} else {
throw new Error("Invalid image input: must be a string path or a Buffer");
}
const { width, height } = jimpImage.bitmap;
assert(
width && height,
`Invalid image: ${typeof image === "string" ? image : "Buffer"}`
);
return { width, height, jimpImage };
});
}
function imageInfoOfBase64(imageBase64) {
return __async(this, null, function* () {
const buffer = yield bufferFromBase64(imageBase64);
return imageInfo(buffer);
});
}
function bufferFromBase64(imageBase64) {
return __async(this, null, function* () {
const base64Data = imageBase64.replace(/^data:image\/\w+;base64,/, "");
return Buffer2.from(base64Data, "base64");
});
}
function base64Encoded(image, withHeader = true) {

@@ -44,29 +91,50 @@ const imageBuffer = readFileSync(image);

// src/img/transform.ts
import { Buffer as Buffer2 } from "buffer";
import Jimp2 from "jimp";
async function saveBase64Image(options) {
const { base64Data, outputPath } = options;
const base64Image = base64Data.split(";base64,").pop() || base64Data;
const imageBuffer = Buffer2.from(base64Image, "base64");
const image = await Jimp2.read(imageBuffer);
await image.writeAsync(outputPath);
import { Buffer as Buffer3 } from "buffer";
function saveBase64Image(options) {
return __async(this, null, function* () {
const { base64Data, outputPath } = options;
const base64Image = base64Data.split(";base64,").pop() || base64Data;
const imageBuffer = Buffer3.from(base64Image, "base64");
const Jimp = yield getJimp();
const image = yield Jimp.read(imageBuffer);
yield image.writeAsync(outputPath);
});
}
async function transformImgPathToBase64(inputPath) {
const image = await Jimp2.read(inputPath);
const buffer = await image.getBufferAsync(Jimp2.MIME_PNG);
return buffer.toString("base64");
function transformImgPathToBase64(inputPath) {
return __async(this, null, function* () {
const Jimp = yield getJimp();
const image = yield Jimp.read(inputPath);
const buffer = yield image.getBufferAsync(Jimp.MIME_PNG);
return buffer.toString("base64");
});
}
async function resizeImg(inputData, newSize) {
const isBase64 = typeof inputData === "string";
const imageBuffer = isBase64 ? Buffer2.from(inputData.split(";base64,").pop() || inputData, "base64") : inputData;
const image = await Jimp2.read(imageBuffer);
const { width, height } = image.bitmap;
if (!width || !height) {
throw Error("Undefined width or height from the input image.");
}
const finalNewSize = newSize || calculateNewDimensions(width, height);
image.resize(finalNewSize.width, finalNewSize.height);
const resizedBuffer = await image.getBufferAsync(Jimp2.MIME_PNG);
return isBase64 ? resizedBuffer.toString("base64") : resizedBuffer;
function resizeImg(inputData, newSize) {
return __async(this, null, function* () {
if (typeof inputData === "string")
throw Error("inputData is base64, use resizeImgBase64 instead");
const Jimp = yield getJimp();
const image = yield Jimp.read(inputData);
const { width, height } = image.bitmap;
if (!width || !height) {
throw Error("Undefined width or height from the input image.");
}
const finalNewSize = newSize || calculateNewDimensions(width, height);
image.resize(finalNewSize.width, finalNewSize.height);
const resizedBuffer = yield image.getBufferAsync(Jimp.MIME_PNG);
return resizedBuffer;
});
}
function resizeImgBase64(inputData, newSize) {
return __async(this, null, function* () {
const splitFlag = ";base64,";
const dataSplitted = inputData.split(splitFlag);
if (dataSplitted.length !== 2) {
throw Error("Invalid base64 data");
}
const imageBuffer = Buffer3.from(dataSplitted[1], "base64");
const buffer = yield resizeImg(imageBuffer, newSize);
const content = buffer.toString("base64");
return `${dataSplitted[0]}${splitFlag}${content}`;
});
}
function calculateNewDimensions(originalWidth, originalHeight) {

@@ -91,23 +159,26 @@ const maxWidth = 2048;

}
async function trimImage(image) {
const jimpImage = await Jimp2.read(
Buffer2.isBuffer(image) ? image : Buffer2.from(image)
);
const { width, height } = jimpImage.bitmap;
if (width <= 3 || height <= 3) {
return null;
}
const trimmedImage = jimpImage.autocrop();
const { width: trimmedWidth, height: trimmedHeight } = trimmedImage.bitmap;
const trimOffsetLeft = (width - trimmedWidth) / 2;
const trimOffsetTop = (height - trimmedHeight) / 2;
if (trimOffsetLeft === 0 && trimOffsetTop === 0) {
return null;
}
return {
trimOffsetLeft: -trimOffsetLeft,
trimOffsetTop: -trimOffsetTop,
width: trimmedWidth,
height: trimmedHeight
};
function trimImage(image) {
return __async(this, null, function* () {
const Jimp = yield getJimp();
const jimpImage = yield Jimp.read(
Buffer3.isBuffer(image) ? image : Buffer3.from(image)
);
const { width, height } = jimpImage.bitmap;
if (width <= 3 || height <= 3) {
return null;
}
const trimmedImage = jimpImage.autocrop();
const { width: trimmedWidth, height: trimmedHeight } = trimmedImage.bitmap;
const trimOffsetLeft = (width - trimmedWidth) / 2;
const trimOffsetTop = (height - trimmedHeight) / 2;
if (trimOffsetLeft === 0 && trimOffsetTop === 0) {
return null;
}
return {
trimOffsetLeft: -trimOffsetLeft,
trimOffsetTop: -trimOffsetTop,
width: trimmedWidth,
height: trimmedHeight
};
});
}

@@ -117,134 +188,145 @@

import assert2 from "assert";
import { Buffer as Buffer3 } from "buffer";
import Jimp3 from "jimp";
var createSvgOverlay = (elements, imageWidth, imageHeight) => {
const createPngOverlay = async (elements2, imageWidth2, imageHeight2) => {
const image = new Jimp3(imageWidth2, imageHeight2, 0);
const colors = [
{ rect: 4278190335, text: 4294967295 }
// red, white
// { rect: 0x0000ffff, text: 0xffffffff }, // blue, white
// { rect: 0x8b4513ff, text: 0xffffffff }, // brown, white
];
const boxPadding = 5;
for (let index = 0; index < elements2.length; index++) {
const element = elements2[index];
const color = colors[index % colors.length];
const paddedRect = {
left: Math.max(0, element.rect.left - boxPadding),
top: Math.max(0, element.rect.top - boxPadding),
width: Math.min(
imageWidth2 - element.rect.left,
element.rect.width + boxPadding * 2
),
height: Math.min(
imageHeight2 - element.rect.top,
element.rect.height + boxPadding * 2
)
};
image.scan(
paddedRect.left,
paddedRect.top,
paddedRect.width,
paddedRect.height,
function(x, y, idx) {
if (x === paddedRect.left || x === paddedRect.left + paddedRect.width - 1 || y === paddedRect.top || y === paddedRect.top + paddedRect.height - 1) {
this.bitmap.data[idx + 0] = color.rect >> 24 & 255;
this.bitmap.data[idx + 1] = color.rect >> 16 & 255;
this.bitmap.data[idx + 2] = color.rect >> 8 & 255;
this.bitmap.data[idx + 3] = color.rect & 255;
}
var cachedFont = null;
var createSvgOverlay = (elements, imageWidth, imageHeight) => __async(void 0, null, function* () {
const Jimp = yield getJimp();
const image = new Jimp(imageWidth, imageHeight, 0);
const colors = [
{ rect: 4278190335, text: 4294967295 }
// red, white
// { rect: 0x0000ffff, text: 0xffffffff }, // blue, white
// { rect: 0x8b4513ff, text: 0xffffffff }, // brown, white
];
const boxPadding = 5;
for (let index = 0; index < elements.length; index++) {
const element = elements[index];
const color = colors[index % colors.length];
const paddedRect = {
left: Math.max(0, element.rect.left - boxPadding),
top: Math.max(0, element.rect.top - boxPadding),
width: Math.min(
imageWidth - element.rect.left,
element.rect.width + boxPadding * 2
),
height: Math.min(
imageHeight - element.rect.top,
element.rect.height + boxPadding * 2
)
};
image.scan(
paddedRect.left,
paddedRect.top,
paddedRect.width,
paddedRect.height,
function(x, y, idx) {
if (x === paddedRect.left || x === paddedRect.left + paddedRect.width - 1 || y === paddedRect.top || y === paddedRect.top + paddedRect.height - 1) {
this.bitmap.data[idx + 0] = color.rect >> 24 & 255;
this.bitmap.data[idx + 1] = color.rect >> 16 & 255;
this.bitmap.data[idx + 2] = color.rect >> 8 & 255;
this.bitmap.data[idx + 3] = color.rect & 255;
}
);
const textWidth = element.indexId.toString().length * 8;
const textHeight = 12;
const rectWidth = textWidth + 5;
const rectHeight = textHeight + 4;
let rectX = paddedRect.left - rectWidth;
let rectY = paddedRect.top + paddedRect.height / 2 - textHeight / 2 - 2;
const checkOverlap = (x, y) => {
return elements2.slice(0, index).some((otherElement) => {
return x < otherElement.rect.left + otherElement.rect.width && x + rectWidth > otherElement.rect.left && y < otherElement.rect.top + otherElement.rect.height && y + rectHeight > otherElement.rect.top;
});
};
const isWithinBounds = (x, y) => {
return x >= 0 && x + rectWidth <= imageWidth2 && y >= 0 && y + rectHeight <= imageHeight2;
};
if (checkOverlap(rectX, rectY) || !isWithinBounds(rectX, rectY)) {
if (!checkOverlap(paddedRect.left, paddedRect.top - rectHeight - 2) && isWithinBounds(paddedRect.left, paddedRect.top - rectHeight - 2)) {
rectX = paddedRect.left;
rectY = paddedRect.top - rectHeight - 2;
} else if (!checkOverlap(
paddedRect.left,
paddedRect.top + paddedRect.height + 2
) && isWithinBounds(
paddedRect.left,
paddedRect.top + paddedRect.height + 2
)) {
rectX = paddedRect.left;
rectY = paddedRect.top + paddedRect.height + 2;
} else if (!checkOverlap(
paddedRect.left + paddedRect.width + 2,
paddedRect.top
) && isWithinBounds(paddedRect.left + paddedRect.width + 2, paddedRect.top)) {
rectX = paddedRect.left + paddedRect.width + 2;
rectY = paddedRect.top;
} else {
rectX = paddedRect.left;
rectY = paddedRect.top + 2;
}
}
image.scan(rectX, rectY, rectWidth, rectHeight, function(x, y, idx) {
this.bitmap.data[idx + 0] = color.rect >> 24 & 255;
this.bitmap.data[idx + 1] = color.rect >> 16 & 255;
this.bitmap.data[idx + 2] = color.rect >> 8 & 255;
this.bitmap.data[idx + 3] = color.rect & 255;
);
const textWidth = element.indexId.toString().length * 8;
const textHeight = 12;
const rectWidth = textWidth + 5;
const rectHeight = textHeight + 4;
let rectX = paddedRect.left - rectWidth;
let rectY = paddedRect.top + paddedRect.height / 2 - textHeight / 2 - 2;
const checkOverlap = (x, y) => {
return elements.slice(0, index).some((otherElement) => {
return x < otherElement.rect.left + otherElement.rect.width && x + rectWidth > otherElement.rect.left && y < otherElement.rect.top + otherElement.rect.height && y + rectHeight > otherElement.rect.top;
});
const font = await Jimp3.loadFont(Jimp3.FONT_SANS_16_WHITE);
image.print(
font,
rectX,
rectY,
{
text: element.indexId.toString(),
alignmentX: Jimp3.HORIZONTAL_ALIGN_CENTER,
alignmentY: Jimp3.VERTICAL_ALIGN_MIDDLE
},
rectWidth,
rectHeight
);
};
const isWithinBounds = (x, y) => {
return x >= 0 && x + rectWidth <= imageWidth && y >= 0 && y + rectHeight <= imageHeight;
};
if (checkOverlap(rectX, rectY) || !isWithinBounds(rectX, rectY)) {
if (!checkOverlap(paddedRect.left, paddedRect.top - rectHeight - 2) && isWithinBounds(paddedRect.left, paddedRect.top - rectHeight - 2)) {
rectX = paddedRect.left;
rectY = paddedRect.top - rectHeight - 2;
} else if (!checkOverlap(
paddedRect.left,
paddedRect.top + paddedRect.height + 2
) && isWithinBounds(paddedRect.left, paddedRect.top + paddedRect.height + 2)) {
rectX = paddedRect.left;
rectY = paddedRect.top + paddedRect.height + 2;
} else if (!checkOverlap(paddedRect.left + paddedRect.width + 2, paddedRect.top) && isWithinBounds(paddedRect.left + paddedRect.width + 2, paddedRect.top)) {
rectX = paddedRect.left + paddedRect.width + 2;
rectY = paddedRect.top;
} else {
rectX = paddedRect.left;
rectY = paddedRect.top + 2;
}
}
return image.getBufferAsync(Jimp3.MIME_PNG);
};
return createPngOverlay(elements, imageWidth, imageHeight);
};
var compositeElementInfoImg = async (options) => {
const { inputImgBase64, elementsPositionInfo } = options;
const imageBuffer = Buffer3.from(inputImgBase64, "base64");
const image = await Jimp3.read(imageBuffer);
const { width, height } = image.bitmap;
image.scan(rectX, rectY, rectWidth, rectHeight, function(x, y, idx) {
this.bitmap.data[idx + 0] = color.rect >> 24 & 255;
this.bitmap.data[idx + 1] = color.rect >> 16 & 255;
this.bitmap.data[idx + 2] = color.rect >> 8 & 255;
this.bitmap.data[idx + 3] = color.rect & 255;
});
try {
cachedFont = cachedFont || (yield Jimp.loadFont(Jimp.FONT_SANS_16_WHITE));
} catch (error) {
console.error("Error loading font", error);
}
image.print(
cachedFont,
rectX,
rectY,
{
text: element.indexId.toString(),
alignmentX: Jimp.HORIZONTAL_ALIGN_CENTER,
alignmentY: Jimp.VERTICAL_ALIGN_MIDDLE
},
rectWidth,
rectHeight
);
}
return image;
});
var compositeElementInfoImg = (options) => __async(void 0, null, function* () {
assert2(options.inputImgBase64, "inputImgBase64 is required");
let width = 0;
let height = 0;
let jimpImage;
const Jimp = yield getJimp();
if (options.size) {
width = options.size.width;
height = options.size.height;
}
if (!width || !height) {
const info = yield imageInfoOfBase64(options.inputImgBase64);
width = info.width;
height = info.height;
jimpImage = info.jimpImage;
} else {
const imageBuffer = yield bufferFromBase64(options.inputImgBase64);
jimpImage = yield Jimp.read(imageBuffer);
}
if (!width || !height) {
throw Error("Image processing failed because width or height is undefined");
}
const svgOverlay = await createSvgOverlay(
elementsPositionInfo,
width,
height
);
return await Jimp3.read(imageBuffer).then(async (image2) => {
const svgImage = await Jimp3.read(svgOverlay);
return image2.composite(svgImage, 0, 0, {
mode: Jimp3.BLEND_SOURCE_OVER,
const { elementsPositionInfo } = options;
const result = yield Promise.resolve(jimpImage).then((image) => __async(void 0, null, function* () {
const svgOverlay = yield createSvgOverlay(
elementsPositionInfo,
width,
height
);
const svgImage = yield Jimp.read(svgOverlay);
const compositeImage = yield image.composite(svgImage, 0, 0, {
mode: Jimp.BLEND_SOURCE_OVER,
opacitySource: 1,
opacityDest: 1
});
}).then((compositeImage) => {
return compositeImage.getBufferAsync(Jimp3.MIME_PNG);
}).then((buffer) => {
return buffer.toString("base64");
}).catch((error) => {
return compositeImage;
})).then((compositeImage) => __async(void 0, null, function* () {
const base64 = yield compositeImage.getBase64Async(Jimp.MIME_PNG);
return base64;
})).catch((error) => {
throw error;
});
};
var processImageElementInfo = async (options) => {
return result;
});
var processImageElementInfo = (options) => __async(void 0, null, function* () {
const base64Image = options.inputImgBase64.split(";base64,").pop();

@@ -255,3 +337,3 @@ assert2(base64Image, "base64Image is undefined");

compositeElementInfoImgWithoutTextBase64
] = await Promise.all([
] = yield Promise.all([
compositeElementInfoImg({

@@ -270,6 +352,7 @@ inputImgBase64: options.inputImgBase64,

};
};
});
export {
base64Encoded,
base64ToPngFormat,
bufferFromBase64,
calculateNewDimensions,

@@ -281,2 +364,3 @@ compositeElementInfoImg,

resizeImg,
resizeImgBase64,
saveBase64Image,

@@ -283,0 +367,0 @@ transformImgPathToBase64,

// src/index.ts
function src_default() {
return "hello world";
}
var src_default = {};
export {
src_default as default
};
"use strict";
var __create = Object.create;
var __defProp = Object.defineProperty;
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
var __getOwnPropNames = Object.getOwnPropertyNames;
var __getProtoOf = Object.getPrototypeOf;
var __hasOwnProp = Object.prototype.hasOwnProperty;

@@ -20,10 +18,2 @@ var __export = (target, all) => {

};
var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
// If the importer is in node compatibility mode or this is not an ESM
// file that has been converted to a CommonJS file using a Babel-
// compatible transform (i.e. "__esModule" has not been set), then set
// "default" to the CommonJS "module.exports" for node compatibility.
isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
mod
));
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);

@@ -35,25 +25,28 @@

findNearestPackageJson: () => findNearestPackageJson,
getMidscenePkgInfo: () => getMidscenePkgInfo
getRunningPkgInfo: () => getRunningPkgInfo
});
module.exports = __toCommonJS(fs_exports);
var import_node_assert = __toESM(require("assert"));
var import_node_fs = require("fs");
var import_node_path = require("path");
var pkg;
function getMidscenePkgInfo(dir) {
if (pkg) {
return pkg;
var pkgCacheMap = {};
var ifInBrowser = typeof window !== "undefined";
function getRunningPkgInfo(dir) {
if (ifInBrowser) {
return null;
}
const pkgDir = findNearestPackageJson(dir || process.cwd());
(0, import_node_assert.default)(pkgDir, "package.json not found");
const pkgJsonFile = (0, import_node_path.join)(pkgDir, "package.json");
if (pkgJsonFile) {
const dirToCheck = dir || process.cwd();
if (pkgCacheMap[dirToCheck]) {
return pkgCacheMap[dirToCheck];
}
const pkgDir = findNearestPackageJson(dirToCheck);
const pkgJsonFile = pkgDir ? (0, import_node_path.join)(pkgDir, "package.json") : null;
if (pkgDir && pkgJsonFile) {
const { name, version } = JSON.parse((0, import_node_fs.readFileSync)(pkgJsonFile, "utf-8"));
pkg = { name, version, dir: pkgDir };
return pkg;
pkgCacheMap[dirToCheck] = { name, version, dir: pkgDir };
return pkgCacheMap[dirToCheck];
}
return {
name: "midscene-unknown-page-name",
name: "midscene-unknown-package-name",
version: "0.0.0",
dir: pkgDir
dir: dirToCheck
};

@@ -75,3 +68,3 @@ }

findNearestPackageJson,
getMidscenePkgInfo
getRunningPkgInfo
});

@@ -29,2 +29,22 @@ "use strict";

var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
var __async = (__this, __arguments, generator) => {
return new Promise((resolve, reject) => {
var fulfilled = (value) => {
try {
step(generator.next(value));
} catch (e) {
reject(e);
}
};
var rejected = (value) => {
try {
step(generator.throw(value));
} catch (e) {
reject(e);
}
};
var step = (x) => x.done ? resolve(x.value) : Promise.resolve(x.value).then(fulfilled, rejected);
step((generator = generator.apply(__this, __arguments)).next());
});
};

@@ -36,2 +56,3 @@ // src/img/index.ts

base64ToPngFormat: () => base64ToPngFormat,
bufferFromBase64: () => bufferFromBase64,
calculateNewDimensions: () => calculateNewDimensions,

@@ -43,2 +64,3 @@ compositeElementInfoImg: () => compositeElementInfoImg,

resizeImg: () => resizeImg,
resizeImgBase64: () => resizeImgBase64,
saveBase64Image: () => saveBase64Image,

@@ -54,23 +76,49 @@ transformImgPathToBase64: () => transformImgPathToBase64,

var import_node_fs = require("fs");
var import_jimp = __toESM(require("jimp"));
async function imageInfo(image) {
let jimpImage;
if (typeof image === "string") {
jimpImage = await import_jimp.default.read(image);
} else if (import_node_buffer.Buffer.isBuffer(image)) {
jimpImage = await import_jimp.default.read(image);
} else {
throw new Error("Invalid image input: must be a string path or a Buffer");
}
const { width, height } = jimpImage.bitmap;
(0, import_node_assert.default)(
width && height,
`Invalid image: ${typeof image === "string" ? image : "Buffer"}`
);
return { width, height };
// src/img/get-jimp.ts
var ifInBrowser = typeof window !== "undefined";
function getJimp() {
return __async(this, null, function* () {
if (ifInBrowser) {
yield import("jimp/browser/lib/jimp.js");
return window.Jimp;
}
return (yield import("jimp")).default;
});
}
async function imageInfoOfBase64(imageBase64) {
const base64Data = imageBase64.replace(/^data:image\/\w+;base64,/, "");
return imageInfo(import_node_buffer.Buffer.from(base64Data, "base64"));
// src/img/info.ts
function imageInfo(image) {
return __async(this, null, function* () {
const Jimp = yield getJimp();
let jimpImage;
if (typeof image === "string") {
jimpImage = yield Jimp.read(image);
} else if (import_node_buffer.Buffer.isBuffer(image)) {
jimpImage = yield Jimp.read(image);
} else if (image instanceof Jimp) {
jimpImage = image;
} else {
throw new Error("Invalid image input: must be a string path or a Buffer");
}
const { width, height } = jimpImage.bitmap;
(0, import_node_assert.default)(
width && height,
`Invalid image: ${typeof image === "string" ? image : "Buffer"}`
);
return { width, height, jimpImage };
});
}
function imageInfoOfBase64(imageBase64) {
return __async(this, null, function* () {
const buffer = yield bufferFromBase64(imageBase64);
return imageInfo(buffer);
});
}
function bufferFromBase64(imageBase64) {
return __async(this, null, function* () {
const base64Data = imageBase64.replace(/^data:image\/\w+;base64,/, "");
return import_node_buffer.Buffer.from(base64Data, "base64");
});
}
function base64Encoded(image, withHeader = true) {

@@ -95,28 +143,49 @@ const imageBuffer = (0, import_node_fs.readFileSync)(image);

var import_node_buffer2 = require("buffer");
var import_jimp2 = __toESM(require("jimp"));
async function saveBase64Image(options) {
const { base64Data, outputPath } = options;
const base64Image = base64Data.split(";base64,").pop() || base64Data;
const imageBuffer = import_node_buffer2.Buffer.from(base64Image, "base64");
const image = await import_jimp2.default.read(imageBuffer);
await image.writeAsync(outputPath);
function saveBase64Image(options) {
return __async(this, null, function* () {
const { base64Data, outputPath } = options;
const base64Image = base64Data.split(";base64,").pop() || base64Data;
const imageBuffer = import_node_buffer2.Buffer.from(base64Image, "base64");
const Jimp = yield getJimp();
const image = yield Jimp.read(imageBuffer);
yield image.writeAsync(outputPath);
});
}
async function transformImgPathToBase64(inputPath) {
const image = await import_jimp2.default.read(inputPath);
const buffer = await image.getBufferAsync(import_jimp2.default.MIME_PNG);
return buffer.toString("base64");
function transformImgPathToBase64(inputPath) {
return __async(this, null, function* () {
const Jimp = yield getJimp();
const image = yield Jimp.read(inputPath);
const buffer = yield image.getBufferAsync(Jimp.MIME_PNG);
return buffer.toString("base64");
});
}
async function resizeImg(inputData, newSize) {
const isBase64 = typeof inputData === "string";
const imageBuffer = isBase64 ? import_node_buffer2.Buffer.from(inputData.split(";base64,").pop() || inputData, "base64") : inputData;
const image = await import_jimp2.default.read(imageBuffer);
const { width, height } = image.bitmap;
if (!width || !height) {
throw Error("Undefined width or height from the input image.");
}
const finalNewSize = newSize || calculateNewDimensions(width, height);
image.resize(finalNewSize.width, finalNewSize.height);
const resizedBuffer = await image.getBufferAsync(import_jimp2.default.MIME_PNG);
return isBase64 ? resizedBuffer.toString("base64") : resizedBuffer;
function resizeImg(inputData, newSize) {
return __async(this, null, function* () {
if (typeof inputData === "string")
throw Error("inputData is base64, use resizeImgBase64 instead");
const Jimp = yield getJimp();
const image = yield Jimp.read(inputData);
const { width, height } = image.bitmap;
if (!width || !height) {
throw Error("Undefined width or height from the input image.");
}
const finalNewSize = newSize || calculateNewDimensions(width, height);
image.resize(finalNewSize.width, finalNewSize.height);
const resizedBuffer = yield image.getBufferAsync(Jimp.MIME_PNG);
return resizedBuffer;
});
}
function resizeImgBase64(inputData, newSize) {
return __async(this, null, function* () {
const splitFlag = ";base64,";
const dataSplitted = inputData.split(splitFlag);
if (dataSplitted.length !== 2) {
throw Error("Invalid base64 data");
}
const imageBuffer = import_node_buffer2.Buffer.from(dataSplitted[1], "base64");
const buffer = yield resizeImg(imageBuffer, newSize);
const content = buffer.toString("base64");
return `${dataSplitted[0]}${splitFlag}${content}`;
});
}
function calculateNewDimensions(originalWidth, originalHeight) {

@@ -141,23 +210,26 @@ const maxWidth = 2048;

}
async function trimImage(image) {
const jimpImage = await import_jimp2.default.read(
import_node_buffer2.Buffer.isBuffer(image) ? image : import_node_buffer2.Buffer.from(image)
);
const { width, height } = jimpImage.bitmap;
if (width <= 3 || height <= 3) {
return null;
}
const trimmedImage = jimpImage.autocrop();
const { width: trimmedWidth, height: trimmedHeight } = trimmedImage.bitmap;
const trimOffsetLeft = (width - trimmedWidth) / 2;
const trimOffsetTop = (height - trimmedHeight) / 2;
if (trimOffsetLeft === 0 && trimOffsetTop === 0) {
return null;
}
return {
trimOffsetLeft: -trimOffsetLeft,
trimOffsetTop: -trimOffsetTop,
width: trimmedWidth,
height: trimmedHeight
};
function trimImage(image) {
return __async(this, null, function* () {
const Jimp = yield getJimp();
const jimpImage = yield Jimp.read(
import_node_buffer2.Buffer.isBuffer(image) ? image : import_node_buffer2.Buffer.from(image)
);
const { width, height } = jimpImage.bitmap;
if (width <= 3 || height <= 3) {
return null;
}
const trimmedImage = jimpImage.autocrop();
const { width: trimmedWidth, height: trimmedHeight } = trimmedImage.bitmap;
const trimOffsetLeft = (width - trimmedWidth) / 2;
const trimOffsetTop = (height - trimmedHeight) / 2;
if (trimOffsetLeft === 0 && trimOffsetTop === 0) {
return null;
}
return {
trimOffsetLeft: -trimOffsetLeft,
trimOffsetTop: -trimOffsetTop,
width: trimmedWidth,
height: trimmedHeight
};
});
}

@@ -167,134 +239,145 @@

var import_node_assert2 = __toESM(require("assert"));
var import_node_buffer3 = require("buffer");
var import_jimp3 = __toESM(require("jimp"));
var createSvgOverlay = (elements, imageWidth, imageHeight) => {
const createPngOverlay = async (elements2, imageWidth2, imageHeight2) => {
const image = new import_jimp3.default(imageWidth2, imageHeight2, 0);
const colors = [
{ rect: 4278190335, text: 4294967295 }
// red, white
// { rect: 0x0000ffff, text: 0xffffffff }, // blue, white
// { rect: 0x8b4513ff, text: 0xffffffff }, // brown, white
];
const boxPadding = 5;
for (let index = 0; index < elements2.length; index++) {
const element = elements2[index];
const color = colors[index % colors.length];
const paddedRect = {
left: Math.max(0, element.rect.left - boxPadding),
top: Math.max(0, element.rect.top - boxPadding),
width: Math.min(
imageWidth2 - element.rect.left,
element.rect.width + boxPadding * 2
),
height: Math.min(
imageHeight2 - element.rect.top,
element.rect.height + boxPadding * 2
)
};
image.scan(
paddedRect.left,
paddedRect.top,
paddedRect.width,
paddedRect.height,
function(x, y, idx) {
if (x === paddedRect.left || x === paddedRect.left + paddedRect.width - 1 || y === paddedRect.top || y === paddedRect.top + paddedRect.height - 1) {
this.bitmap.data[idx + 0] = color.rect >> 24 & 255;
this.bitmap.data[idx + 1] = color.rect >> 16 & 255;
this.bitmap.data[idx + 2] = color.rect >> 8 & 255;
this.bitmap.data[idx + 3] = color.rect & 255;
}
var cachedFont = null;
var createSvgOverlay = (elements, imageWidth, imageHeight) => __async(void 0, null, function* () {
const Jimp = yield getJimp();
const image = new Jimp(imageWidth, imageHeight, 0);
const colors = [
{ rect: 4278190335, text: 4294967295 }
// red, white
// { rect: 0x0000ffff, text: 0xffffffff }, // blue, white
// { rect: 0x8b4513ff, text: 0xffffffff }, // brown, white
];
const boxPadding = 5;
for (let index = 0; index < elements.length; index++) {
const element = elements[index];
const color = colors[index % colors.length];
const paddedRect = {
left: Math.max(0, element.rect.left - boxPadding),
top: Math.max(0, element.rect.top - boxPadding),
width: Math.min(
imageWidth - element.rect.left,
element.rect.width + boxPadding * 2
),
height: Math.min(
imageHeight - element.rect.top,
element.rect.height + boxPadding * 2
)
};
image.scan(
paddedRect.left,
paddedRect.top,
paddedRect.width,
paddedRect.height,
function(x, y, idx) {
if (x === paddedRect.left || x === paddedRect.left + paddedRect.width - 1 || y === paddedRect.top || y === paddedRect.top + paddedRect.height - 1) {
this.bitmap.data[idx + 0] = color.rect >> 24 & 255;
this.bitmap.data[idx + 1] = color.rect >> 16 & 255;
this.bitmap.data[idx + 2] = color.rect >> 8 & 255;
this.bitmap.data[idx + 3] = color.rect & 255;
}
);
const textWidth = element.indexId.toString().length * 8;
const textHeight = 12;
const rectWidth = textWidth + 5;
const rectHeight = textHeight + 4;
let rectX = paddedRect.left - rectWidth;
let rectY = paddedRect.top + paddedRect.height / 2 - textHeight / 2 - 2;
const checkOverlap = (x, y) => {
return elements2.slice(0, index).some((otherElement) => {
return x < otherElement.rect.left + otherElement.rect.width && x + rectWidth > otherElement.rect.left && y < otherElement.rect.top + otherElement.rect.height && y + rectHeight > otherElement.rect.top;
});
};
const isWithinBounds = (x, y) => {
return x >= 0 && x + rectWidth <= imageWidth2 && y >= 0 && y + rectHeight <= imageHeight2;
};
if (checkOverlap(rectX, rectY) || !isWithinBounds(rectX, rectY)) {
if (!checkOverlap(paddedRect.left, paddedRect.top - rectHeight - 2) && isWithinBounds(paddedRect.left, paddedRect.top - rectHeight - 2)) {
rectX = paddedRect.left;
rectY = paddedRect.top - rectHeight - 2;
} else if (!checkOverlap(
paddedRect.left,
paddedRect.top + paddedRect.height + 2
) && isWithinBounds(
paddedRect.left,
paddedRect.top + paddedRect.height + 2
)) {
rectX = paddedRect.left;
rectY = paddedRect.top + paddedRect.height + 2;
} else if (!checkOverlap(
paddedRect.left + paddedRect.width + 2,
paddedRect.top
) && isWithinBounds(paddedRect.left + paddedRect.width + 2, paddedRect.top)) {
rectX = paddedRect.left + paddedRect.width + 2;
rectY = paddedRect.top;
} else {
rectX = paddedRect.left;
rectY = paddedRect.top + 2;
}
}
image.scan(rectX, rectY, rectWidth, rectHeight, function(x, y, idx) {
this.bitmap.data[idx + 0] = color.rect >> 24 & 255;
this.bitmap.data[idx + 1] = color.rect >> 16 & 255;
this.bitmap.data[idx + 2] = color.rect >> 8 & 255;
this.bitmap.data[idx + 3] = color.rect & 255;
);
const textWidth = element.indexId.toString().length * 8;
const textHeight = 12;
const rectWidth = textWidth + 5;
const rectHeight = textHeight + 4;
let rectX = paddedRect.left - rectWidth;
let rectY = paddedRect.top + paddedRect.height / 2 - textHeight / 2 - 2;
const checkOverlap = (x, y) => {
return elements.slice(0, index).some((otherElement) => {
return x < otherElement.rect.left + otherElement.rect.width && x + rectWidth > otherElement.rect.left && y < otherElement.rect.top + otherElement.rect.height && y + rectHeight > otherElement.rect.top;
});
const font = await import_jimp3.default.loadFont(import_jimp3.default.FONT_SANS_16_WHITE);
image.print(
font,
rectX,
rectY,
{
text: element.indexId.toString(),
alignmentX: import_jimp3.default.HORIZONTAL_ALIGN_CENTER,
alignmentY: import_jimp3.default.VERTICAL_ALIGN_MIDDLE
},
rectWidth,
rectHeight
);
};
const isWithinBounds = (x, y) => {
return x >= 0 && x + rectWidth <= imageWidth && y >= 0 && y + rectHeight <= imageHeight;
};
if (checkOverlap(rectX, rectY) || !isWithinBounds(rectX, rectY)) {
if (!checkOverlap(paddedRect.left, paddedRect.top - rectHeight - 2) && isWithinBounds(paddedRect.left, paddedRect.top - rectHeight - 2)) {
rectX = paddedRect.left;
rectY = paddedRect.top - rectHeight - 2;
} else if (!checkOverlap(
paddedRect.left,
paddedRect.top + paddedRect.height + 2
) && isWithinBounds(paddedRect.left, paddedRect.top + paddedRect.height + 2)) {
rectX = paddedRect.left;
rectY = paddedRect.top + paddedRect.height + 2;
} else if (!checkOverlap(paddedRect.left + paddedRect.width + 2, paddedRect.top) && isWithinBounds(paddedRect.left + paddedRect.width + 2, paddedRect.top)) {
rectX = paddedRect.left + paddedRect.width + 2;
rectY = paddedRect.top;
} else {
rectX = paddedRect.left;
rectY = paddedRect.top + 2;
}
}
return image.getBufferAsync(import_jimp3.default.MIME_PNG);
};
return createPngOverlay(elements, imageWidth, imageHeight);
};
var compositeElementInfoImg = async (options) => {
const { inputImgBase64, elementsPositionInfo } = options;
const imageBuffer = import_node_buffer3.Buffer.from(inputImgBase64, "base64");
const image = await import_jimp3.default.read(imageBuffer);
const { width, height } = image.bitmap;
image.scan(rectX, rectY, rectWidth, rectHeight, function(x, y, idx) {
this.bitmap.data[idx + 0] = color.rect >> 24 & 255;
this.bitmap.data[idx + 1] = color.rect >> 16 & 255;
this.bitmap.data[idx + 2] = color.rect >> 8 & 255;
this.bitmap.data[idx + 3] = color.rect & 255;
});
try {
cachedFont = cachedFont || (yield Jimp.loadFont(Jimp.FONT_SANS_16_WHITE));
} catch (error) {
console.error("Error loading font", error);
}
image.print(
cachedFont,
rectX,
rectY,
{
text: element.indexId.toString(),
alignmentX: Jimp.HORIZONTAL_ALIGN_CENTER,
alignmentY: Jimp.VERTICAL_ALIGN_MIDDLE
},
rectWidth,
rectHeight
);
}
return image;
});
var compositeElementInfoImg = (options) => __async(void 0, null, function* () {
(0, import_node_assert2.default)(options.inputImgBase64, "inputImgBase64 is required");
let width = 0;
let height = 0;
let jimpImage;
const Jimp = yield getJimp();
if (options.size) {
width = options.size.width;
height = options.size.height;
}
if (!width || !height) {
const info = yield imageInfoOfBase64(options.inputImgBase64);
width = info.width;
height = info.height;
jimpImage = info.jimpImage;
} else {
const imageBuffer = yield bufferFromBase64(options.inputImgBase64);
jimpImage = yield Jimp.read(imageBuffer);
}
if (!width || !height) {
throw Error("Image processing failed because width or height is undefined");
}
const svgOverlay = await createSvgOverlay(
elementsPositionInfo,
width,
height
);
return await import_jimp3.default.read(imageBuffer).then(async (image2) => {
const svgImage = await import_jimp3.default.read(svgOverlay);
return image2.composite(svgImage, 0, 0, {
mode: import_jimp3.default.BLEND_SOURCE_OVER,
const { elementsPositionInfo } = options;
const result = yield Promise.resolve(jimpImage).then((image) => __async(void 0, null, function* () {
const svgOverlay = yield createSvgOverlay(
elementsPositionInfo,
width,
height
);
const svgImage = yield Jimp.read(svgOverlay);
const compositeImage = yield image.composite(svgImage, 0, 0, {
mode: Jimp.BLEND_SOURCE_OVER,
opacitySource: 1,
opacityDest: 1
});
}).then((compositeImage) => {
return compositeImage.getBufferAsync(import_jimp3.default.MIME_PNG);
}).then((buffer) => {
return buffer.toString("base64");
}).catch((error) => {
return compositeImage;
})).then((compositeImage) => __async(void 0, null, function* () {
const base64 = yield compositeImage.getBase64Async(Jimp.MIME_PNG);
return base64;
})).catch((error) => {
throw error;
});
};
var processImageElementInfo = async (options) => {
return result;
});
var processImageElementInfo = (options) => __async(void 0, null, function* () {
const base64Image = options.inputImgBase64.split(";base64,").pop();

@@ -305,3 +388,3 @@ (0, import_node_assert2.default)(base64Image, "base64Image is undefined");

compositeElementInfoImgWithoutTextBase64
] = await Promise.all([
] = yield Promise.all([
compositeElementInfoImg({

@@ -320,3 +403,3 @@ inputImgBase64: options.inputImgBase64,

};
};
});
// Annotate the CommonJS export names for ESM import in node:

@@ -326,2 +409,3 @@ 0 && (module.exports = {

base64ToPngFormat,
bufferFromBase64,
calculateNewDimensions,

@@ -333,2 +417,3 @@ compositeElementInfoImg,

resizeImg,
resizeImgBase64,
saveBase64Image,

@@ -335,0 +420,0 @@ transformImgPathToBase64,

@@ -26,4 +26,2 @@ "use strict";

module.exports = __toCommonJS(src_exports);
function src_default() {
return "hello world";
}
var src_default = {};

@@ -1,3 +0,3 @@

declare function export_default(): string;
declare const _default: {};
export { export_default as default };
export { _default as default };
{
"name": "@midscene/shared",
"version": "0.7.2",
"version": "0.7.3-beta-20241029030944.0",
"repository": "https://github.com/web-infra-dev/midscene",
"homepage": "https://midscenejs.com/",
"types": "./dist/types/index.d.ts",
"types": "./src/index.ts",
"type": "commonjs",
"main": "./dist/lib/index.js",

@@ -11,20 +12,30 @@ "module": "./dist/es/index.js",

".": {
"types": "./dist/types/index.d.ts",
"import": "./dist/es/index.js",
"require": "./dist/lib/index.js"
"types": "./dist/lib/index.d.ts",
"require": "./dist/lib/index.js",
"import": "./dist/es/index.js"
},
"./constants": {
"types": "./dist/types/constants.d.ts",
"import": "./dist/es/constants.js",
"require": "./dist/lib/constants.js"
"types": "./dist/lib/constants.d.ts",
"require": "./dist/lib/constants.js",
"import": "./dist/es/constants.js"
},
"./fs": {
"types": "./dist/lib/fs.d.ts",
"require": "./dist/lib/fs.js",
"import": "./dist/es/fs.js"
},
"./img": {
"types": "./dist/types/img.d.ts",
"import": "./dist/es/img.js",
"require": "./dist/lib/img.js"
"types": "./dist/lib/img.d.ts",
"require": "./dist/lib/img.js",
"import": "./dist/es/img.js"
},
"./fs": {
"types": "./dist/types/fs.d.ts",
"import": "./dist/es/fs.js",
"require": "./dist/lib/fs.js"
"./browser/img": {
"types": "./dist/browser/img.d.ts",
"require": "./dist/browser/img.js",
"import": "./dist/browser/img.js"
},
"./utils": {
"types": "./dist/lib/utils.d.ts",
"require": "./dist/lib/utils.js",
"import": "./dist/es/utils.js"
}

@@ -35,12 +46,18 @@ },

".": [
"./dist/types/index.d.ts"
"./dist/lib/index.d.ts"
],
"constants": [
"./dist/types/constants.d.ts"
"./dist/lib/constants.d.ts"
],
"img": [
"./dist/types/img.d.ts"
"./dist/lib/img.d.ts"
],
"browser/img": [
"./dist/browser/img.d.ts"
],
"fs": [
"./dist/types/fs.d.ts"
"./dist/lib/fs.d.ts"
],
"utils": [
"./dist/lib/utils.d.ts"
]

@@ -47,0 +64,0 @@ }

@@ -11,21 +11,25 @@ import assert from 'node:assert';

let pkg: PkgInfo | undefined;
export function getMidscenePkgInfo(dir: string): PkgInfo {
if (pkg) {
return pkg;
const pkgCacheMap: Record<string, PkgInfo> = {};
const ifInBrowser = typeof window !== 'undefined';
export function getRunningPkgInfo(dir?: string): PkgInfo | null {
if (ifInBrowser) {
return null;
}
const dirToCheck = dir || process.cwd();
if (pkgCacheMap[dirToCheck]) {
return pkgCacheMap[dirToCheck];
}
const pkgDir = findNearestPackageJson(dir || process.cwd());
assert(pkgDir, 'package.json not found');
const pkgJsonFile = join(pkgDir, 'package.json');
const pkgDir = findNearestPackageJson(dirToCheck);
const pkgJsonFile = pkgDir ? join(pkgDir, 'package.json') : null;
if (pkgJsonFile) {
if (pkgDir && pkgJsonFile) {
const { name, version } = JSON.parse(readFileSync(pkgJsonFile, 'utf-8'));
pkg = { name, version, dir: pkgDir };
return pkg;
pkgCacheMap[dirToCheck] = { name, version, dir: pkgDir };
return pkgCacheMap[dirToCheck];
}
return {
name: 'midscene-unknown-page-name',
name: 'midscene-unknown-package-name',
version: '0.0.0',
dir: pkgDir,
dir: dirToCheck,
};

@@ -32,0 +36,0 @@ }

import assert from 'node:assert';
import { Buffer } from 'node:buffer';
import type { Buffer } from 'node:buffer';
import type { Rect } from '@/types';
import Jimp from 'jimp';
import type Jimp from 'jimp';
import type { NodeType } from '../constants';
import getJimp from './get-jimp';
import { bufferFromBase64, imageInfo, imageInfoOfBase64 } from './index';

@@ -25,166 +27,159 @@ // Define picture path

const createSvgOverlay = (
let cachedFont: any = null;
const createSvgOverlay = async (
elements: Array<ElementType>,
imageWidth: number,
imageHeight: number,
) => {
const createPngOverlay = async (
elements: Array<ElementType>,
imageWidth: number,
imageHeight: number,
) => {
const image = new Jimp(imageWidth, imageHeight, 0x00000000);
): Promise<Jimp> => {
const Jimp = await getJimp();
const image = new Jimp(imageWidth, imageHeight, 0x00000000);
// Define color array
const colors = [
{ rect: 0xff0000ff, text: 0xffffffff }, // red, white
// { rect: 0x0000ffff, text: 0xffffffff }, // blue, white
// { rect: 0x8b4513ff, text: 0xffffffff }, // brown, white
];
// Define color array
const colors = [
{ rect: 0xff0000ff, text: 0xffffffff }, // red, white
// { rect: 0x0000ffff, text: 0xffffffff }, // blue, white
// { rect: 0x8b4513ff, text: 0xffffffff }, // brown, white
];
const boxPadding = 5;
for (let index = 0; index < elements.length; index++) {
const element = elements[index];
const color = colors[index % colors.length];
const boxPadding = 5;
for (let index = 0; index < elements.length; index++) {
const element = elements[index];
const color = colors[index % colors.length];
// Add 5px padding to the rect
const paddedRect = {
left: Math.max(0, element.rect.left - boxPadding),
top: Math.max(0, element.rect.top - boxPadding),
width: Math.min(
imageWidth - element.rect.left,
element.rect.width + boxPadding * 2,
),
height: Math.min(
imageHeight - element.rect.top,
element.rect.height + boxPadding * 2,
),
};
// Add 5px padding to the rect
const paddedRect = {
left: Math.max(0, element.rect.left - boxPadding),
top: Math.max(0, element.rect.top - boxPadding),
width: Math.min(
imageWidth - element.rect.left,
element.rect.width + boxPadding * 2,
),
height: Math.min(
imageHeight - element.rect.top,
element.rect.height + boxPadding * 2,
),
};
// Draw rectangle
image.scan(
paddedRect.left,
paddedRect.top,
paddedRect.width,
paddedRect.height,
function (x, y, idx) {
if (
x === paddedRect.left ||
x === paddedRect.left + paddedRect.width - 1 ||
y === paddedRect.top ||
y === paddedRect.top + paddedRect.height - 1
) {
this.bitmap.data[idx + 0] = (color.rect >> 24) & 0xff; // R
this.bitmap.data[idx + 1] = (color.rect >> 16) & 0xff; // G
this.bitmap.data[idx + 2] = (color.rect >> 8) & 0xff; // B
this.bitmap.data[idx + 3] = color.rect & 0xff; // A
}
},
);
// Draw rectangle
image.scan(
paddedRect.left,
paddedRect.top,
paddedRect.width,
paddedRect.height,
function (x, y, idx) {
if (
x === paddedRect.left ||
x === paddedRect.left + paddedRect.width - 1 ||
y === paddedRect.top ||
y === paddedRect.top + paddedRect.height - 1
) {
this.bitmap.data[idx + 0] = (color.rect >> 24) & 0xff; // R
this.bitmap.data[idx + 1] = (color.rect >> 16) & 0xff; // G
this.bitmap.data[idx + 2] = (color.rect >> 8) & 0xff; // B
this.bitmap.data[idx + 3] = color.rect & 0xff; // A
}
},
);
// Calculate text position
const textWidth = element.indexId.toString().length * 8;
const textHeight = 12;
const rectWidth = textWidth + 5;
const rectHeight = textHeight + 4;
let rectX = paddedRect.left - rectWidth;
let rectY = paddedRect.top + paddedRect.height / 2 - textHeight / 2 - 2;
// Calculate text position
const textWidth = element.indexId.toString().length * 8;
const textHeight = 12;
const rectWidth = textWidth + 5;
const rectHeight = textHeight + 4;
let rectX = paddedRect.left - rectWidth;
let rectY = paddedRect.top + paddedRect.height / 2 - textHeight / 2 - 2;
// Check if this new position overlaps with any existing boxes
// Function to check if a given position overlaps with any existing boxes
const checkOverlap = (x: number, y: number) => {
// Check against all previously processed elements
return elements.slice(0, index).some((otherElement) => {
// Check if the rectangles overlap
return (
x < otherElement.rect.left + otherElement.rect.width &&
x + rectWidth > otherElement.rect.left &&
y < otherElement.rect.top + otherElement.rect.height &&
y + rectHeight > otherElement.rect.top
);
});
};
// Function to check if a given position is within the image bounds
const isWithinBounds = (x: number, y: number) => {
// Check if this new position overlaps with any existing boxes
// Function to check if a given position overlaps with any existing boxes
const checkOverlap = (x: number, y: number) => {
// Check against all previously processed elements
return elements.slice(0, index).some((otherElement) => {
// Check if the rectangles overlap
return (
x >= 0 &&
x + rectWidth <= imageWidth &&
y >= 0 &&
y + rectHeight <= imageHeight
x < otherElement.rect.left + otherElement.rect.width &&
x + rectWidth > otherElement.rect.left &&
y < otherElement.rect.top + otherElement.rect.height &&
y + rectHeight > otherElement.rect.top
);
};
});
};
// Check left side (original position)
if (checkOverlap(rectX, rectY) || !isWithinBounds(rectX, rectY)) {
// If the original position overlaps or is out of bounds, try alternative positions
// Function to check if a given position is within the image bounds
const isWithinBounds = (x: number, y: number) => {
return (
x >= 0 &&
x + rectWidth <= imageWidth &&
y >= 0 &&
y + rectHeight <= imageHeight
);
};
// Check top position
if (
!checkOverlap(paddedRect.left, paddedRect.top - rectHeight - 2) &&
isWithinBounds(paddedRect.left, paddedRect.top - rectHeight - 2)
) {
rectX = paddedRect.left;
rectY = paddedRect.top - rectHeight - 2;
}
// Check bottom position
else if (
!checkOverlap(
paddedRect.left,
paddedRect.top + paddedRect.height + 2,
) &&
isWithinBounds(
paddedRect.left,
paddedRect.top + paddedRect.height + 2,
)
) {
rectX = paddedRect.left;
rectY = paddedRect.top + paddedRect.height + 2;
}
// Check right position
else if (
!checkOverlap(
paddedRect.left + paddedRect.width + 2,
paddedRect.top,
) &&
isWithinBounds(paddedRect.left + paddedRect.width + 2, paddedRect.top)
) {
rectX = paddedRect.left + paddedRect.width + 2;
rectY = paddedRect.top;
}
// If all sides are overlapped or out of bounds, place it inside the box at the top
else {
rectX = paddedRect.left;
rectY = paddedRect.top + 2;
}
// Check left side (original position)
if (checkOverlap(rectX, rectY) || !isWithinBounds(rectX, rectY)) {
// If the original position overlaps or is out of bounds, try alternative positions
// Check top position
if (
!checkOverlap(paddedRect.left, paddedRect.top - rectHeight - 2) &&
isWithinBounds(paddedRect.left, paddedRect.top - rectHeight - 2)
) {
rectX = paddedRect.left;
rectY = paddedRect.top - rectHeight - 2;
}
// Note: If the original left position doesn't overlap and is within bounds, we keep it as is
// Check bottom position
else if (
!checkOverlap(
paddedRect.left,
paddedRect.top + paddedRect.height + 2,
) &&
isWithinBounds(paddedRect.left, paddedRect.top + paddedRect.height + 2)
) {
rectX = paddedRect.left;
rectY = paddedRect.top + paddedRect.height + 2;
}
// Check right position
else if (
!checkOverlap(paddedRect.left + paddedRect.width + 2, paddedRect.top) &&
isWithinBounds(paddedRect.left + paddedRect.width + 2, paddedRect.top)
) {
rectX = paddedRect.left + paddedRect.width + 2;
rectY = paddedRect.top;
}
// If all sides are overlapped or out of bounds, place it inside the box at the top
else {
rectX = paddedRect.left;
rectY = paddedRect.top + 2;
}
}
// Note: If the original left position doesn't overlap and is within bounds, we keep it as is
// Draw text background
image.scan(rectX, rectY, rectWidth, rectHeight, function (x, y, idx) {
this.bitmap.data[idx + 0] = (color.rect >> 24) & 0xff; // R
this.bitmap.data[idx + 1] = (color.rect >> 16) & 0xff; // G
this.bitmap.data[idx + 2] = (color.rect >> 8) & 0xff; // B
this.bitmap.data[idx + 3] = color.rect & 0xff; // A
});
// Draw text (simplified, as Jimp doesn't have built-in text drawing)
const font = await Jimp.loadFont(Jimp.FONT_SANS_16_WHITE);
image.print(
font,
rectX,
rectY,
{
text: element.indexId.toString(),
alignmentX: Jimp.HORIZONTAL_ALIGN_CENTER,
alignmentY: Jimp.VERTICAL_ALIGN_MIDDLE,
},
rectWidth,
rectHeight,
);
// Draw text background
image.scan(rectX, rectY, rectWidth, rectHeight, function (x, y, idx) {
this.bitmap.data[idx + 0] = (color.rect >> 24) & 0xff; // R
this.bitmap.data[idx + 1] = (color.rect >> 16) & 0xff; // G
this.bitmap.data[idx + 2] = (color.rect >> 8) & 0xff; // B
this.bitmap.data[idx + 3] = color.rect & 0xff; // A
});
// Draw text (simplified, as Jimp doesn't have built-in text drawing)
try {
cachedFont = cachedFont || (await Jimp.loadFont(Jimp.FONT_SANS_16_WHITE));
} catch (error) {
console.error('Error loading font', error);
}
image.print(
cachedFont,
rectX,
rectY,
{
text: element.indexId.toString(),
alignmentX: Jimp.HORIZONTAL_ALIGN_CENTER,
alignmentY: Jimp.VERTICAL_ALIGN_MIDDLE,
},
rectWidth,
rectHeight,
);
}
return image.getBufferAsync(Jimp.MIME_PNG);
};
return createPngOverlay(elements, imageWidth, imageHeight);
return image;
};

@@ -195,23 +190,42 @@

elementsPositionInfo: Array<ElementType>;
size?: { width: number; height: number };
}) => {
const { inputImgBase64, elementsPositionInfo } = options;
const imageBuffer = Buffer.from(inputImgBase64, 'base64');
const image = await Jimp.read(imageBuffer);
const { width, height } = image.bitmap;
assert(options.inputImgBase64, 'inputImgBase64 is required');
let width = 0;
let height = 0;
let jimpImage: Jimp;
const Jimp = await getJimp();
if (options.size) {
width = options.size.width;
height = options.size.height;
}
if (!width || !height) {
const info = await imageInfoOfBase64(options.inputImgBase64);
width = info.width;
height = info.height;
jimpImage = info.jimpImage;
} else {
const imageBuffer = await bufferFromBase64(options.inputImgBase64);
jimpImage = await Jimp.read(imageBuffer);
}
if (!width || !height) {
throw Error('Image processing failed because width or height is undefined');
}
// Create svg overlay
const svgOverlay = await createSvgOverlay(
elementsPositionInfo,
width,
height,
);
const { elementsPositionInfo } = options;
return await Jimp.read(imageBuffer)
const result = await Promise.resolve(jimpImage)
.then(async (image: Jimp) => {
// Create svg overlay
const svgOverlay = await createSvgOverlay(
elementsPositionInfo,
width,
height,
);
const svgImage = await Jimp.read(svgOverlay);
return image.composite(svgImage, 0, 0, {
const compositeImage = await image.composite(svgImage, 0, 0, {
mode: Jimp.BLEND_SOURCE_OVER,

@@ -221,12 +235,13 @@ opacitySource: 1,

});
return compositeImage;
})
.then((compositeImage: Jimp) => {
return compositeImage.getBufferAsync(Jimp.MIME_PNG);
.then(async (compositeImage: Jimp) => {
const base64 = await compositeImage.getBase64Async(Jimp.MIME_PNG);
return base64;
})
.then((buffer: Buffer) => {
return buffer.toString('base64');
})
.catch((error: unknown) => {
throw error;
});
return result;
};

@@ -233,0 +248,0 @@

export {
imageInfo,
imageInfoOfBase64,
bufferFromBase64,
base64Encoded,

@@ -11,2 +12,3 @@ base64ToPngFormat,

resizeImg,
resizeImgBase64,
transformImgPathToBase64,

@@ -13,0 +15,0 @@ saveBase64Image,

import assert from 'node:assert';
import { Buffer } from 'node:buffer';
import { readFileSync } from 'node:fs';
import Jimp from 'jimp';
import type Jimp from 'jimp';
import getJimp from './get-jimp';

@@ -11,2 +12,6 @@ export interface Size {

export interface ImageInfo extends Size {
jimpImage: Jimp;
}
/**

@@ -19,3 +24,6 @@ * Retrieves the dimensions of an image asynchronously

*/
export async function imageInfo(image: string | Buffer): Promise<Size> {
export async function imageInfo(
image: string | Buffer | Jimp,
): Promise<ImageInfo> {
const Jimp = await getJimp();
let jimpImage: Jimp;

@@ -26,2 +34,4 @@ if (typeof image === 'string') {

jimpImage = await Jimp.read(image);
} else if (image instanceof Jimp) {
jimpImage = image;
} else {

@@ -35,3 +45,3 @@ throw new Error('Invalid image input: must be a string path or a Buffer');

);
return { width, height };
return { width, height, jimpImage };
}

@@ -46,8 +56,16 @@

*/
export async function imageInfoOfBase64(imageBase64: string): Promise<Size> {
const base64Data = imageBase64.replace(/^data:image\/\w+;base64,/, '');
export async function imageInfoOfBase64(
imageBase64: string,
): Promise<ImageInfo> {
// const base64Data = imageBase64.replace(/^data:image\/\w+;base64,/, '');
// Call the imageInfo function to get the dimensions of the image
return imageInfo(Buffer.from(base64Data, 'base64'));
const buffer = await bufferFromBase64(imageBase64);
return imageInfo(buffer);
}
export async function bufferFromBase64(imageBase64: string): Promise<Buffer> {
const base64Data = imageBase64.replace(/^data:image\/\w+;base64,/, '');
return Buffer.from(base64Data, 'base64');
}
/**

@@ -54,0 +72,0 @@ * Encodes an image file to a base64 encoded string

import { Buffer } from 'node:buffer';
import Jimp from 'jimp';
import getJimp from './get-jimp';
/**
/**
* Saves a Base64-encoded image to a file

@@ -24,2 +25,3 @@ *

// Use Jimp to process the image and save it to the specified location
const Jimp = await getJimp();
const image = await Jimp.read(imageBuffer);

@@ -36,2 +38,3 @@ await image.writeAsync(outputPath);

// Use Jimp to process images and generate base64 data
const Jimp = await getJimp();
const image = await Jimp.read(inputPath);

@@ -50,3 +53,3 @@ const buffer = await image.getBufferAsync(Jimp.MIME_PNG);

export async function resizeImg(
inputData: string | Buffer,
inputData: Buffer,
newSize?: {

@@ -56,9 +59,8 @@ width: number;

},
): Promise<string | Buffer> {
const isBase64 = typeof inputData === 'string';
const imageBuffer = isBase64
? Buffer.from(inputData.split(';base64,').pop() || inputData, 'base64')
: inputData;
): Promise<Buffer> {
if (typeof inputData === 'string')
throw Error('inputData is base64, use resizeImgBase64 instead');
const image = await Jimp.read(imageBuffer);
const Jimp = await getJimp();
const image = await Jimp.read(inputData);
const { width, height } = image.bitmap;

@@ -75,5 +77,24 @@

return isBase64 ? resizedBuffer.toString('base64') : resizedBuffer;
return resizedBuffer;
}
export async function resizeImgBase64(
inputData: string,
newSize?: {
width: number;
height: number;
},
): Promise<string> {
const splitFlag = ';base64,';
const dataSplitted = inputData.split(splitFlag);
if (dataSplitted.length !== 2) {
throw Error('Invalid base64 data');
}
const imageBuffer = Buffer.from(dataSplitted[1], 'base64');
const buffer = await resizeImg(imageBuffer, newSize);
const content = buffer.toString('base64');
return `${dataSplitted[0]}${splitFlag}${content}`;
}
/**

@@ -135,2 +156,3 @@ * Calculates new dimensions for an image while maintaining its aspect ratio.

} | null> {
const Jimp = await getJimp();
const jimpImage = await Jimp.read(

@@ -137,0 +159,0 @@ Buffer.isBuffer(image) ? image : Buffer.from(image),

@@ -1,3 +0,1 @@

export default function () {
return 'hello world';
}
export default {};
SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc