Imagemagick background gradient - php

I've got some basic code working to generate an image with a solid background. However I was wondering how I can make a gradient. This is my code:
<?php
function process($inputdata)
{
/* Create some objects */
$image = new Imagick();
$draw = new ImagickDraw();
$pixel = new ImagickPixel( 'gray' );
/* New image */
$image->newImage(400, 300, $pixel);
/* Black text */
$draw->setFillColor('black');
/* Font properties */
$draw->setFont('Bookman-DemiItalic');
$draw->setFontSize( 30 );
/* Create text */
$image->annotateImage($draw, 10, 45, 0, $inputdata);
/* Give image a format */
$image->setImageFormat('png');
/* Output the image with headers */
header('Content-type: image/png');
echo $image;
return;
}
The closest code I could find is something like this:
$gradient = new Imagick();
$gradient->newPseudoImage(400, 300, 'gradient:blue-red');
But I don't know how I then combine the gradient with the text.

Please use compositeImage function. It combine one image into another. Create one Imagick instance with gradient, second one with text and alpha channel background, and combine them into the one.
Reference: http://php.net/manual/en/imagick.compositeimage.php
$text = 'The quick brown fox jumps over the lazy dog';
$width = 1000;
$height = 1000;
$textBackground = new ImagickPixel('transparent');
$textColor = new ImagickPixel('#000');
$gradient = new Imagick();
$gradient->newPseudoImage($width, $height, 'gradient:blue-red');
$image = new Imagick();
$image->newImage($width, $height, $textBackground);
$gradient->setImageColorspace($image->getImageColorspace());
$draw = new ImagickDraw();
$draw->setFillColor($textColor);
$draw->setFontSize( 10 );
$image->annotateImage($draw, 10, 45, 0, $text);
$gradient->compositeImage($image, Imagick::COMPOSITE_MATHEMATICS, 0, 0);
$gradient->setImageFormat('png');
header('Content-type: image/png');
echo $image;

Related

PHP imagick COMPOSITE_DSTIN result has black background

I try to set a text gradient from this solution here https://www.sitepoint.com/community/t/gd-text-gradient/82127/9
But the background color of the final image is black, I try $im->flattenImages and $img->setBackgroundColor but it's not working.
$im = new Imagick();
$draw = new ImagickDraw();
$draw->setFontSize(90);
$draw->setFillColor(new ImagickPixel("black"));
$draw->setTextEncoding('UTF-8');
$draw->setGravity(Imagick::GRAVITY_CENTER);
$metric = $im->queryFontMetrics($draw, $text);
$width = $metric['textWidth'];
$height = $metric['textHeight'];
/* Create and save the gradiant */
$Imagick = new Imagick();
$Imagick->newPseudoImage($height, $width, "gradient:#FB7F4C-#FF409C");
/*** rotate the image ***/
$Imagick->rotateImage(new ImagickPixel(), 270);
$Imagick->setImageFormat('png');
$Imagick->writeImage("gradiant.png");
/* Create and save the canvas */
$im->newPseudoImage($width, $height, "null:");
$im->setImageFormat('png');
$im->writeImage("canvas.png");
/* Add the text to the canvas ( Make the mask )*/
$im = new Imagick("canvas.png");
// Write the text on the image
$im->annotateImage($draw, 0, 0, 0, $text);
$im->setImageBackgroundColor("transparent"); // <= Here
/* Final image */
$canvas = new Imagick("gradiant.png");
$canvas->compositeImage($im, imagick::COMPOSITE_DSTIN, 0, 0, Imagick::CHANNEL_ALPHA);
$canvas->setImageFormat('png');
$canvas->writeImage(__DIR__ . "/../../final.png");
header('Content-Type: image/' . $im->getImageFormat());
echo $canvas;
unlink("canvas.png");
unlink("gradiant.png");
I found after the COMPOSITE_DSTIN the background color goes black, I try many way but its not working
How to remove black background?
I'm solved it by adding alphachannel
I try $canvas->setImageAlphaChannel(Imagick::ALPHACHANNEL_RESET); and after that the background stay transparent
UPDATE
After I updated my imagick library it's stop working and search for similar issue and found this Imagemagick compose image inverted
And here the code that works well
$canvas->transformImageColorspace(Imagick::COLORSPACE_SRGB);

Imagick not working and showing null image

I am using shared hosting and extensions is installed too, the following code not working and just showing blank image in output I have tried many of code/function of Imagick all of codes showing the following image.
Please help me out.
<?php
ini_set('display_errors', 1);
ini_set('display_startup_errors', 1);
error_reporting(E_ALL);
// Create objects
$image = new Imagick('image.png');
$watermark = new Imagick();
$mask = new Imagick();
$draw = new ImagickDraw();
// Define dimensions
$width = $image->getImageWidth();
$height = $image->getImageHeight();
// Create some palettes
$watermark->newImage($width, $height, new ImagickPixel('grey30'));
$mask->newImage($width, $height, new ImagickPixel('black'));
// Watermark text
$text = 'Copyright';
// Set font properties
$draw->setFont('arial.ttf');
$draw->setFontSize(20);
$draw->setFillColor('grey70');
// Position text at the bottom right of the image
$draw->setGravity(Imagick::GRAVITY_SOUTHEAST);
// Draw text on the watermark palette
$watermark->annotateImage($draw, 10, 12, 0, $text);
// Draw text on the mask palette
$draw->setFillColor('white');
$mask->annotateImage($draw, 11, 13, 0, $text);
$mask->annotateImage($draw, 10, 12, 0, $text);
$draw->setFillColor('black');
$mask->annotateImage($draw, 9, 11, 0, $text);
// This is needed for the mask to work
$mask->setImageMatte(false);
// Apply mask to watermark
$watermark->compositeImage($mask, Imagick::COMPOSITE_COPYOPACITY, 0, 0);
// Overlay watermark on image
$image->compositeImage($watermark, Imagick::COMPOSITE_DISSOLVE, 0, 0);
// Set output image format
$image->setImageFormat('png');
// Output the new image
header('Content-type: image/png');
echo $image;

Annotate an image twice

I annotate an image using Imagick:
$image = new Imagick('image.jpg');
$draw = new ImagickDraw();
$draw->setFillColor('#ffffff');
$draw->setFont('fonts/opensans-regular.ttf');
$draw->setFontSize(40);
$image->annotateImage($draw, 20, 100, 0, 'The quick fox jumps over the lazy dog');
$image->setImageFormat('png');
header('Content-type: image/png');
echo $image;
How can i Use annotateImage() twice in order to insert to text elements with different positions? When I just copy the draw paragraph, the last use isn't visible. Do I have to save the image and edit it again or exists a way to do it on the fly? Thanks in advance.
Update:
Just adding a second ImagickDraw() doesn't work, it is not visible.
$image = new Imagick('image.jpg');
//first
$draw = new ImagickDraw();
$draw->setFillColor('#ffffff');
$draw->setFont('fonts/opensans-regular.ttf');
$draw->setFontSize(40);
$image->annotateImage($draw, 20, 100, 0, 'The quick fox jumps over the lazy dog');
//second
$draw2 = new ImagickDraw();
$draw2->setFillColor('red');
$draw2->setFont('fonts/opensans-regular.ttf');
$draw2->setFontSize(40);
$image->annotateImage($draw2, 20, 800, 0, 'The quick fox jumps over the lazy dog');
$image->setImageFormat('png');
header('Content-type: image/png');
echo $image;
Here is an example of a 2nd annotation that you can add to the image.
<?php
$image = new Imagick();
$draw = new ImagickDraw();
$pixel = new ImagickPixel( 'white' );
$image->newImage(800, 75, $pixel);
$draw->setFillColor('black');
$draw->setFont('Bookman-DemiItalic');
$draw->setFontSize( 30 );
$image->annotateImage($draw, 10, 25, 0, '1st line of annotation text here');
$image->annotateImage($draw, 10, 60, 0, '2nd line of annotation text here');
$image->setImageFormat('png');
header('Content-type: image/png');
echo $image;
Based on the x,y coordinates you can add annotations where you like. Just remember that they can overlap and over each other.

Mask text with imagick php

The following code is a very basic example of imagick's Imagick::annotateImage() function. How would I go about masking the top half of the text while retaining the background image?
<?php
/* Create some objects */
$image = new Imagick('bg.jpg');
$draw = new ImagickDraw();
$pixel = new ImagickPixel( 'transparent' );
/* New image */
$image->newImage(800, 75, $pixel);
/* Black text */
$draw->setFillColor('black');
/* Font properties */
$draw->setFont('Bookman-DemiItalic');
$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;
?>

Generate dummy images local via CLI

I need to generate some (thousands) dummy images local to test a CLI based content converter. The file names are set.
A name list as example:
fw4df.jpg
antotherName.jpg
and so on.
I would write a script using ImageMagick extension to create those images with some dummy content.
Any suggestion to solve this more clever?
I would do this for 1,000 images:
head -1000 /path/to/your/word/list |
while read word; do \
echo -n $word | convert label:#- "$word.jpg" \
done
You get
ImageMagick ships with some built in images. The most common ones are wizard:, rose:, and logo:
convert wizard: wizard.jpg
convert rose: rose.jpg
convert logo: logo.jpg
Edit
If you just want a clever PHP function, I would continue to use PseudoImages to simplify everything.
function createPseudoImage($label_text, $width, $height, $label_format='No. %d') {
$background = new Imagick;
$background->newPseudoImage($width, $height, 'PATTERN:HORIZONTALSAW');
$label = new Imagick();
$label->setBackgroundColor('transparent');
$label_width = $background->getImageWidth() * 0.8;
$label_height = $background->getImageHeight() * 0.8;
$label_text = sprintf('CAPTION:'.$label_format, $label_text);
$label->newPseudoImage($label_width, $label_height, $label_text);
$offset_x = $background->getImageWidth()/2 - $label->getImageWidth()/2;
$offset_y = $background->getImageHeight()/2 - $label->getImageHeight()/2;
$background->compositeImage($label, Imagick::COMPOSITE_ATOP, $offset_x, $offset_y);
return $background;
}
$fpo = createPseudoImage(49, 500, 200);
$fpo->writeImage('/tmp/out.png');
But YMMV
I wrote a script based on the PHP doc example. Perhaps it will help someone:
<?php
generateDummyImages(array("test.jpg", "test2.jpg"));
/**
*
* #param array $files
* #param string $dataOutPath
*/
function generateDummyImages($files, $dataOutPath = "") {
$width = 500;
$height = 500;
$imageCompressionQuality = 90;
foreach($files as $i => $filename) {
/* Create a new imagick object */
$im = new Imagick();
/* Create new image. This will be used as fill pattern */
$im->newPseudoImage($width, $height, "gradient:red-black");
/* Create imagickdraw object */
$draw = new ImagickDraw();
/* Start a new pattern called "gradient" */
$draw->pushPattern('typo', 0, 0, $width, $height);
/* Composite the gradient on the pattern */
$draw->composite(Imagick::COMPOSITE_OVER, 0, 0, $width, $height, $im);
/* Close the pattern */
$draw->popPattern();
/* Use the pattern called "gradient" as the fill */
$draw->setFillPatternURL('#typo');
/* Set font size to 52 */
$draw->setFontSize(100);
/* Annotate some text */
$draw->annotation($width / 2 - 100, $height / 2, "No. " . $i);
/* Create a new canvas object and a white image */
$canvas = new Imagick();
$canvas->newImage($width, $height, "white");
/* Draw the ImagickDraw on to the canvas */
$canvas->drawImage($draw);
/* 1px black border around the image */
$canvas->borderImage('black', 1, 1);
/* Set the format to PNG */
$canvas->setImageFormat('jpg');
$canvas->setImageCompression(Imagick::COMPRESSION_JPEG);
$canvas->setCompressionQuality($imageCompressionQuality);
/* Output the image */
$canvas->writeimage($dataOutPath . $filename);
echo "Image generated: " . $dataOutPath . $filename . PHP_EOL;
}
}
?>

Categories