Page 1 of 1

Magick++ double cropping conundrum

Posted: 2008-03-02T21:33:07-07:00
by Bob-O-Rama
Hi,

I'm sorry for the lengthy posting, but I wanted to offer as much detail as I can in the hopes someone will recognize the error of my ways... The short version is that I'm using Magick++ for rotating and cropping and image and then perfom another crop operation. The resulting image after the final crop() is not what I expect... Here are the details:

So I have a situation where I need to rotate a series of images ( all of them are same size, like extracted frames from a movie, for example ) and then after rotatating by some amount, I need to get a crop relative to the center of the image. Ecerything goes great till I perform two crop() operations right after one another.

See http://www.vimeo.com/740283 for reference. So loading the same image, then rotating by varying amounts we see that the resulting image can be wider or narrower than the original in one or both directions. So I use extent() and roll() to get an image which is at least as tall and wide as the original. ( If there is a better way, please tell me! ) Then I crop the image back to the original size, centered relative to the center of the rotated image. The white portions of the frame are generated by resize() and the black portions by extent(). Extent adds all its padding on one side, so roll() is used to shift the image so the padding ( black ) from extent() is equal on both sides. This works fine, as indicated in the movie.

However.... when I go to perform the SECOND and final crop to get a fixed section from the frame ( last 3 lines in the code below ) the resulting image is cropped to a smaller height than specified. ??? On debugging, I can see the height and width of the frame prior to the final crop is 1920x1080 ( which is correct ), but the resulting frame gets shorter and shorter and shorter.

Is there some issue with performing multiple crops ( other than it being inefficient ) or is there some operation I need to perform between them? Or is the coordinate system some how different after the rotate() and crop() that I'm failing to account for?

Code: Select all

	my_image.read( sourceFile.GetString() ); // read an image file from disk;
	original.cx = my_image.columns();
	original.cy = my_image.rows();  // e.g. 1920x1080

	my_image.rotate( m_Metrics.m_RotateDegrees );
	rotated.cx = my_image.columns();
	rotated.cy = my_image.rows(); // e.g. 1120x1104

	Geometry postrotate = Geometry( original.cx,
					original.cy,
					(( rotated.cx - original.cx ) / 2),
					(( rotated.cy - original.cy ) / 2),
					false, 
					false );

	my_image.crop( postrotate );
	postrotated.cx = my_image.columns();
	postrotated.cy = my_image.rows();  // e.g. 1920x1080

	// To IM Forum - the problem happens if the following if()...
	// block executes or not

	if( postrotated.cx < original.cx || postrotated.cy < original.cy )
	{
		Geometry extend = Geometry( original.cx,
						original.cy,
						original.cx - postrotated.cx,
						original.cy - postrotated.cy,
						false, 
						false );

		my_image.extent( extend );
		postextent.cx = my_image.columns();
		postextent.cy = my_image.rows();

		// The extend algorithm does not pad both side, so we have to roll
		my_image.roll( ( original.cx - postrotated.cx ) / 2,
				( original.cy - postrotated.cy ) / 2  );
				postroll.cx = my_image.columns();
				postroll.cy = my_image.rows();
	}

	// So at this point we have an image that is the same size as the original
	// So all we do is crop the image as requested by the user

	// To IM Forum - at this point I have a 1920x1080 image
	// my crop Geometry is set to "960x540+480+270"

	my_image.crop( crop );  // Here is where things go wrong.....
	postcrop.cx = my_image.columns();
	postcrop.cy = my_image.rows(); e.g. 960x442 ???

	// To IM Forum - at this point we will NOT have a 960x540 image
	// it will be 960 wide, but less than 540 tall, all the way down to 0

Thanks!

-- Bob

Re: Magick++ double cropping conundrum

Posted: 2008-03-03T07:44:20-07:00
by magick
Cropping is relative to a virtual canvas. You may want to remove this virtual canvas after you crop with
  • image.page("+0+0");

Re: Magick++ double cropping conundrum

Posted: 2008-03-03T20:04:31-07:00
by Bob-O-Rama
Thanks!!! Its works like Magick, in fact!

Of course I guess I should RTF(riendly)M WRT the virtual canvas stuff, as this might eliminate the necessity for a double crop and the rest. If I could set up a coordinate system centered on the center of the image, and have the rotate() maintain 0,0 as the center, then I could crop relative to that and avoid the double crop completely. Assuming rotate() would preserve the coordinate system.

-- Bob