PHP Imagick don't use custom font > convert does - php

It's driving me insane.. Just searched for hours to find a solution. But nothing really found. So hopefully anyone can help me.
I'm trying to create an customized image on the fly. I use this to create the images: https://github.com/Treinetic/ImageArtist
Everything works fine except the font. This is the snippet from the class:
$im = new \Imagick();
$background = new \ImagickPixel('none');
$im->setBackgroundColor($background);
$im->setFont($font->getPath());
$im->setPointSize($writer->getSize() * (0.75));
$im->setGravity(\Imagick::GRAVITY_EAST); //later we will have to change this
$width = $writer->getWidth();
$height = $writer->getHeight();
$text = $writer->getText();
$margin = $writer->getMargin();
$im->newPseudoImage($width, $height, "pango:" . $text );
$clut = new \Imagick();
$clut->newImage(2, 2, new \ImagickPixel($color->toString()));
$im->clutImage($clut);
$clut->destroy();
$im->setImageFormat("png");
$image = imagecreatefromstring($im->getImageBlob());
$template = $this->imageHelper->createTransparentTemplate($width+ (2*$margin),$height+ (2 *$margin));
$img = new Image($template);
$text = new Image($image);
imagedestroy($image);
imagedestroy($template);
return $img->merge($text,$margin,$margin);
The $font-getPath(); looks correct and echo /var/www/vhosts/example.com/dev-test/ImageArtist/src/lib/AssetManager/../../resources/Fonts/Gotham-Light.ttf
This is the full code
use Treinetic\ImageArtist\lib\PolygonShape;
use Treinetic\ImageArtist\lib\Text\TextBox;
use Treinetic\ImageArtist\lib\Text\Color;
use Treinetic\ImageArtist\lib\Text\Font;
use Treinetic\ImageArtist\lib\Overlays\Overlay;
use Treinetic\ImageArtist\lib\Image;
require('../vendor/autoload.php');
$main_image = new Image("ranks/main-image.png");
$textBox = new TextBox(720,40);
$textBox->setColor(new Color(0,0,0, 125));
$textBox->setFont(Font::getFont('./Gotham-Light.ttf'));
$textBox->setSize(42);
$textBox->setMargin(0);
$textBox->setText($_GET["name"]);
$main_image->setTextBox($textBox, 40, 620);
$main_image->save("./newImage.png",IMAGETYPE_PNG);
But the font specified is not used by Imagick. If i try to create an image from den command line via
convert -font /var/www/vhosts/example.com/dev-test/ImageArtist/src/lib/AssetManager/../../resources/Fonts/Gotham-Light.ttf -pointsize 72 label:Test test.gif
And... The Font is used on command line created image :/ The font file is reachable and readable via php but not used via Imagick ....
Does anyone has an idea why php imagick can't use my font but convert -font can?
The script is running on PHP-FPM 7.0.23 on an dedicated root server with nginx as an RPS.
Hope you can help me out.. It really drives me crazy :)
Thanks
Stanlay
SOLVED
Found out that $im->newPseudoImage($width, $height, "pango:" . $text ); cause the issue. Switching to $im->newPseudoImage($width, $height, "caption:" . $text ); and everything works fine.

Related

get and set image dpi

I need some info about images inside cardimg folder.
$arr = glob("../cardimg/*.jpg");
foreach ($arr as $item){
list($width, $height) = getimagesize($item);
echo $width . '<br>';
echo $height . '<br>';
}
Works fine for width and height, but don't know how to see if an image is 72 or 300 dpi?
my php is 7.0.20 and using
print_r(imageresolution($item));
result is error - Call to undefined function
Also is there a way to change 300dpi to 72dpi using php?
This is straight from PHP.net for imageresolution(). (PHP 7 >= 7.2.0)
<?php
$im = imagecreatetruecolor(100, 100);
print_r(imageresolution($im));
imageresolution($im, 300, 72);
print_r(imageresolution($im));
?>
This should get you what you need once you update your php version:
$im = imagecreatefromstring(file_get_contents($path));
print_r(imageresolution($im));
imagedestroy($im);
Here is a link on how to get gd library up and going.. I'm sure this varies on server setup hosted or not, I don't know. But should help I imagine.
Enable GD support in PHP

php imagick convert pdf to png high quality

I'm trying to convert a PDF to a high quality PNG via Imagick, but the file keeps coming out fuzzy. Currently, I'm running the following options but can't find the right flags to get a clear PNG out of the conversion. The original PDF file is 8.5 x 11. Suggestions? Thanks!
$image = new \Imagick(storage_path('app/'.$path));
$image->setResolution( 200, 200 );
$image->scaleImage(1700,2200);
$image->setImageFormat( "png32" );
$image->writeImage(storage_path('app/'.$split[0].'.png'));
You need to set the resolution before reading the image because the image is rasterised when read, so it doesn't help to set the resolution afterwards - it's too late!
Try along these lines:
$imagick = new Imagick();
$imagick->setResolution(288,288);
$imagick->readImage('someFile.pdf');
$imagick_i = new Imagick();
$imagick_i->setResolution( 595, 842 );
$imagick_i->readImageblob($blob);
$imagick_i->setImageFormat( "png32" );
foreach ($imagick_i as $auxiliaryvalue) {
echo '<img src="data:image/png;base64,' . base64_encode($auxiliaryvalue->getimageblob()) . '" /><br>';
}

Merging animated Gif into background image

I'm trying to merge an animated gif into a static jpeg as a background, this is being generated by html canvas and a file upload that the user uploads. I had it working great with imagemagick command line
exec("convert ".$_paths['images_dir'].$fname.".gif \( gif/cleared_dance".$dance.".gif -resize '80%' -repage 0x0-10+$imgHeight\! \) -coalesce -delete 0 -deconstruct -loop 0 ".$_paths['images_dir'].$fname.".gif");
this was taking about 15~ seconds to process which was acceptable, but then I found out I can't use the exec command and must use Imagick API, I was eventually able to recreate the process using the following code:
$data = $_POST["imgData"];
$dance = $_POST["dancer"]+1;
$spriteLeft = $_POST['left'];
$spriteTop = $_POST['top'];
$scale = $_POST['scale'];
$canvas = new Imagick();
$data = str_replace("data:image/png;base64,", "",$data);
$data = base64_decode($data);
$canvas->readImageBlob($data);
$fname = 'tmp_'.uniqid();
$gif = new Imagick();
$gif->readImage('gif/cleared_dance'.$dance.'.gif');
do {
$canvas->addImage($gif);
} while ($gif->nextImage());
foreach($canvas as $frame){
if($frame->getIteratorIndex() != 0){
$page = $frame->getImagePage();
$frame->setImagePage(200,200,$page['x']+$spriteLeft,$page['y']+$spriteTop);
}
}
This code takes about 5 seconds which is great but their is a blank frame in the gif when it loops that was super annoying so i added this after:
$canvas->setIteratorIndex(0);
$canvas->removeImage();
$canvas = $canvas->deconstructImages();
$canvas->writeImages('tmp/'.$fname.'.gif', true);
This takes out the blank frame, but adds about 20 - 30 seconds of processing. Am I doing something wrong, I've played around a good bit with the order of the code and trying different approaches. Is there a way to get the processing time back under 20 seconds like it was with the command line?
Your code is quite odd. Why are you setting the format of the Imagick object that is going to contain an animated gif to JPG? Why are you fiddling with the image page after you composited the image?
I'm pretty sure you want your code to look a lot more like
$static = new Imagick();
//$static->readImage("./testFile.png");
$inputGif->readImageBlob($data);
$inputGif = new Imagick();
//$inputGif->readImage('./testGif.gif');
$inputGif->readImage('gif/cleared_dance'.$dance.'.gif');
$gifFrames = $inputGif->coalesceImages();
$outputGif = new Imagick();
$outputGif->setFormat('gif');
foreach ($gifFrames as $gifFrame) {
$frame = clone $static;
$frame->compositeimage(
$gifFrame,
Imagick::COMPOSITE_OVER, // or maybe \Imagick::COMPOSITE_ATOP,
0, 0 // Set the offset here if you don't want the gif in the top left corner.
);
$outputGif->addImage($frame);
}
$outputGif->setImageIterations(0); //loop forever
$outputGif->deconstructImages();
$outputGif->writeImages("./outso.gif", true);

Imagine with Yii, issue with palette / color

I installed Yii and Imagine with composer and tried to use imagine.
the issue is when i try to use this code from the imagine website introduction i got an error 500 :
Argument 2 passed to Imagine\Gd\Imagine::create() must be an instance of Imagine\Image\Color, instance of Imagine\Image\Palette\Color\RGB given
code:
use Imagine\Image\Box;
$imagine = new Imagine\Gd\Imagine();
$palette = new Imagine\Image\Palette\RGB();
$size = new Box(400, 300);
$color = $palette->color('#000', 100);
$image = $imagine->create($size, $color);
$image->save('images/test.png');
when i edit this line :
$image = $imagine->create($size, $color);
with
$image = $imagine->create($size);
the picture is created white so i guess Imagine is working
Did i miss something ? Do i have to change something in the config or something else ?
Any idea will be much appreciated
Thanks

circularize an image with imagick

Trying to take a rectangular photo, crop it into a square region, and then mask it into a circular with a transparent background.
//$dims is an array with the width, height, x, y of the region in the rectangular image (whose path on disk is $tempfile)
$circle = new \Imagick();
$circle->newImage($dims['w'], $dims['h'], 'none');
$circle->setimageformat('png');
$circle->setimagematte(true);
$draw = new \ImagickDraw();
$draw->setfillcolor('#ffffff');
$draw->circle($dims['w']/2, $dims['h']/2, $dims['w']/2, $dims['w']);
$circle->drawimage($draw);
$imagick = new \Imagick();
$imagick->readImage($tempfile);
$imagick->setImageFormat( "png" );
$imagick->setimagematte(true);
$imagick->cropimage($dims['w'], $dims['h'], $dims['x'], $dims['y']);
$imagick->compositeimage($circle, \Imagick::COMPOSITE_DSTIN, 0, 0);
$imagick->writeImage($tempfile);
$imagick->destroy();
The result is the rectangular image, uncropped and without being circularized. What am I doing wrong?
Example image:
Example input for $dims = {"x":253,"y":0,"x2":438.5,"y2":185.5,"w":185.5,"h":185.5}
Rough expected output:
Image i'm getting looks roughly like the input image.
For those with an older version of Imagick (setimagematte does not exist in version lower than 6.2.9), I came up with an easy solution. The thing here is to copy opacity from the mask to the original image.
Original Image:
Mask:
Result:
The code:
$base = new Imagick('original.jpg');
$mask = new Imagick('mask.png');
$base->compositeImage($mask, Imagick::COMPOSITE_COPYOPACITY, 0, 0);
$base->writeImage('result.png');
You could use an Imagick black circle as mask but I though it wasn't perfect so I used my own.
Of course you will certainly have to resize / crop your images but that's another story.
Hope this helps.
J.
This works for me:
<?php
//$dims is an array with the width, height, x, y of the region in the rectangular image (whose path on disk is $tempfile)
$tempfile = 'VDSlU.jpg';
$outfile = 'blah.png';
$circle = new Imagick();
$circle->newImage(185.5, 185.5, 'none');
$circle->setimageformat('png');
$circle->setimagematte(true);
$draw = new ImagickDraw();
$draw->setfillcolor('#ffffff');
$draw->circle(185.5/2, 185.5/2, 185.5/2, 185.5);
$circle->drawimage($draw);
$imagick = new Imagick();
$imagick->readImage($tempfile);
$imagick->setImageFormat( "png" );
$imagick->setimagematte(true);
$imagick->cropimage(185.5, 185.5, 253, 0);
$imagick->compositeimage($circle, Imagick::COMPOSITE_DSTIN, 0, 0);
$imagick->writeImage($outfile);
$imagick->destroy();
?>
<img src="blah.png">
I always try to keep the code simple until I get it working and then add all the variables etc. That could be the problem or there could be a problem with your version of Imagick.
It's namespaced
Still do not know what it means! - I am getting a bit behind with php as I do not use it very much these days.
There's also another workaround that I suggest here :
// create an imagick object of your image
$image = new \Imagick('/absolute/path/to/your/image');
// crop square your image from its center (100px witdh/height in my example)
$image->cropThumbnailImage(100, 100);
// then round the corners (0.5x the width and height)
$image->roundCorners(50, 50);
// force the png format for transparency
$image->setImageFormat("png");
// write the new image
$image->writeImage('/absolute/path/to/your/new/image');
// done!
Many thanks to all previous answers and contributors that lead me to this code!
Feel free to test/comment my solution!
I stumbled upon this as I was searching for a similar solution for Ruby on Rails, notice that this Stackoverflow question uses vignette instead which seems to be a much simpler way to solve the problem.
I used vignette to solve my problem with rounded images in Ruby on Rails using Dragonfly.

Categories