Getting bus error when composing a lot of images with sharp - node.js

I'm trying to compose a ton of images (2300) into a transparent png using sharp. I'm trying that with the following code:
await sharp({
create: {
width: 256,
height: 256,
channels: 4,
background: { r: 0, g: 0, b: 0, alpha: 0 },
},
})
.composite(images)
.png()
.toBuffer();
Where images is an array generated like this:
const pinSvg = fs.readFileSync("./icon_web_pin_record_basic.svg");
const pinWidth = 18;
const pinHeight = 25;
const generateImageFromLocationArray = (locations) => {
const images = [];
for (let i = 0; i < locations.length; i++) {
const [x, y] = locations[i];
images.push({
input: pinSvg,
blend: "add",
left: x - Math.floor(pinWidth / 2),
top: y - pinHeight,
});
}
return images;
};
With a few images, everything works fine, but with 2300 images, I get the following error:
[1] 12202 bus error node index.js
I have tried to set sharp.cache(false), but that has not worked. Any idea how to solve it? I suppose I'm getting some overflow, but I do not know how to fix it.

Related

How to center continued text using PdfKit?

I have this code:
const PDFDocument = require("pdfkit");
const QRCode = require("qrcode");
const fs = require("fs");
const exec = async () => {
const doc = new PDFDocument({ layout: "landscape" });
doc.pipe(fs.createWriteStream("output.pdf"));
for (let pageNumber = 1; pageNumber <= 1000; pageNumber++) {
const url = await QRCode.toDataURL("I am a url!");
doc
.image(url, 10, 100, {
width: 420,
height: 420,
align: "center",
valign: "center",
})
doc
.font("Helvetica")
.fontSize(50)
.fillColor("#000")
.text(`Item `, 465, 200, { continued: true })
.fontSize(55)
.font("Courier-Bold")
.fillColor("#1b83c5")
.text(`${pageNumber}`);
doc
.font("Helvetica-Bold")
.fontSize(40)
.fillColor("#000")
.text("Order and Pay", 420, 320);
doc.addPage();
}
doc.end();
};
exec();
Which would produce something like this:
It looks centered and all, but as pages increase it will no longer be centered since the numbers are fixed.
I saw in the docs that there's an align property, but the docs didn't explain how to handle continued text.
Any working examples?
Maybe it's a little late, but I found a solution battling with the same problem:
First you need to create a constant with the width of the container you want to center your text in: (this value you have to calculate or invent, but it's easy to do that)
const containerWidth = 100 // as an example
Then, you need to create a variable that contains a plain string that contains all the text you want to center, in your example:
var appendedText = `Item ${pageNumber}`
To finish, you need to use pdf-kit's function: widthOfString, and add the text in the document as follows:
const xOffset = 465 // The original X offset value
doc
.text(`Item `, xOffset + (containerWidth / 2) - (doc.widthOfString(appendedText) / 2), 200, { continued: true })
.text(`${pageNumber}`);
Removed the text styling lines for clarity, but you have to add them later.

Tensorflow js server side classification with mobilenet and blazeface

I'm trying to use tensorflowjs with an already built model, at the beginning I had a problem with blazeface because it didn't find face on photo (that display just faces) and so I'm trying with mobilenet and same probleme the result are non sens. So pretty sur it came from the format of image I'm sending.
So this is my code:
module.exports = {
blazeface: require('#tensorflow-models/blazeface'),
mobilenet: require('#tensorflow-models/mobilenet'),
tf: require("#tensorflow/tfjs-node"),
fs: require("fs"),
sizeOf: require("image-size"),
async structureData(imageLink) {
let data = this.fs.readFileSync(imageLink);//return a buffer
const dimension = await this.sizeOf(imageLink);
const tensorflowImage = {
data: data,
width: dimension.width,
height: dimension.height
};
console.log(tensorflowImage)
return tensorflowImage;
},
async detectFace(imageLink) {
let image = await this.structureData(imageLink);
const model = await this./*blazeface*/mobilenet.load();
const returnTensors = false;
const predictions = await model.classify(image);
console.log(predictions);
}
}
So this code do not result of an error but the result are this =>
[
{
className: 'theater curtain, theatre curtain',
probability: 0.03815646469593048
},
{
className: 'web site, website, internet site, site',
probability: 0.0255243219435215
},
{ className: 'matchstick', probability: 0.02520526386797428 }
]
and with any photo (here it's a banana in white background).
So I'm pretty sur i need to rebuilt the structureData function but I don't know how ...
I also tried this with uint32array
async structureData(imageLink) {
let data = this.fs.readFileSync(imageLink);
data = new Uint32Array(data);
const dimension = await this.sizeOf(imageLink);
const tensorflowImage = {
data: data,
width: dimension.width,
height: dimension.height
};
console.log(tensorflowImage)
return tensorflowImage;
},
But I'm getting this error.
Error: pixels passed to tf.browser.fromPixels() must be either an HTMLVideoElement, HTMLImageElement, HTMLCanvasElement, ImageData in browser, or OffscreenCanvas, ImageData in webworker or {data: Uint32Array, width: number, height: number}, but was Object
remember that i'm using node and so I can't (or don't think I can) us HTMLimageelement
Thanks a lot :)
By using a tensor, a video or image element as parameter to the model, it will be able to do the classification.
let data = this.fs.readFileSync(imageLink);
tensor = tf.node.decodeImage(data, 3)
await model.classify(tensor)

Expiry date of PDFs in Node

I'm trying to generate a PDF with an expiry date (auto expiring after 24 hours).
I have strong experience with pdf-lib, but searching through their repo there is no mention of expiry dates.
I've also found two articles on how to do it in C# and Python:
C#/VB:
https://www.e-iceblue.com/Tutorials/Spire.PDF/Spire.PDF-Program-Guide/Security/How-to-Add-Expiry-Date-to-PDF-Files-in-C-VB.NET.html
https://docs.aspose.com/pdf/java/set-pdf-expiration-in-python/
I'm trying to make a PDF expire on a person's device after they have downloaded it from the server and surprised to see there isn't much support in the node/pdf area.
Any suggestions? Is this possible?
import { PDFDocument, StandardFonts, rgb } from 'pdf-lib'
const pdfDoc = await PDFDocument.create()
const timesRomanFont = await pdfDoc.embedFont(StandardFonts.TimesRoman)
const page = pdfDoc.addPage()
const { width, height } = page.getSize()
const fontSize = 30
page.drawText('Creating PDFs in JavaScript would be great if the PDF had an expiry date!', {
x: 50,
y: height - 4 * fontSize,
size: fontSize,
font: timesRomanFont,
color: rgb(0, 0.53, 0.71),
})
// TODO: add expiry before the save.
const pdfBytes = await pdfDoc.save()
You can use addJavascript method, so your code will look like:
import { PDFDocument, StandardFonts, rgb } from 'pdf-lib'
const pdfDoc = await PDFDocument.create()
const timesRomanFont = await pdfDoc.embedFont(StandardFonts.TimesRoman)
pdfDoc.addJavaScript(
'main',
'var year=2020; var month=11;today = new Date();today = new Date(today.getFullYear(), today.getMonth());expiry = new Date(year, month);if (today.getTime() > expiry.getTime())app.alert("The file is expired. You need a new one.");',
);
const page = pdfDoc.addPage()
const { width, height } = page.getSize()
const fontSize = 30
page.drawText('Creating PDFs in JavaScript would be great if the PDF had an expiry date!', {
x: 50,
y: height - 4 * fontSize,
size: fontSize,
font: timesRomanFont,
color: rgb(0, 0.53, 0.71),
})
const pdfBytes = await pdfDoc.save()
You can more investigate it there https://github.com/Hopding/pdf-lib/commit/30d2aa22c0c0d694189ae3202562d4c0565cce42

Pixi.js v5 - apply alpha to displacement map

I'm scaling a displacement map on click but would like that map to fade away once it reaches almost full scale. The idea is that the filter should be non-existent after a couple of seconds.
const app = new PIXI.Application({
view: document.querySelector("#canvas"),
width: 512,
height: 512
});
const logo = PIXI.Sprite.fromImage("https://unsplash.it/600");
const displacement = PIXI.Sprite.fromImage("https://images.unsplash.com/photo-1541701494587-cb58502866ab?ixlib=rb-1.2.1&ixid=eyJhcHBfaWQiOjEyMDd9&w=1000&q=80");
const filter = new PIXI.filters.DisplacementFilter(displacement);
logo.anchor.set(0.5);
logo.position.set(256);
logo.interactive = true;
displacement.anchor.set(0.5);
displacement.position.set(256);
displacement.scale.set(0.05)
displacement.alpha = 1
app.stage.filterArea = app.screen;
app.stage.filters = [filter];
app.stage.addChild(logo, displacement);
app.ticker.add(function() {
displacement.scale.x += 0.05
displacement.scale.y += 0.05
if (displacement.scale.x > 10) app.ticker.stop()
});
logo.on('mousedown', function() {
displacement.scale.set(0.05)
app.ticker.start()
});
Here's what I have so far:
https://codepen.io/mariojankovic/pen/pojjNae?editors=0111
I've only just started looking at Pixi but I think you want to use the scale property of the displacement filter. This value says how far to shift. Reducing this value to 0 will lessen its effect to none.
https://pixijs.download/dev/docs/PIXI.filters.DisplacementFilter.html
https://pixijs.download/dev/docs/PIXI.filters.DisplacementFilter.html#scale
The way it works is it uses the values of the displacement map to look
up the correct pixels to output. This means it's not technically
moving the original. Instead, it's starting at the output and asking
"which pixel from the original goes here". For example, if a
displacement map pixel has red = 1 and the filter scale is 20, this
filter will output the pixel approximately 20 pixels to the right of
the original.
https://codepen.io/PAEz/pen/BaoREwv
const app = new PIXI.Application({
view: document.querySelector("#canvas"),
width: 512,
height: 512
});
const logo = PIXI.Sprite.fromImage("https://unsplash.it/600");
const displacement = PIXI.Sprite.fromImage(
"https://images.unsplash.com/photo-1541701494587-cb58502866ab?ixlib=rb-1.2.1&ixid=eyJhcHBfaWQiOjEyMDd9&w=1000&q=80"
);
const filter = new PIXI.filters.DisplacementFilter(displacement);
logo.anchor.set(0.5);
logo.position.set(256);
logo.interactive = true;
displacement.anchor.set(0.5);
displacement.position.set(256);
displacement.scale.set(0.0);
displacement.alpha = 1;
app.stage.filterArea = app.screen;
app.stage.filters = [filter];
app.stage.addChild(logo, displacement);
const displacementScaleFrom = 0.05;
const displacementScaleTo = 10 ;
const displacementStep = 0.05;
const filterScaleFrom = 20;// the default value for the filter is 20
const filterStep = filterScaleFrom / ((displacementScaleTo-displacementScaleFrom) / displacementStep);
app.ticker.add(function () {
displacement.scale.x += displacementStep;
displacement.scale.y += displacementStep;
filter.scale.x -= filterStep;
filter.scale.y -= filterStep;
if (displacement.scale.x >= displacementScaleTo) {
app.ticker.stop();
filter.scale.x = 0;
filter.scale.y = 0;
}
});
logo.on("mousedown", function () {
displacement.scale.set(displacementScaleFrom);
filter.scale.x = filterScaleFrom;
filter.scale.y = filterScaleFrom;
app.ticker.start();
});

What to use as inputs in OpenCV calibrateCamera cameraMatrix and distCoeffs parameters?

I'm trying to get calibrateCamera working on my Node.js backend. The library is working fine, but I'm having trouble with the OpenCV functions not giving any error messages if I have faulty inputs. I'm kind of flying in the dark.
But that's beside the point. I've taken 17 images of the chessboard calibration pattern, and got the code to detect the pattern in all of the images. Everything works just fine until I call cv.calibrateCamera(), probably due to me not knowing what I should use as the required inputs for cameraMatrix and distCoeff (4th and 5th input parameters). However, I can't be 100% this is the issue because of not receiving any error messages from errors in the cv... functions.
I tried to follow the example at https://docs.opencv.org/3.1.0/dc/dbb/tutorial_py_calibration.html , but on python in the tutorial you can use None as inputs to cameraMatrix and distCoeff. I tried to use null, but that didn't work either.
Any help would be appreciated.
const size = new cv.Size(9,6);
let mat = null;
let objpt = [];
for(let i=0;i<9;i++) {
for(let j=0;j<6;j++) {
objpt.push(cv.Point(2.5*i,2.5*j,0))
}
}
let objectPoints = [];
let imagePoints =[];
for (let i=0; i < 17;i++) {
mat = cv.imread('./calib/calib'+(i+1)+'.jpg');
let smallmat = mat.resize(756,1008);
const corners = smallmat.findChessboardCorners(size);
if (corners.returnValue) {
objectPoints = objectPoints.concat(objpt);
imagePoints = imagePoints.concat(corners.corners);
}
}
// THIS IS WHERE EXECUTION JUST STOPS WITH NO ERROR MESSAGE
cv.calibrateCamera(
objectPoints,
imagePoints,
new cv.Size(756,1008),
new cv.Mat(3, 3, cv.CV_32FC1,0),
[0,0,0,0,0]
);
According to the test parameters should be passed like this:
[_objectPoints, _objectPoints],
[imagePoints, imagePoints],
imageSize,
_cameraMatrix,
distCoefficients
where
const _cameraMatrix = new cv.Mat([
[800, 0, 100],
[0, 800, 100],
[0, 0, 1]
], cv.CV_64F);
and
const distCoefficients = [0, 0.5, 1.0, 1.0];

Resources