Merge two images / replicating Photoshop's "resize canvas"?
Merge two images / replicating Photoshop's "resize canvas"?
Hi,
First of all, is there any built in function that does a similar job to Photoshop's resize canvas tool. i.e. It takes a width, height, and location (south west, south...north...center etc.) and crops/increases the height and with of the images "canvas", without scaling the actual image?
I couldn't find one, so decided to write my own, but I can't work out how to do it. I think setImageExtent can be used to increase the canvas (that right?), however it doesn't allow you to set where the original image should be positioned in the new size.
So instead I've tried to create a new image which is the target size, and then somehow copy the original into that, but I can't find the method for copying one image into another (and specifying the location). Any ideas?
Thanks,
Jack
EDIT:
With thanks to mkoppanen, the extentImage method has now been added to IMagick. This makes is easy to resize the image "canvas". For anyone after a method that auto calculates the x and y based on a gravity constant (like Photoshop does) check out my function here: viewtopic.php?p=30475#p30475
First of all, is there any built in function that does a similar job to Photoshop's resize canvas tool. i.e. It takes a width, height, and location (south west, south...north...center etc.) and crops/increases the height and with of the images "canvas", without scaling the actual image?
I couldn't find one, so decided to write my own, but I can't work out how to do it. I think setImageExtent can be used to increase the canvas (that right?), however it doesn't allow you to set where the original image should be positioned in the new size.
So instead I've tried to create a new image which is the target size, and then somehow copy the original into that, but I can't find the method for copying one image into another (and specifying the location). Any ideas?
Thanks,
Jack
EDIT:
With thanks to mkoppanen, the extentImage method has now been added to IMagick. This makes is easy to resize the image "canvas". For anyone after a method that auto calculates the x and y based on a gravity constant (like Photoshop does) check out my function here: viewtopic.php?p=30475#p30475
Last edited by Jack-S on 2007-10-01T08:49:04-07:00, edited 1 time in total.
Re: Merge two images / replicating Photoshop's "resize canvas"?
OK, I figured out one way to do it, but there could be a better way. Any guidance on this would be great:
P.S. Any ideas where I can get a win32 2.0.0rc4 dll for PHP 5.2.4?
Edit: Hmmmm, I really need to find a better way to do this. This function is REALLY slow, especially on large images.
Code: Select all
class Jack_Imagick extends Imagick
{
public function resizeCanvasImage($widthB, $heightB, $gravity, ImagickPixel $backgroundColor = null)
{
$widthA = $this->getImageWidth();
$heightA = $this->getImageHeight();
switch ($gravity) {
case Imagick::GRAVITY_CENTER:
$x = floor(($widthB - $widthA) / 2);
$y = floor(($heightB - $heightA) / 2);
break;
// ...
default:
// error
break;
}
$draw = new ImagickDraw();
$draw->setFillColor((isset($backgroundColor)) ? $backgroundColor : $this->getImageBackgroundColor());
$draw->rectangle(0, 0, $widthB, $heightB);
$draw->composite(Imagick::COMPOSITE_OVER, $x, $y, $widthA, $heightA, $this);
$this->setImageExtent($widthB, $heightB);
$this->drawImage($draw);
}
}
Edit: Hmmmm, I really need to find a better way to do this. This function is REALLY slow, especially on large images.
Re: Merge two images / replicating Photoshop's "resize canvas"?
OK, I've tried another approach now, which is a lot faster. Again, any advice on the best way to do this is appreciated.
Code: Select all
public function resizeCanvasImage($widthB, $heightB, $gravity = Imagick::GRAVITY_CENTER, ImagickPixel $backgroundColor = null)
{
$widthA = $this->getImageWidth();
$heightA = $this->getImageHeight();
switch ($gravity) {
case Imagick::GRAVITY_CENTER:
$x = floor(($widthB - $widthA) / 2);
$y = floor(($heightB - $heightA) / 2);
break;
// @todo
default:
throw new Jack_Imagick_Exception("Gravity setting '$gravity' unknown");
break;
}
if ($x > 0) {
$this->setImageExtent($widthB, $heightA);
$this->rollImage($x, 0);
} else {
$this->rollImage($x, 0);
$this->setImageExtent($widthB, $heightA);
}
if ($y > 0) {
$this->setImageExtent($widthB, $heightB);
$this->rollImage(0, $y);
} else {
$this->rollImage(0, $y);
$this->setImageExtent($widthB, $heightB);
}
}
Re: Merge two images / replicating Photoshop's "resize canvas"?
The latter way looks pretty good to me. My assumption is that that is the closest you get to resize canvas. If I understood the "resize canvas" correctly.
Mikko Koppanen
My blog: http://valokuva.org
My blog: http://valokuva.org
Re: Merge two images / replicating Photoshop's "resize canvas"?
Great thanks.
There is still one problem though. When setImageExtent increases the image size the additional space is filled with black. How can I change this colour? I though setImageBackgroundColor would do it, but it doesn't work. Any ideas? I'm using 2.0.0rc1 presently.
There is still one problem though. When setImageExtent increases the image size the additional space is filled with black. How can I change this colour? I though setImageBackgroundColor would do it, but it doesn't work. Any ideas? I'm using 2.0.0rc1 presently.
Re: Merge two images / replicating Photoshop's "resize canvas"?
Jack-S wrote:Great thanks.
There is still one problem though. When setImageExtent increases the image size the additional space is filled with black. How can I change this colour? I though setImageBackgroundColor would do it, but it doesn't work. Any ideas? I'm using 2.0.0rc1 presently.
What is the image format? If you set transparent on jpeg image I think that is shown as black.
Try with png image and use:
Code: Select all
$im->setImageMatte( true );
$im->setImageBackgroundColor( new ImagickPixel( "transparent" ) );
Mikko Koppanen
My blog: http://valokuva.org
My blog: http://valokuva.org
Re: Merge two images / replicating Photoshop's "resize canvas"?
The source and target are JPEG yeah. Shouldn't there be a way to set the colour though, even with JPEG's?
Re: Merge two images / replicating Photoshop's "resize canvas"?
Yes, of course. Try setting the background to white. In my opinion that should work. I can test that a little later if it doesn't work for you.Jack-S wrote:The source and target are JPEG yeah. Shouldn't there be a way to set the colour though, even with JPEG's?
Mikko Koppanen
My blog: http://valokuva.org
My blog: http://valokuva.org
Re: Merge two images / replicating Photoshop's "resize canvas"?
Yeah, it dosen't seem to work, these both result in an image with a black area:
Code: Select all
$imagick = new Imagick('1.jpg'); // a 400x400px image
$imagick->setImageBackgroundColor(new ImagickPixel('white'));
$imagick->setImageExtent(800, 800);
Code: Select all
$imagick = new Imagick('1.png'); // a 400x400px image
$imagick->setImageMatte(true);
$imagick->setImageBackgroundColor(new ImagickPixel('transparent'));
$imagick->setImageExtent(800, 800);
Re: Merge two images / replicating Photoshop's "resize canvas"?
Seems like setting background color does not affect extent. You could ask in general forum how to set the image extent color.
You can also try this code:
Might be a little slower thou.
You can also try this code:
Code: Select all
function resizeCanvasImage( Imagick $image, $widthB, $heightB, $gravity, ImagickPixel $backgroundColor = null )
{
$composite = new Imagick();
$composite->newImage( $widthB, $heightB, new ImagickPixel( "white" ) );
$widthA = $this->getImageWidth();
$heightA = $this->getImageHeight();
switch ($gravity) {
case Imagick::GRAVITY_CENTER:
$x = floor(($widthB - $widthA) / 2);
$y = floor(($heightB - $heightA) / 2);
break;
// ...
default:
// error
break;
}
return $composite->compositeImage( $image, Imagick::COMPOSITE_OVER, $x, $y );
}
Mikko Koppanen
My blog: http://valokuva.org
My blog: http://valokuva.org
Re: Merge two images / replicating Photoshop's "resize canvas"?
Yeah, that is similar to the approach I originally tried, however it was a lot slower. I'll have a look in the general forum.
Re: Merge two images / replicating Photoshop's "resize canvas"?
OK,
According to this page: http://www.imagemagick.org/Usage/crop/#extent, -extent allows you to set the background colour. I have no idea how the command line arguments of ImageMagick relate to the IMagick PHP extensions interface, but it seems that it should be possible with the background colour setting, so is this an ImageMagick issue or an IMagick issue?
Also, as of ImageMagick 6.3.2 -extent now supports the gravity setting, which (if supported by the IMagick:setImageExtent method) would remove the need for my custom method anyway, which would be great !
Any chance this could be added?
Thanks,
Jack
P.S. I am using Imagick 2.0.0rc, with ImageMagick 6.3.3 04/21/07 Q16
According to this page: http://www.imagemagick.org/Usage/crop/#extent, -extent allows you to set the background colour. I have no idea how the command line arguments of ImageMagick relate to the IMagick PHP extensions interface, but it seems that it should be possible with the background colour setting, so is this an ImageMagick issue or an IMagick issue?
Also, as of ImageMagick 6.3.2 -extent now supports the gravity setting, which (if supported by the IMagick:setImageExtent method) would remove the need for my custom method anyway, which would be great !
Any chance this could be added?
Thanks,
Jack
P.S. I am using Imagick 2.0.0rc, with ImageMagick 6.3.3 04/21/07 Q16
-
- Posts: 1015
- Joined: 2005-03-21T21:16:57-07:00
Re: Merge two images / replicating Photoshop's "resize canvas"?
Magickwand has two functions which deal with background colour. One is MagickSetImageBackgroundColor and the other is MagickSetBackgroundColor.
If IMagick also has a setBackgroundColor function I think you'll find that it is the one you need.
Pete
If IMagick also has a setBackgroundColor function I think you'll find that it is the one you need.
Pete
Re: Merge two images / replicating Photoshop's "resize canvas"?
Yes it does, however it doesn't seem to work: viewtopic.php?p=30419#p30419el_supremo wrote:Magickwand has two functions which deal with background colour. One is MagickSetImageBackgroundColor and the other is MagickSetBackgroundColor.
If IMagick also has a setBackgroundColor function I think you'll find that it is the one you need.
Edit: setBackgroundColor() doesn't work either.
Re: Merge two images / replicating Photoshop's "resize canvas"?
Seems like neither of them helps in this case. MagickSetBackgroundColor sets the background color for the whole wand and MagickSetImageBackgroundColor sets for single image (if I understood correctly).el_supremo wrote:Magickwand has two functions which deal with background colour. One is MagickSetImageBackgroundColor and the other is MagickSetBackgroundColor.
If IMagick also has a setBackgroundColor function I think you'll find that it is the one you need.
Pete
Could this be a bug?
http://imagemagick.org/api/magick-image ... mageExtentJack-S wrote: Also, as of ImageMagick 6.3.2 -extent now supports the gravity setting, which (if supported by the IMagick:setImageExtent method) would remove the need for my custom method anyway, which would be great !
The api does not support setting gravity so I assume that just calling rollImage and setImageExtent.
Mikko Koppanen
My blog: http://valokuva.org
My blog: http://valokuva.org