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;
}
}
?>
Related
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);
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.
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;
I am using PHP GD library to flip an image and then save that flipped image. However I am able to flip image successfully but I don’t know how to save it with another name in a folder. My code is
$filename = '324234234234.jpg';
header('Content-type: image/jpeg');
$im = imagecreatefromjpeg($filename);
imageflip($im, IMG_FLIP_VERTICAL);
imagejpeg($im);
You need to pass a second parameter to imagejpeg($im) call with the path to the file you want to store.
imagejpeg($im, 'path/to/new/file.jpg');
http://php.net/manual/en/function.imagejpeg.php
Look at the documentation for imagejpeg where it explains the second parameter relates to $filename:
bool imagejpeg ( resource $image [, string $filename [, int $quality ]] )
The path to save the file to. If not set or NULL, the raw image stream will be outputted directly.
So just add the new filename as a second parameter like this; assuming the name of the new name is new_filename.jpg. Also comment out or completely remove the header line so you are not outputting the image to the browser, but rather saving it to a file so the header isn’t needed:
$filename = '324234234234.jpg';
// header('Content-type: image/jpeg');
$im = imagecreatefromjpeg($filename);
imageflip($im, IMG_FLIP_VERTICAL);
imagejpeg($im, 'new_filename.jpg');
Also note that while imageflip is nice to use it is only available in PHP 5.5 & higher; it won’t be available in PHP 5.4 or lower:
(PHP 5 >= 5.5.0)
image flip — Flips an image using a given mode
So if you want to use it in PHP 5.4 or lower, you need to create the logic to flip it on your own in the code or use a function like this. It only flips horizontally so you would have to adjust it to flip vertically, but posting here so you have something to explore & work with if needed:
/**
* Flip (mirror) an image left to right.
*
* #param image resource
* #param x int
* #param y int
* #param width int
* #param height int
* #return bool
* #require PHP 3.0.7 (function_exists), GD1
*/
function imageflip(&$image, $x = 0, $y = 0, $width = null, $height = null)
{
if ($width < 1) $width = imagesx($image);
if ($height < 1) $height = imagesy($image);
// Truecolor provides better results, if possible.
if (function_exists('imageistruecolor') && imageistruecolor($image))
{
$tmp = imagecreatetruecolor(1, $height);
}
else
{
$tmp = imagecreate(1, $height);
}
$x2 = $x + $width - 1;
for ($i = (int) floor(($width - 1) / 2); $i >= 0; $i--)
{
// Backup right stripe.
imagecopy($tmp, $image, 0, 0, $x2 - $i, $y, 1, $height);
// Copy left stripe to the right.
imagecopy($image, $image, $x2 - $i, $y, $x + $i, $y, 1, $height);
// Copy backuped right stripe to the left.
imagecopy($image, $tmp, $x + $i, $y, 0, 0, 1, $height);
}
imagedestroy($tmp);
return true;
}
I have some images that are pulled from a server and $imgUrl holds the path of the image.
Right now I use <img src="<?php echo $imgUrl ?>" width="100" height="200"/> or CSS to scale down the image, but I want to do it in PHP so that I will serve already scaled images to the DOM
Any ideas?
Thanks
This solution will cause the thumb to be created when it is requested for the first time. All future requests will fetch the already created thumb. It is using ImageMagick:
HTML:
<img src="script.php?img=example" />
PHP (script.php):
$width = 140;
$height = 80;
$image = $_GET['img'];
$ext = 'png';
// Check if file exists
if ( ! file_exists('/path/to/the/'.$image.'.'.$ext))
{
die('Unable to process the requested file.');
}
// Check if a thumb already exists, otherwise create a thumb
if (file_exists('/path/to/the/'.$image.'_thumb.'.$ext))
{
$img = new imagick('/path/to/the/'.$image.'_thumb.'.$ext);
}
else
{
$img = new imagick('/path/to/the/'.$image.'.'.$ext);
$img->setImageFormat($ext);
$img->scaleImage($width, 0);
$img->cropImage($width, $height, 0, 0);
$img->writeImage('/path/to/the/'.$image.'_thumb.'.$ext);
}
// Return as an image
header('Content-Type: image/'.$ext);
echo $img;
You should create a smaller version and save it to a folder. Then you don't need to rezise them on every request (it's memory intensive). Use Gd or ImageMagick for resize.
Example with GD
Be aware that doing this in PHP will mean a memory intensive process either every time the image is accessed (if done on the fly) or when the image is saved (which means you'll be using more storage to save the converted images). If you're still sure this is something you need/want then look into using GD. See this answer for an idea or how to do this: Image GD resize to 100px while keep the ratio
Here is what I am using atm. Feel free to extract you needs:
Usage:
<CLASS>::scale_image($dir.$name, 1024, 768, $dir.'thumb_'.$name);
/**
* Most simple way to get File Extension
* #param string $path Local path to File
* #return string Extension in lower case
*/
public static function extension($path){
return strtolower(pathinfo($path, PATHINFO_EXTENSION));
}
/**
* Rename Filename for more secure usage
* #param string $name filename
* #return string more secure filename
*/
public static function secure_name($name){
return urlencode(preg_replace('/[^a-z0-9 \-_\.]/i', '_', strtolower($name)));
}
/**
* Scale Image without ratio changes
* #param int $sw source width of orig image
* #param int $sh source height of orig image
* #param int $tw max target width
* #param int $th max target height
* #return array list($width, $height)
*/
public static function scale($sw, $sh, $tw, $th){
if ($sw > $tw && $sw/$tw > $sh/$th) {
$tw = $sw * ($tw / $sw);
$th = $sh * ($tw / $sw);
}else if ($sh > $th) {
$tw = $sw * ($th / $sh);
$th = $sh * ($th / $sh);
}else{
$th = $sh;
$tw = $sw;
}
return array(round($tw), round($th));
}
/**
* Scale Image
* #param string $sPath
* #param int $width max width
* #param int $height max height
* #param string $tPath Optional Path for Thumbnail
* #param int $thumbScale Scale ratio for optional Thumbnail (Width and Height / $thumbScale)
* #return void
*/
public static function scale_image($sPath, $width, $height, $tPath = NULL, $thumbScale = 10){
if(!function_exists('imagecreatetruecolor')){
return;
}
$ext = strtolower(self::extension($sPath));
if($ext == 'jpg' or $ext == 'jpeg'){
$src = imagecreatefromjpeg($sPath);
}elseif($ext == 'png'){
$src = imagecreatefrompng($sPath);
}elseif($ext == 'gif'){
$src = imagecreatefromgif($sPath);
}else{
return;
}
list($sw, $sh) = getimagesize($sPath);
list($tw, $th) = File::scale($sw, $sh, $width, $height);
$trg = imagecreatetruecolor($tw, $th);
imagecopyresampled($trg, $src, 0, 0, 0, 0, $tw, $th, $sw, $sh);
imagejpeg($trg, $sPath, 90);
if($tPath){
$tw = (int)$tw / $thumbScale;
$th = (int)$th / $thumbScale;
$trg = imagecreatetruecolor($tw, $th);
imagecopyresampled($trg, $src, 0, 0, 0, 0, $tw, $th, $sw, $sh);
imagejpeg($trg, $tPath, 90);
}
}