Clone and Append

MagickWand for PHP is an object-oriented PHP interface to ImageMagick. Use this forum to discuss, make suggestions about, or report bugs concerning MagickWand for PHP.
Post Reply
stefan9
Posts: 15
Joined: 2012-02-22T00:56:56-07:00
Authentication code: 8675308

Clone and Append

Post by stefan9 »

Hi all,

i have a problem with the order of images put together with MagickAppendImages();

Code: Select all

$resource = NewMagickWand();
MagickReadImage( $resource, 'test.jpg' );

$tmpres1 = CloneMagickWand($resource);
MagickFlopImage($tmpres1);
MagickAddImage($resource,$tmpres1);
DestroyMagickWand($tmpres1);

$tmpres2 = CloneMagickWand($resource);
MagickFlipImage($tmpres2);
MagickAddImage($resource,$tmpres2);
DestroyMagickWand($tmpres2);

MagickResetIterator($resource);

$newres = MagickAppendImages($resource);
MagickSetImageCompressionQuality($newres ,95);
MagickWriteImage($nmwc,'testres.jpg');
i need to have "$tmpres1 - $resource - $tmpres2"
i can get only "$resource - $resource1 - $tmpres2" :(
if i set MagickSetImageIndex($resource,0); infront of the second MagickAddImage()

thanks for help
Stefan
User avatar
anthony
Posts: 8883
Joined: 2004-05-31T19:27:03-07:00
Authentication code: 8675308
Location: Brisbane, Australia

Re: Clone and Append

Post by anthony »

MagickAddImage() appends (a clone) after the current image.
To add images to the end you must set the wand to the last image.
try this...

Code: Select all

$resource = NewMagickWand();
MagickReadImage( $resource, 'test.jpg' );

$tmpres1 = CloneMagickWand($resource);
MagickFlopImage($tmpres1);
MagickSetLastIterator($resource);
MagickAddImage($resource,$tmpres1);
DestroyMagickWand($tmpres1);

$tmpres2 = CloneMagickWand($resource);
MagickFlipImage($tmpres2);
MagickSetLastIterator($resource);
MagickAddImage($resource,$tmpres2);
DestroyMagickWand($tmpres2);

$newres = MagickAppendImages($resource);
MagickSetImageCompressionQuality($newres ,95);
MagickWriteImage($nmwc,'testres.jpg');
I looked at this as part of reading images MagickReadImage() , which also added images to the wand in the same way.
Use MagickSetFirstIterator(), to insert new images before all the current images in the wand, MagickSetLastIterator() to append add to the end, MagickSetImageIndex() to place images just after the given index.
This is actually much like using ( ... ) in the Shell API, except you can only append images to the end of the list.
Anthony Thyssen -- Webmaster for ImageMagick Example Pages
https://imagemagick.org/Usage/
stefan9
Posts: 15
Joined: 2012-02-22T00:56:56-07:00
Authentication code: 8675308

Re: Clone and Append

Post by stefan9 »

Hi Anthony,

thanks for your investigation.
the first MagickSetLastIterator($resource); has no effekt to the result
infront of the second MagickAddImage(); it works. i can set the position with MagickSetLastIterator($resource);

so i can get only "$resource - $tmpres1 - $tmpres2" or "$resource - $tmpres2 - $tmpres1" but not "$tmpres1 - $resource - $tmpres2"

is it a bug?
User avatar
anthony
Posts: 8883
Joined: 2004-05-31T19:27:03-07:00
Authentication code: 8675308
Location: Brisbane, Australia

Re: Clone and Append

Post by anthony »

Possibly. Their was some weirdness I noted when I looked though the code for the first time, December last year. Yes it was not too long ago. I was doing so as part of preparation for IM v7 Shell API additions, which is why I knew the answer.

ASIDE: I wanted to more closely link shell option handling with Magick wand handling. I hope to improve some parts of MagickWand API in the process of adding 'scripting' and 'pipelining' interface. EG: Allow co-processing programming techniques, which should work well with PHP as well as Shell script. Work on that is still in progress, and I'm sort of got it working.

Anyway back to you problem... What version of IM are you using?
Anthony Thyssen -- Webmaster for ImageMagick Example Pages
https://imagemagick.org/Usage/
stefan9
Posts: 15
Joined: 2012-02-22T00:56:56-07:00
Authentication code: 8675308

Re: Clone and Append

Post by stefan9 »

i setup a new server for testing and used the latest ImageMagick-6.7.5-6 (i see there is a new ImageMagick-6.7.5-7 out right now) and MagickWandForPHP-1.0.8

i can work around with a new Wand and put the Images with MagickAddImage($resource2,$tmpres1); MagickAddImage($resource2,$resource); MagickAddImage($resource2,$tmpres2); in correct order but i think this will take a more memory normaly needed!? Especially if $resource is a "big" image.

shell option work fine but is to slow becouse there are some more imageprocessing with the resulting image as far as i tested until now.
User avatar
anthony
Posts: 8883
Joined: 2004-05-31T19:27:03-07:00
Authentication code: 8675308
Location: Brisbane, Australia

Re: Clone and Append

Post by anthony »

That is what IMv7 co-processing is about. You run the image command in background, and while it holds the files, you send it processing commands and queries to work out what you want to do. basically a way to avoid temporary files or multiple commands. But this is in development: scripting done, error handling and scripting options still to be done.

However this does not help with you current problem with Imv6.

Okay you are using the latest IMv6,
But add image with 'lastinteration' set while only one image is present prepends rather than appends. Is that right?
Anthony Thyssen -- Webmaster for ImageMagick Example Pages
https://imagemagick.org/Usage/
stefan9
Posts: 15
Joined: 2012-02-22T00:56:56-07:00
Authentication code: 8675308

Re: Clone and Append

Post by stefan9 »

this sound interesting for my application. if you need beta-tester just give me a beep :)

yes, i tryed all combinations (i think) and can not set the original image at the last one if i add a new image
:(

how can i check the memory consuming of a wand? MagickGetImageSize() returns after MagickAddImage 0 result ...
a workaround can be a temporar wand or a MagickAddImage($resource,$resource);

btw. is there a compleat fuction listing?
http://www.imagemagick.org/api/magick-image.php
and
http://www.magickwand.org
have differend set of functions listed :!:
stefan9
Posts: 15
Joined: 2012-02-22T00:56:56-07:00
Authentication code: 8675308

Re: Clone and Append

Post by stefan9 »

i did a test with Imagick and got the same result. As far as i understand Imagick is a differend wrapper for Imagmagick API so maybe the "error" is not a bug but my wrong thinking of how to use?

Code: Select all

$resource = new Imagick('test.jpg');
$tmpres1= new Imagick();
$tmpres1 = $resource->clone();
$tmpres1->flipImage();
$resource->setLastIterator();
$resource->addImage($tmpres1);
$tmpres1->destroy(); 
$resource->resetIterator();
$result= new Imagick();
$result = $resource->appendImages(False);
$result->writeImage('test.new.jpg');
$resource->destroy(); 
$result->destroy(); 
like to have "$tmpres1 - $resource" but just can get "$resource - $tmpres1"
User avatar
anthony
Posts: 8883
Joined: 2004-05-31T19:27:03-07:00
Authentication code: 8675308
Location: Brisbane, Australia

Re: Clone and Append

Post by anthony »

I created a small MagickWand test script to test out various things,
All seems to work as expected (once i checked the manual for each function)

https://dl.dropbox.com/u/9500683/append_test.c.txt

See the comments in the script about how to use MagickAddImage() (image list append)
and MagickAppendImages() (image layout append), which I gleaned from the manual, code, and some testing.
Anthony Thyssen -- Webmaster for ImageMagick Example Pages
https://imagemagick.org/Usage/
stefan9
Posts: 15
Joined: 2012-02-22T00:56:56-07:00
Authentication code: 8675308

Re: Clone and Append

Post by stefan9 »

thanks for your testing antony!
in you example you working with a new wand there you past alle parts. in this way i also got it working.

i was afraid about memory consuming becouse my application need to handle parallel big images.
so you have a copy of the original wand in memory and i hoped to work without the copy and past the clone direct into the original wand.
User avatar
anthony
Posts: 8883
Joined: 2004-05-31T19:27:03-07:00
Authentication code: 8675308
Location: Brisbane, Australia

Re: Clone and Append

Post by anthony »

Note that wands do not actually pass or copy images to each other, only image meta-data. The actual image data is cached and shared until such time as the data is modified.. That is what a 'image clone' is. So if you don't keep a clone of the original you will not duplicate the data.

Some operators will create a new image, rather than directly modify the old image. Typically this happens if the image is resized, or has 'area effects' such that it needs to preserve the original information, but the wand calls should delete the original image immediately, unless the call actually creates a new wand. Basicaly so as to let the user decide if the original is still wanted (rare). For example MagickImageAppend() creates a new wand, but see Cavat in the MagickWand Example above.

WARNING: about memory use: resize creates two new images (making three images at one point during its processing That is because it first does resize on one direction, then in the other direction. The first intermediary image is deleted internally in MagickCore resize function, the original image is deleted (replaced in wand) by MagickWand. The same goes for some multi-kernel morphology operations. These are typically the worse case with regards for image memory usage.

ASIDE: Distort resize is slower but does not need an internal intermediary image as it is a 1-pass 2-dimentional process.
Anthony Thyssen -- Webmaster for ImageMagick Example Pages
https://imagemagick.org/Usage/
stefan9
Posts: 15
Joined: 2012-02-22T00:56:56-07:00
Authentication code: 8675308

Re: Clone and Append

Post by stefan9 »

thanks for explain anthony!
i give your c program a try and this runs much faster then the PHP-API so i will go forward with the c implementation.
User avatar
anthony
Posts: 8883
Joined: 2004-05-31T19:27:03-07:00
Authentication code: 8675308
Location: Brisbane, Australia

Re: Clone and Append

Post by anthony »

I have been looking again at the MagickAddImage() (which also is what MagickReadImage() used to add images to the given wand).

I was right about the need to add MagickSetLastIterator() before each call to either of the above to get MagickWand to add images to a wand in the right place (at the end). Though from experience I think most people avoided the issue by just storing each image read in thier own separate wand.

This should not be the case and I have figured out the reason it stuffs up. I have fixed this coding in both IMv6 and IMv7 versions of MagickWand, along with updated function documentation, for the various functions involved.

Still if you are not certain of the state of a wand, adding a MagickSetLastIterator() before calling MagickAddImage() or MagickReadImage(), will always be a good idea.


As for C being faster than the PHP MagickWand. I am not supprised, as PHP probably adds another layer of error checking. But I would not have thought it would be that noticable for actual image processing, so the difference is probably in PHP initialisation (PHP is a very large interpreted language, C is compiled).
Anthony Thyssen -- Webmaster for ImageMagick Example Pages
https://imagemagick.org/Usage/
Post Reply