Using clone instead of created temp images

Questions and postings pertaining to the usage of ImageMagick regardless of the interface. This includes the command-line utilities, as well as the C and C++ APIs. Usage questions are like "How do I use ImageMagick to create drop shadows?".
Post Reply
Defacta
Posts: 12
Joined: 2017-04-19T03:48:21-07:00
Authentication code: 1151

Using clone instead of created temp images

Post by Defacta »

Hello,

I am new to Imagemagick, just installed it yesterday and I find it a little bit complicated. :)

I have cut with Gimp a frame into 8 pieces :
- top-left.png
- top-middle.png
- top-right.png
- right-middle.png
- bottom-right.png
- bottom-middle.png
- bottom-left.png
- left-middle.png
You may find them here to test the code I share: http://www.cjoint.com/doc/17_04/GDtsbdUYPze_frames.zip

The source image:
Image
The result of my Imagemagick script:
Image

It's working fine, but I generate 18 images to achieve this result, the PHP Code with exe() :

Code: Select all

$timeStart = microtime(TRUE);

$maxSize = 1000;
$imageSrc = 'images/image1.jpg';

$sizeTopLeft = getimagesize('frames/top-left.png');
$sizeTopRight = getimagesize('frames/top-right.png');
$sizeBottomLeft = getimagesize('frames/bottom-left.png');
$sizeBottomRight = getimagesize('frames/bottom-right.png');

$sizeImage = getimagesize($imageSrc);
if($sizeImage[0] >= $sizeImage[1]) {
    $widthFramedImage = $maxSize;
    $widthImage = ($widthFramedImage - $sizeTopLeft[0] - $sizeTopRight[0]);
    $heightImage = intval(($widthImage * $sizeImage[1]) / $sizeImage[0]);
    $heightFramedImage = $heightImage + $sizeTopLeft[1] + $sizeBottomLeft[1];
} else {
    $heightFramedImage = $maxSize;
    $heightImage = ($heightFramedImage - $sizeTopLeft[1] - $sizeTopRight[1]) + 1;
    $widthImage = intval(($heightImage * $sizeImage[0]) / $sizeImage[1]);
    $widthFramedImage = $widthImage + $sizeTopLeft[0] + $sizeBottomLeft[0];
}

echo "$widthFramedImage / $heightFramedImage <hr>";

exec("convert $imageSrc -resize ".$widthImage."x".$heightImage." target-image.png");
echo '<img src="target-image.png"><hr>';

exec("convert -size ".$widthFramedImage."x".$heightFramedImage." xc:white 1.png");

/**
 *  Add top Left
 */
exec("convert 1.png frames/top-left.png -geometry +0+0 -composite 2.png");
echo '<img src="2.png"><hr>';

/**
 *  Add top Right
 */
$x = $widthFramedImage - $sizeTopRight[0];
exec("convert 2.png  frames/top-right.png -geometry +$x+0 -composite 3.png");
echo '<img src="3.png"><hr>';

/**
 *  Add Bottom Right
 */
$x = $widthFramedImage - $sizeBottomRight[0];
$y = $heightFramedImage - $sizeBottomRight[1];
exec("convert 3.png  frames/bottom-right.png -geometry +$x+$y -composite 4.png");
echo '<img src="4.png"><hr>';

/**
 *  Add Bottom Left
 */
$y = $heightFramedImage - $sizeBottomLeft[1];
exec("convert 4.png  frames/bottom-left.png -geometry +0+$y -composite 5.png");
echo '<img src="5.png"><hr>';

/**
 *  Pattern Right with tile:
 */
$heightPattern = $heightFramedImage - ($sizeTopRight[1] + $sizeBottomRight[1]);
$x = $widthFramedImage - $sizeTopRight[0];
$y = $sizeTopRight[1];
exec("convert -size ".$sizeTopRight[0]."x".$heightPattern." tile:frames/right-middle.png pattern-right.png");
echo '<img src="pattern-right.png"><hr>';
exec("convert 5.png pattern-right.png -geometry +$x+$y -composite 6.png");
echo '<img src="6.png"><hr>';

/**
 *  Pattern Bottom with tile:
 */
$widthPattern = $widthFramedImage - ($sizeBottomLeft[0] + $sizeBottomRight[0]);
$y = $heightFramedImage - ($sizeBottomLeft[1]);
exec("convert -size ".$widthPattern."x".$sizeBottomLeft[1]." tile:frames/bottom-middle.png 0x0 pattern-bottom.png");
echo '<img src="pattern-bottom.png"><hr>';
exec("convert 6.png pattern-bottom.png -geometry +$sizeBottomLeft[0]+$y -composite 7.png");
echo '<img src="7.png"><hr>';

/**
 *  Adding the picture inside the Frame before the shadows...
 */
$x = $sizeTopLeft[0];
$y = $sizeTopLeft[1];
exec("convert 7.png  target-image.png -geometry +$x+$y -composite 8.png");
echo '<img src="8.png"><hr>';

/**
 *  Pattern Top with Shadow using tile:
 */
$widthPattern = $widthFramedImage - ($sizeTopLeft[0] + $sizeTopRight[0]);
exec("convert -size ".$widthPattern."x".$sizeTopLeft[1]." tile:frames/top-middle.png pattern-top.png");
exec("convert pattern-top.png ( -clone 0 -background black -shadow 40x6+0+15 ) -reverse -background none -layers merge +repage pattern-top-shadow.png");
$sizePatternTop = getimagesize("pattern-top.png");
$sizePatternTopShadow = getimagesize("pattern-top-shadow.png");
$widthCrop = intval( ($sizePatternTopShadow[0] - $sizePatternTop[0])/2);
exec("convert pattern-top-shadow.png -crop ".$sizePatternTop[0]."x".$sizePatternTopShadow[1]."+$widthCrop+0 pattern-top-shadow-cropped.png");

echo "Pattern Sizes/Pattern Shadow Sizes : <br>$sizePatternTop[0] / $sizePatternTopShadow[0] <br> $sizePatternTop[1] / $sizePatternTopShadow[1] <br>";
echo '<img src="pattern-top-shadow-cropped.png"><hr>';
exec("convert 8.png pattern-top-shadow-cropped.png -geometry +$sizeTopLeft[0]+0 -composite 9.png");
echo '<img src="9.png"><hr>';

/**
 *  Pattern Left with Shadow using tile:
 */
$heightPattern = $heightFramedImage - ($sizeTopLeft[1] + $sizeBottomLeft[1]);
$y = $sizeTopRight[1];
exec("convert -size ".$sizeTopRight[0]."x".$heightPattern." tile:frames/left-middle.png pattern-left.png");
exec("convert pattern-left.png ( -clone 0 -background black -shadow 40x6+15+0 ) -reverse -background none -layers merge +repage pattern-left-shadow.png");
$sizePatternLeft = getimagesize("pattern-left.png");
$sizePatternLeftShadow = getimagesize("pattern-left-shadow.png");
$heightCrop = intval( ($sizePatternLeftShadow[1] - $sizePatternLeft[1])/2);
exec("convert pattern-left-shadow.png -crop ".$sizePatternLeftShadow[0]."x".$sizePatternLeft[1]."+0+$heightCrop pattern-left-shadow-cropped.png");

echo '<img src="pattern-left-shadow.png"><hr>';
exec("convert 9.png pattern-left-shadow-cropped.png -geometry +0+$y -composite 10.jpg");
echo '<img src="10.jpg" style="margin:50px; box-shadow: 8px 8px 20px #404040;"><hr>';

$timeEnd = microtime(TRUE);
$timeTaken = $timeEnd - $timeStart;
$time_taken = round($timeTaken,5);
echo 'Image generated in '.$timeTaken.' seconds.';
How to use clone to avoid creating so many temp png images ? I know I used clone to generate the Left and Top Pattern with shadow but it was a copy/paste which I didn't really understand :?

You may find test images I used here: http://www.cjoint.com/doc/17_04/GDtsneVNIAe_images.zip

Many thanks
snibgo
Posts: 12159
Joined: 2010-01-23T23:01:33-07:00
Authentication code: 1151
Location: England, UK

Re: Using clone instead of created temp images

Post by snibgo »

Untangling your code isn't easy, but you seem to have one convert per operation. For example:

Code: Select all

exec("convert -size ".$widthFramedImage."x".$heightFramedImage." xc:white 1.png");

exec("convert 1.png frames/top-left.png -geometry +0+0 -composite 2.png");
You don't need 1.png. So you can simply combine these two commands:

Code: Select all

exec("convert -size ".$widthFramedImage."x".$heightFramedImage." xc:white 
frames/top-left.png -geometry +0+0 -composite 2.png");
"-geometry +0+0" is superfluous here, so can be removed.
snibgo's IM pages: im.snibgo.com
User avatar
fmw42
Posts: 25562
Joined: 2007-07-02T17:14:51-07:00
Authentication code: 1152
Location: Sunnyvale, California, USA

Re: Using clone instead of created temp images

Post by fmw42 »

No clones are needed. You only need to use parenthesis processing. See http://www.imagemagick.org/Usage/basics/#parenthesis


Try this (unix syntax)

Code: Select all

infile="image1.jpg"
ww=`convert -ping $infile -format "%w" info:`
hh=`convert -ping $infile -format "%h" info:`
convert \
\( top-left.png \( top-middle.png -scale ${ww}x! \) top-right.png +append \) \
\( \( left-middle.png -scale x${hh}! \) $infile \( right-middle.png -scale x${hh}! \) +append \) \
\( bottom-left.png \( bottom-middle.png -scale ${ww}x! \) bottom-right.png +append \) \
-append result.jpg
Note above I have used newline \ characters to make it more readable, but you probably want the convert to be on long line for PHP exec(). So

Code: Select all

infile="image1.jpg"

Code: Select all

ww=`convert -ping $infile -format "%w" info:`

Code: Select all

hh=`convert -ping $infile -format "%h" info:`

Code: Select all

convert \( top-left.png \( top-middle.png -scale ${ww}x! \) top-right.png +append \) \( \( left-middle.png -scale x${hh}! \) $infile \( right-middle.png -scale x${hh}! \) +append \) \( bottom-left.png \( bottom-middle.png -scale ${ww}x! \) bottom-right.png +append \) -append result.jpg
Also see other techniques for framing at http://www.imagemagick.org/Usage/thumbnails/#frame_edge.

For novices, see

viewtopic.php?f=1&t=9620
http://www.imagemagick.org/script/comma ... essing.php
http://www.imagemagick.org/Usage/reference.html
http://www.imagemagick.org/Usage/
Defacta
Posts: 12
Joined: 2017-04-19T03:48:21-07:00
Authentication code: 1151

Re: Using clone instead of created temp images

Post by Defacta »

Thanks for your help,
I thought I can't do what I did with php Imagick but apparently each step I did is possible through php Imagick objects.
Defacta
Posts: 12
Joined: 2017-04-19T03:48:21-07:00
Authentication code: 1151

Re: Using clone instead of created temp images

Post by Defacta »

Ok, much more rapid without creating any temp image it generates frames in less than 1 sec.

I didn't get the shadow I wish on the top left. I have to check how to cover the white corner :
Image

Here is the code, maybe it will help someone:

Code: Select all

$timeStart = microtime(TRUE);

$maxSize = 1000;
$imageSrc = 'images/image1.jpg';
$frameSrc = 'frames';

$sizeTopLeft = getimagesize("frames/top-left.png");
$sizeTopRight = getimagesize("frames/top-right.png");
$sizeBottomLeft = getimagesize("frames/bottom-left.png");
$sizeBottomRight = getimagesize("frames/bottom-right.png");

$sizeImage = getimagesize($imageSrc);
if($sizeImage[0] >= $sizeImage[1]) {
    $widthFramedImage = $maxSize;
    $widthImage = ($widthFramedImage - $sizeTopLeft[0] - $sizeTopRight[0]);
    $heightImage = intval(($widthImage * $sizeImage[1]) / $sizeImage[0]);
    $heightFramedImage = $heightImage + $sizeTopLeft[1] + $sizeBottomLeft[1];
} else {
    $heightFramedImage = $maxSize;
    $heightImage = ($heightFramedImage - $sizeTopLeft[1] - $sizeTopRight[1]) + 1;
    $widthImage = intval(($heightImage * $sizeImage[0]) / $sizeImage[1]);
    $widthFramedImage = $widthImage + $sizeTopLeft[0] + $sizeBottomLeft[0];
}

echo "$widthFramedImage / $heightFramedImage <hr>";

$im = new Imagick();
$im->newImage($widthFramedImage, $heightFramedImage, new ImagickPixel('white'));
$im->setImageFormat('jpg');

/**
 *  Add top Left
 */
$topLeft = new Imagick();
$topLeft->readImage(getcwd()."/frames/top-left.png");
$im->compositeImage($topLeft, imagick::COMPOSITE_OVER, 0, 0);
$topLeft->destroy();

/**
 *  Add top Right
 */
$x = $widthFramedImage - $sizeTopRight[0];
$topRight = new Imagick();
$topRight->readImage(getcwd()."/frames/top-right.png");
$im->compositeImage($topRight, imagick::COMPOSITE_OVER, $x, 0);
$topRight->destroy();

/**
 *  Add Bottom Right
 */
$x = $widthFramedImage - $sizeBottomRight[0];
$y = $heightFramedImage - $sizeBottomRight[1];
$bottomRight = new Imagick();
$bottomRight->readImage(getcwd()."/frames/bottom-right.png");
$im->compositeImage($bottomRight, imagick::COMPOSITE_OVER, $x, $y);
$bottomRight->destroy();

/**
 *  Add Bottom Left
 */
$y = $heightFramedImage - $sizeBottomLeft[1];
$bottomLeft = new Imagick();
$bottomLeft->readImage(getcwd()."/frames/bottom-left.png");
$im->compositeImage($bottomLeft, imagick::COMPOSITE_OVER, 0, $y);
$bottomLeft->destroy();

/**
 *  Pattern Right using Crop:
 */
$rightMiddle = new Imagick();
$rightMiddle->readImage(getcwd()."/frames/right-middle.png");
$heightPattern = $heightFramedImage - ($sizeTopRight[1] + $sizeBottomRight[1]);
$rightMiddle->cropImage($sizeTopRight[0], $heightPattern, 0, 0);
$x = $widthFramedImage - $sizeTopRight[0];
$y = $sizeTopRight[1];
$im->compositeImage($rightMiddle, imagick::COMPOSITE_OVER, $x, $y);
$rightMiddle->destroy();

/**
 *  Pattern Bottom using Crop:
 */
$bottomMiddle = new Imagick();
$bottomMiddle->readImage(getcwd()."/frames/bottom-middle.png");
$widthPattern = $widthFramedImage - ($sizeBottomLeft[0] + $sizeBottomRight[0]);
$bottomMiddle->cropImage($widthPattern, $sizeBottomLeft[1], 0, 0);
$x = $sizeTopLeft[0];
$y = $heightFramedImage - $sizeBottomLeft[1];
$im->compositeImage($bottomMiddle, imagick::COMPOSITE_OVER, $x, $y);
$bottomMiddle->destroy();

/**
 *  Adding the picture inside the Frame before the shadows...
 */
$imSrc = new Imagick();
$imSrc->readImage(getcwd()."/".$imageSrc);
$imSrc->resizeImage($widthImage, $heightImage, imagick::FILTER_POINT,1);
$x = $sizeTopLeft[0];
$y = $sizeTopLeft[1];
$im->compositeImage($imSrc, imagick::COMPOSITE_OVER, $x, $y);


/**
 *  Pattern Top with shadow using Crop:
 */
$topMiddle = new Imagick();
$topMiddle->readImage(getcwd()."/frames/top-middle.png");
$shadow = $topMiddle->clone();
$shadow->setImageBackgroundColor( new ImagickPixel( 'black' ) );
$shadow->shadowImage( 40, 5, 0, 40); 
$shadow->compositeImage($topMiddle, Imagick::COMPOSITE_OVER, 0, 0 );
$widthPattern = $widthFramedImage - ($sizeTopLeft[0] + $sizeTopRight[0]);
$shadow->setImagePage($widthPattern, $shadow->getImageHeight(), 0, 0);
$shadow->cropImage($widthPattern, $shadow->getImageHeight(), 0, 0);
$im->compositeImage($shadow, imagick::COMPOSITE_OVER, $sizeTopLeft[0], 0);
$topMiddle->destroy();
$shadow->destroy();

/**
 *  Pattern Left with Shadow using Crop:
 */
$leftMiddle = new Imagick();
$leftMiddle->readImage(getcwd()."/frames/left-middle.png");
$shadow = $leftMiddle->clone();
$shadow->setImageBackgroundColor( new ImagickPixel( 'black' ) );
$shadow->shadowImage( 40, 5, 0, 40); 
$shadow->compositeImage($leftMiddle, Imagick::COMPOSITE_OVER, 0, 0 );
$heightPattern = $heightFramedImage - ($sizeTopLeft[1] + $sizeBottomLeft[1]);
$shadow->setImagePage($shadow->getImageWidth(), $heightPattern, 0, 0);
$shadow->cropImage($shadow->getImageWidth(), $heightPattern, 0, 0);
$im->compositeImage($shadow, imagick::COMPOSITE_OVER, 0, $sizeTopLeft[1]);
$shadow->destroy();

$im->writeImage(getcwd().'/10.jpg');
$im->destroy();

echo '<img src="10.jpg" style="margin:50px; box-shadow: 8px 8px 20px #404040;"><hr>';

$timeEnd = microtime(TRUE);
$timeTaken = $timeEnd - $timeStart;
$time_taken = round($timeTaken,5);
echo 'Image generated in '.$timeTaken.' seconds.';
Post Reply