Mask text with imagick php - 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;
?>

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);

ImageMagick PHP - Distort text and annotate on image

Is it possible to distort a text and annotate it on an image with ImageMagick (PHP)? Or do I have to create an image from the text, distort it and then paste it on my base image?
I have a coffee mug and want to add text. I want to add a slight arc to my text to have a threedimensional look on my mug.
I tried around with arched font:
http://www.imagemagick.org/Usage/fonts/#arch
But in my code example I cannot get it to work because the text is $draw = new ImagickDraw(); and I cannot distort it or use arched font. I always end up with my whole image being distorted because the distortion only works on images like $image = new Imagick('original/'.$id.'.jpg')
Any hints or advice is greatly apprciated. I need a font with a little concave arch like in this example here:
http://www.imagemagick.org/discourse-server/viewtopic.php?t=13901
I cannot get this to work in PHP.
$fontpath = 'fonts/';
$id = $_REQUEST["id"];
$text1 = $_REQUEST['text1'];
$text2 = $_REQUEST['text2'];
$fontname1 = $_REQUEST['fontname1'];
$fontname2 = $_REQUEST['fontname2'];
$x_coordinate1 = $_REQUEST['x_coordinate1'];
$x_coordinate2 = $_REQUEST['x_coordinate2'];
$y_coordinate1 = $_REQUEST['y_coordinate1'];
$y_coordinate2 = $_REQUEST['y_coordinate2'];
$pointsize1 = $_REQUEST['pointsize1'];
$pointsize2 = $_REQUEST['pointsize2'];
$fill1 = $_REQUEST['fill1'];
$fill2 = $_REQUEST['fill2'];
$stroke1 = $_REQUEST['stroke1'];
$stroke2 = $_REQUEST['stroke2'];
/* Create some objects */
//$image = new Imagick();
$draw = new ImagickDraw();
/* New image */
$image = new Imagick('original/'.$id.'.jpg');
/* Text color */
$draw->setFillColor($fill1);
/* Font properties */
$draw->setFont($fontpath.$fontname1);
$draw->setFontSize( $pointsize1 );
/* Create text */
/* Center is important */
$draw->setGravity (Imagick::GRAVITY_CENTER);
$image->annotateImage($draw, $x_coordinate1, $y_coordinate1, 0, $text1);
/* Text2 color */
$draw->setFillColor($fill2);
/* Font2 properties */
$draw->setFont($fontpath.$fontname2);
$draw->setFontSize( $pointsize2 );
$draw->setGravity (Imagick::GRAVITY_CENTER);
$image->annotateImage($draw, $x_coordinate2, $y_coordinate2, 0, $text2);
/* Give image a format */
$image->setImageFormat('jpg');
/* Output the image with headers */
header('Content-type: image/jpg');
echo $image;
The comment from fmw42 worked best for my problem. I created text as an image with transparent background then distorted and finally composited on another image.

Imagemagick background gradient

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;

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.

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