Issues writing text to an image with PHP ImageMagick - php

I have attempted to create a png with imagemagick with the following code.
<?php
/* Create some objects */
$image = new Imagick();
$draw = new ImagickDraw();
$pixel = new ImagickPixel( 'gray' );
/* New image */
$image->newImage(800, 75, $pixel);
/* Black text */
$draw->setFillColor('black');
/* Font properties */
$draw->setFont('Oxin_free_promo.ttf');
$draw->setFontSize( 30 );
/* Create text */
$image->annotateImage($draw, 10, 45, 0, 'The quick brown fox jumps over the lazy dog');
/* Give image a format */
$image->setImageFormat('png');
/* Output the image with headers */
header('Content-type: image/png');
echo $image;
But I keep getting the errors below. /usr/local/zend/tmp/ is chmod'd to be 777 and owned by daemon:zend and magick-* doesnt exist. Any ideas?
httpd: FreeType library is not available `/Users/gareth.williams/Sites/_tests/texttoimg/Oxin_free_promo.ttf'.
httpd: Postscript delegate failed `/usr/local/zend/tmp/magick-tmfNBDIx': No such file or directory.
PHP Fatal error: Uncaught exception 'ImagickException' with message 'Unable to annotate image'

Look at the error messages given, it says the problem right there.
"FreeType library is not available" - ImageMagick uses the FreeType library to render fonts, you have given it a TTF to use, and it says FreeType is not installed, so it can not use the font. Install FreeType, then reinstall/recompile ImageMagick to get FreeType support.
The second error is probably ImageMagick trying to fallback to rendering the font using its postscript rasterisation support, usually this is via ghostscript (gs), hence "Postscript delegate failed". Either ghostscript is not available, or the path for the temporary file it asks ghostscript to render too/from is not writable. Could be fixed by installing ghostscript and making sure that temporary directory has full write access, as people mention in the comments to the question.
To confirm these causes, use the -list option of convert.
convert -list format : This will show you the supported file types, look for TTF, make sure it has at least r-- status, it should say something like "TTF* TTF r-- TrueType font (Freetype 2.2.1)" if FreeType is installed correctly.
convert -list delegate : This will show handling of delegated types and the command line used. It will be using one of the ps converters as a fallback.
As I say, easiest fix is to install FreeType, then recompile/reinstall ImageMagick.

Related

Getting error message on Cpanel using Imagick

I am using Imagick to edit and save svg image.
I am getting an error when I save svg image after having croped it.
Here is my code to operate svg images:
$image = new Imagick();
$image->readImage($path1);
$image -> cropImage($rw*11.2, $sw*7.7, 0, 0);
$image->writeImage('Cvilogpdfbackend/core/images/tempimage/'.$targetfile.'.svg');
When i call this function, I am getting bellow error
PHP Fatal error: Uncaught ImagickException: delegate failed
`'potrace' --svg --output '%o' '%i'' #
error/delegate.c/InvokeDelegate/1897 in
/home/civilogc/public_html/resizeimage.php:19 Stack trace:
#0 /home/civilogc/public_html/resizeimage.php(19): Imagick->writeimage('Cvilogpdfbacken...')
#1 {main} thrown in /home/civilogc/public_html/resizeimage.php on line 19
How to solve this issue?
Why would you want to use mainly bitmap/raster based image processing library (ImageMagick) to modify vector SVG images?
Let me first point you to do the right way:
ImageMagick should be mostly used for reading and writing bitmap images and for creating/writing SVG images (and other vector based format if required, e.g. EPS, PDF etc).
Instead of using ImageMagick/Imagick for your conversion (changing vector image to bitmap and back again - losing quality) just read your image for example with this code:
$image = file_get_contents($path1);
$svg_dom = new DOMDocument();
$tmp_obj = $svg_dom->getElementsByTagName("svg")->item(0);
$svg_width = floatval($tmp_obj->getAttribute("width"));
$svg_height = floatval($tmp_obj->getAttribute("height"));
$svg_viewbox = floatval($tmp_obj->getAttribute("vieWBox"));
and then I suggest you just calculate the new viewBox with your cropping adjustment (create a function for that) and set it back, optionally set new width and height as well:
$svg_viewBox = calculateCroppedView($svg_viewbox, $new_width, $new_height, $top, $left);
$tmp_obj->setAttribute("viewBox", $svg_viewBox);
$tmp_obj->setAttribute("width", $new_width."px");
$tmp_obj->setAttribute("height", $new_height."px");
file_put_contents('Cvilogpdfbackend/core/images/tempimage/'.$targetfile.'.svg', $svg_dom->saveXML());
Note: you are not really cropping the SVG image (SVG elements), just changing the view (e.g. zoom) to it. Converting all cut paths, shapes, text etc is possible but would require a lot of coding. Either way the goal is to keep the (vector) image quality.
For an excellent explanation of the SVG viewBox attribute read this section:
https://css-tricks.com/scale-svg/#the-viewbox-attribute
To answer your question:
This error states that ImageMagick in your webserver cannot find or doesn't have installed the (free) potrace software that does the actual vectorization of a bitmap image.
Note: you need to have ImageMagick version 7 since older version just embedded bitmap images and data encoded (base64) string to the SVG image tag or maybe used a weird conversion - depending of ImageMagick version - of converting dots to 1px SVG circle tags. And ImageMagick installed needs to be the same version as Imagick as well for the mentioned reasons.
Potrace software command line is set in delegates.xml of the ImageMagick/Imagick installation and ImageMagick or Imagick needs to find potrace in the PATH (environment variable).
I suggest you to contact your web hosting provider to install Potrace that can be downloaded here:
http://potrace.sourceforge.net/#downloading
And then you'll have to test your script, most likely your web hosting provider will already solve the issue just by installing Potrace. Maybe a path to it will need to be added to a user/system PATH variable and that should practically solve your issue.
If not, you can try to use ImageMagick (convert or now renamed magick, main program) and potrace using exec() command in PHP yet your web hosting must allow that since it's usually forbidden in PHP configuration.
To go for other help:
Well, ask a question here on SO or on ImageMagick support forum that based on their main site forum (where you cannot register anymore) is now here:
https://github.com/ImageMagick/ImageMagick/discussions

DOMPDF images have poor quality when processing in server

I am working on a website with different jQuery forms that output to a html result page, this html is converted to a pdf file with DOMPDF library. When the conversion is made in local, there is no problem, but when it takes place in the server, the resulting pdf images have lower quality than the originals, with white scratches and blur (I can upload an example if necessary).
Doing some research, I tried the following solutions:
- tried different image formats (jpg, png, gif)
- tried different values for "DOMPDF_PDF_BACKEND" (rendering backend to use) (CPDF, PDFLib, GD)
- tried different "DOMPDF_DPI" values
- "DOMPDF_ENABLE_REMOTE" value is set to "true"
- tried opening the resulting pdf with different applications (ubuntu pdf viewer, adobe acrobat pdf, gimp, photoshop)
all with the same result.
Also took a look at phpinfo() both in local and server:
PHP version
local: PHP Version 5.5.11
server: PHP Version 5.3.29
GD version:
both: bundled (2.1.0 compatible)
GD FreeType Version :
local: 2.4.8
version: 2.4.9
libPNG Version:
local: 1.5.9
server: 1.2.49
I don't know what other parameters to compare.
I don't know what else to try.
Thanks in advance.
Thanks for the anwswer, I saw that post yesterday, I had tried different image formats, but I had pending playing with the libraries.
Finally, commenting out the code regarding the imagick image processing "// Use PECL imagick + ImageMagic to process transparent PNG images" solved the problem, that was due to images containing transparencies (alpha) such as png and gif.
// Use PECL imagick + ImageMagic to process transparent PNG images
}elseif (extension_loaded("imagick")) {
$imagick = new Imagick($file);
$imagick->setFormat('png');
// Get opacity channel (negative of alpha channel)
$alpha_channel = clone $imagick;
$alpha_channel->separateImageChannel(Imagick::CHANNEL_ALPHA);
$alpha_channel->negateImage(true);
$alpha_channel->writeImage($tempfile_alpha);
// Cast to 8bit+palette
$imgalpha_ = imagecreatefrompng($tempfile_alpha);
imagecopy($imgalpha, $imgalpha_, 0, 0, 0, 0, $wpx, $hpx);
imagedestroy($imgalpha_);
imagepng($imgalpha, $tempfile_alpha);
// Make opaque image
$color_channels = new Imagick();
$color_channels->newImage($wpx, $hpx, "#FFFFFF", "png");
$color_channels->compositeImage($imagick, Imagick::COMPOSITE_COPYRED, 0, 0);
$color_channels->compositeImage($imagick, Imagick::COMPOSITE_COPYGREEN, 0, 0);
$color_channels->compositeImage($imagick, Imagick::COMPOSITE_COPYBLUE, 0, 0);
$color_channels->writeImage($tempfile_plain);
$imgplain = imagecreatefrompng($tempfile_plain);
}
Then it would use the "}else{" option that extracts the image without alpha channel.
You can also disable imagick module in the php.ini

PHP Image Processing GD JPEG Quality

I started using the WideImage image processing library and I'm having a problem with the quality of the JPEG images it's generating. WideImage actually uses GD, so I'm testing just using the GD PHP image functions.
My aim is ultimately to resize images, but here's my test code with no resizing taking place:
$srcImage = "path/to/image.jpg";
list($width, $height) = getimagesize($srcImage);
$image_p = imagecreatetruecolor($width, $height);
$image = imagecreatefromjpeg($srcImage);
imagecopyresampled($image_p, $image, 0, 0, 0, 0, $width, $height, $width, $height);
imagejpg($image_p, "path/to/image_resized.jpg", 100);
This works, but outputs a lower quality more washed out version of the original image.
Here is an example next to the original split down the center:
This happens when I do perform a resize also, but I want to maintain the same colours/quality of the original image.
Has anyone got any ideas as to how I can achieve this? Is there perhaps a setting in my php.ini that I am missing or something? I also tried using imagepng() but with much the same results.
I'm using PHP Version 5.3.29, here is my GD info from phpinfo():
GD Support : enabled
GD Version : bundled (2.1.0 compatible)
FreeType Support : enabled
FreeType Linkage : with freetype
FreeType Version : 2.3.11
T1Lib Support : enabled
GIF Read Support : enabled
GIF Create Support: enabled
JPEG Support : enabled
libJPEG Version : 6b
PNG Support : enabled
libPNG Version : 1.2.49
WBMP Support : enabled
XPM Support : enabled
libXpm Version : 30411
XBM Support : enabled
Thanks!
At squeamish ossifrage's request, here is the original file and the converted file.
EDIT - as per the squeamish ossifrage's answer marked correct below, I took the following steps to solve the issue:
Installed exiftool on the server
Generated the following command with PHP:
exiftool -TagsFromFile "/var/www/vhosts/path/to/image/the file name.jpg" -icc_profile "/var/www/vhosts/path/to/image-processed/the file name.jpg"
Ran the command with PHP's exec() method:
$arrOutput = array();
$return_var = "";
$directOutput = exec($exiftoolCommand, $arrOutput, $return_var);
Worked like a charm!
The original image contains an ICC colour profile. GD doesn't know anything about colour profiles, so this information is missing from the converted file. To fix this problem, you basically have two options:
Save the original file without a colour profile, or
Copy the colour profile from the original file to the converted file.
I'd go with option 1 if you're planning to publish this file on the web, as colour profiles and other EXIF information use up bandwidth for no good reason.
Alternatively, you can use a free tool like exiftool to copy the colour profile from one file to the other. This should work on the command line:
exiftool -TagsFromFile so_original.jpg -icc_profile so_converted.jpg

How do I set a font in Imagick PHP?

I can't seem to get Imagick::setFont to work in php. Taking the example straight from the man page:
/* Create new imagick object */
$im = new Imagick();
/* Set the font for the object */
$im->setFont("comic.ttf");
/* Create new caption */
$im->newPseudoImage(100, 100, "caption:Hello");
$im->setformat('png');
header('Content-type: image/png');
echo $im;
I get...
http://i53.tinypic.com/2d2bn9x.png
... which is clearly not comic sans. I've tried numerous fonts. It never changes. It does complain if the file doesn't exist. It does not accept names like "Arial".
When you're using setFont method you need to make sure you pass absolute path of the font:
$im->setFont("/var/www/html/mysite/media/fonts/myCustomFont.ttf");
Same would apply for your localhost development just change the absolute path.
(This is a bit old question but I figured to answer it anyways.)
I'm having the same situation here and I found this post
http://www.imagemagick.org/discourse-server/viewtopic.php?f=10&t=11937
They say Freetype library should be installed, but haven't tried yet.
UPDATE
Finally I had chance to try it and It worked.
I use
ImageMagick 6.7.6
Imagick 3.0
Freetype 2.4.9
Freetype-devel 2.3.11
Fontconfig-devel 2.8
PHP 5.3.13

PHP JPEG Functions Not Working

Any PHP functions that deal with JPEGs don't seem to be working on my server.
This code:
<?php
$im = imagecreatetruecolor(120, 20);
$text_color = imagecolorallocate($im, 233, 14, 91);
imagestring($im, 1, 5, 5, 'A Simple Text String', $text_color);
header('Content-type: image/jpeg');
imagejpeg($im);
imagedestroy($im);
?>
creates an empty file.
Using a GIF or PNG function will create an image containing the text "A Simple Text String" as expected.
This:
$im = imagecreatefromjpeg("test.jpg");
returns
Warning: imagecreatefromjpeg() [function.imagecreatefromjpeg]: 'test.jpg' is not a valid JPEG file in /path/to/test.php on line 2
A phpinfo() shows:
gd
GD Support enabled
GD Version 2.0 or higher
FreeType Support enabled
FreeType Linkage with freetype
FreeType Version 2.3.9
T1Lib Support enabled
GIF Read Support enabled
GIF Create Support enabled
JPG Support enabled
PNG Support enabled
WBMP Support enabled
And the webserver can read any relevant files.
GIF and PNG functions work fine, and as expected.
Any ideas?
EDIT:
Found this in my Apache error log file:
gd-jpeg: JPEG library reports unrecoverable error: Wrong JPEG library version: library is 80, caller expects 62
Your error log clearly shows that your PHP is compiled against/requires libjpeg version 62, while the library on your server is version 80.
Either install the correct version of libjpeg, or recompile gd/php.
It appears that the file test.jpg doesn't exist, or isn't the correct filetype headers (eg, if someone renames a test.png as test.jpg it will still have the .png headers). Try creating a new test.jpg file using an image editing program and see if it works.
An answer that worked for me was to work around the image altogether and trearit as a string.
Ill try to do it the standard way, but if it doesnt work, try it as a string
$src = imagecreatefromjpeg($file);
if (!$src) {
$src = imagecreatefromstring(file_get_contents($file));
}
There are apparently some issue wilth older versions or combos of GD an PHP.
In my case I had an image using a newer version/compression of jpeg 7 I think.

Categories