(npm package) gm only edits the last frame of GIF - node.js

I'm trying to overlay text on top of a GIF using the gm package. It does overlay the text on top of regular images, however on GIFs it just overlays the last 2 frames. I don't have much experience using this package and Imagemagick.
Here's the code that edits the image.
gm(request(image)) //any image url
.command('convert')
.coalesce()
.font("./impact.ttf")
.dither(false)
.fontSize(Math.round(width/11)) //Width is defined earlier in the code
.stroke("#000000")
.strokeWidth(width/450)
.out('-gravity', 'north')
.out('-size',width+'x','-fill','white','-background', 'transparent', '0')
.out('caption:' + meme[0].toUpperCase().substr(meme[0].indexOf(" ")+1))
.out('-layers','optimize')
.out('-gravity', 'south')
.out('-size',width+'x','caption:' + meme[1].toUpperCase())
.out('-layers','optimize')
.strip()
// If i use these two, it does append all the layers but the text does not wrap like it does using caption
// .drawText(0,1, meme[0].toUpperCase().substr(meme[0].indexOf(" ") + 1), 'North')
// .drawText(0,0, meme[1].toUpperCase(), 'South')
.stream((error, stdout) => {...}
Result of the code
Any help would be appreciated!

Related

random image coding js

so i made a bot for discord and i want it to show a random image when i type g!guess. so i made it work with
if (message.content === 'g!guess') {
number = 2;
imageNumber = Math.floor (Math.random() * (number - 1 + 1)) + 1;
message.channel.send ( {files: ["./images/" + imageNumber + ".png"]} )
}
it shows a random image, i actually have only 2 images named 1.png and 2.png.
I'd like to make that when a random image is shows if i type its name i get a message, like i have 2 images a space image and a dog, if the dog image appear and i write 'dog' i get a message, and if i type something else nothing happen, if i write g!guess and the space image appear, if i write 'space' i get the message. I'd like it to show an image and that i have like 20 second to guess the name of it, and when the time finish it show a message like 'Time's out'. I hope its understandable.
If I understand you correctly, you're trying to inform the code that 1.png is a dog image whereas 2.png is a space image. It would be easier to guide you with a copy of the code but here's a high-level walkthrough:
I would go about this by adding an alt tag to each image and reference it in the javascript function.
for example:
<img src="src/to/img.png" alt="dog"/>
Here's how to reference the alt tag using javascript: Finding An image tag using the alt text
hth.

How to create zoomable text

I am looking to add zoomable text to the rendered image in OpenSeadragon. The desired functionality is that when you are zoomed out, the text is very small, and as you zoom in, the text increases in size.
I have tried to add text to an overlay div DOM element. This adds text, but as you zoom out, the size of the div gets smaller but the text doesn't. The text gets squeezed to multiple lines.
I use the Render2 class in Angular 7 to manipulate the DOM, but this can be done in any framework/library:
// create the DOM element need for SeaDragon's overlay
let div = this.renderer.createElement('div');
const text = this.renderer.createText(`x: ${xaxis}, y: ${yaxis}`);
// append text to div element
this.renderer.appendChild(div, text);
// add id for Seadragon overlay creation and styling of overlay
this.renderer.setAttribute(div, 'id', overlayname);
this.renderer.setAttribute(div, 'class', 'image-ruler');
// now append the div tag to ViewChild div
this.renderer.appendChild(this.singleOverlay.nativeElement, div);
I expect the text to zoom with the image. Is this possible?
I figured out how to do it. I saw this example that uses an svg plugin so d3 can be used to draw an overlay. After downloading this plugin, I noticed that when I printed text on the screen, it was incredibly large. Too large to read.
As d3 at this zoom level uses the scale of 0-1 for the size of the image, I had to divide the scale by the width of my image.
var p = viewer.viewport.pixelFromPoint(new OpenSeadragon.Point(0, 0), true);
var zoom = viewer.viewport.getZoom(true);
var rotation = viewer.viewport.getRotation();
var imageSize = viewer.world.getItemAt(0).getContentSize();
var scale = viewer.viewport._containerInnerSize.x * zoom / imageSize.x;
g.attr('transform',
'translate(' + p.x + ',' + p.y + ') scale(' + scale + ') rotate(' + rotation + ')');
I then reimplemented the plugin's resize function in my component as not to modify a node module. The result was small text on my enormous image that was readable when you zoom in.

Using rotate for images leads to blank pdf with pdfkit

I have asked the question on the repository directly, but in my experience SO is more reactive.
Hey there,
I am trying to create a pdf from photos using pdfkit.
Depending on whether an image is in landscape or portait mode, I want to turn the image around.
This basically means the following (in typescript) :
function toPostscriptPoint(mm: number) {
return mm * 2.8346456693;
}
const document = new PDFDocument({
size: [toPostscriptPoint(156), toPostscriptPoint(106)],
});
document.pipe(fs.createWriteStream('output.pdf'));
document.save();
document.rotate(90);
document.image(
'photos/sample.jpeg',
{ width: toPostscriptPoint(150), fit: [toPostscriptPoint(150), toPostscriptPoint(100)] });
document.restore();
document.end();
What happens though is that the pdf renders completely white. I do see however that something is happening, because the pdf has the size of the input image.
Is rotation for images not supported? What would be possible alternatives? I would like to avoid having to rewrite my files before putting them in the pdf.
Thanks
Alright, after investigation, I can answer my own question :).
I could see that the images were in the pdf somehow because of the size of the file so I dived deeper.
What happened was that the image was rendered out of the viewport. This was due to multiple things:
By default, the origin of a page after rotation in pdfkit is the center of the page! ( See the doc for more info)
The origin is rotated together with the transformation.
The x and y in the image method are actually inverted.
So after getting all this right, the following code shows the image as expected :
function toPostscriptPoint(mm: number) {
return mm * 2.8346456693;
}
const document = new PDFDocument({
size: [toPostscriptPoint(156), toPostscriptPoint(106)],
});
document.pipe(fs.createWriteStream('output.pdf'));
document.save();
document.rotate(90, {origin : [0, 0]});
document.image(
'photos/sample.jpeg',
toPostscriptPoint(0),
toPostscriptPoint(-150),
{ width: toPostscriptPoint(150), height: toPostscriptPoint(100) });
document.restore();
document.end();
Note the :
origin argument in the rotation
toPostscriptPoint(-150) actually takes into account the position of the origin, and corresponds to the X axis.
Hope that helps some later on :).
Its because taking picture from camera , if picture ISO is less than 100 it will be automatically rotated , take picture with iso more than or equal to 100 to avoid autorotation.

Poor quality jpeg resize on GD library use. Wrong steps?

So I have the following script to resize an incoming jpg and save it to the server in a new size. The created jpg file has terrible quality, even when I am making the quality 90 on the imagejpeg. I am wondering if I am messing it up earlier in my efforts.
// Get new sizes
list($width, $height) = getimagesize($filename);
$percentW=298/$width;
$newwidth = $width * $percentW;
$newheight = $height * $percentW;
// Creating a blank canvas to put the new file. Is this an extra step?
$thumb = imagecreatetruecolor($newwidth, $newheight);
$source = imagecreatefromjpeg($filename);
// Now I create the resized photo with the needed width and height on the blank canvas with the source file resized
imagecopyresampled($thumb, $source, 0, 0, 0, 0, $newwidth, $newheight, $width, $height);
// Output to server, define 90% quality. My guess is the quality is destroyed before now.
imagejpeg($thumb,"../../uploads/buckets/" . $_POST["bucket"] . "/" .$fileNameBucket,90);
imagedestroy($thumb);
Am I messing up the quality before I even output the file to the server? Should I use resample instead of resize? I am stuck with using the GD library so ImageMagick is not an option. Thanks.

How to getPixel using Node.js gm graphicsMagick wrapper

Im currently trying to figure out how to get an individual pixel using the Node.js gm graphicsMagic wrapper. My overall end goal is to get the top 10 colors with percentages in an image. I am trying to write a few functions that will get me my result but for the life of me I can't figure out hwo to get the pixel itself using the gm wrapper. It seems that GraphicsMagick has a GetPixels method but I havent had luck being able to call it. Any help would be greatly appreciated.
Thanks!
I wanted to get the average color of an image and I solved it with the following script:
gm(file).setFormat('ppm')
.resize(1, 1)
.toBuffer(function (err, buffer) {
var color = "rgb(" + buffer.readUInt8(buffer.length - 3)
+ "," + buffer.readUInt8(buffer.length - 2)
+ "," + buffer.readUInt8(buffer.length - 1) + ")";
// ...
});
Basically, you could crop the image and convert it to the ppm format to read the pixels from the buffer. Not optimal at all and I really hope that there is a better solution, but for my case it was good enough.
Edit: Another option might be to use Custom Arguments.

Resources