Different signatures from the same image

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
el_supremo
Posts: 1015
Joined: 2005-03-21T21:16:57-07:00

Different signatures from the same image

Post by el_supremo »

While testing my DLL which interfaces MagickWand to the REXX scripting language I came across an oddity with image signatures. I converted wand/drawtest.c to a rexx script and then verified that the rexx script and the C program output the same image by doing a verbose identify (on the command line) of the two images. They both produce identical signature strings which start with "3A".
I then implemented the MagickGetImageSignature function in my DLL and used it to print out the signature directly from within the script and found that this signature is different.
I went back to the C code and modified it in two ways. First I added code such that the original version prints out the signature in a MessageBox just before and just after it writes out the file as drawtest.gif. I then converted the C code to use MagickWand and checked the signatures again.
The MessageBox in the original drawtest code shows a signature string starting with 9E before it writes out the image but starting with 3A after it writes out the image and so the signatures are different.
The MagickWand version of the C code shows the 9E string before and after writing out the image. But when I identify the images on the command line both versions (original C and MagickWand) show the 3A string.

To make the drawtest.c code work in windows I changed the main routine to a function (testit) which takes a filename string as argument, and this function is then called from the winmain routine but otherwise the code is identical to drawtest.c.
This is the change to add a signature before and after the WriteImage - it prints the 9E signature before and the 3A signature after:

Code: Select all

	SignatureImage(canvas);
	signature = GetImageAttribute(canvas,"Signature");
if(signature)MessageBox(NULL,signature->value,"",MB_OK);

  (void) WriteImage ( image_info, canvas );

	SignatureImage(canvas);
	signature = GetImageAttribute(canvas,"Signature");
if(signature)MessageBox(NULL,signature->value,"",MB_OK);
and my complete code which uses MagickWand in the testit function is the following - this shows the 9E signature before and after the write:

Code: Select all

	Image *canvas = (Image *)NULL;
	int rows, columns = 0;

	const ImageAttribute *signature;
	MagickWand *magick_wand;
	PixelWand *p_wand = NULL;

	MagickWandGenesis();

  /*
   * Create canvas image
   */
	columns=596;
	rows=842;
	magick_wand = NewMagickWand();
	p_wand = NewPixelWand();
	PixelSetColor(p_wand,"#ffffff");
	/* set the new magick wand to a 596x842 white image*/ 
	MagickNewImage(magick_wand,columns,rows,p_wand);

	canvas = magick_wand->images;
  /*
   * Scribble on image
   */
	ScribbleImage( canvas );

  /*
   * Save image to file
   */
	SignatureImage(canvas);
	signature = GetImageAttribute(canvas,"Signature");
	if(signature)MessageBox(NULL,signature->value,"",MB_OK);

	MagickWriteImage(magick_wand,filename);

	SignatureImage(canvas);
	signature = GetImageAttribute(canvas,"Signature");
	if(signature)MessageBox(NULL,signature->value,"",MB_OK);

	p_wand = DestroyPixelWand(p_wand);
	magick_wand = DestroyMagickWand(magick_wand);
	MagickWandTerminus();
	return 0;

So far I've been unable to sort out why there are different signatures before and after the ImageMagick WriteImage function and also why MagickWand's MagickWriteImage would behave differently since internally it uses WriteImage anyway.
Shouldn't all these signatures be the same?

Pete
User avatar
magick
Site Admin
Posts: 11064
Joined: 2003-05-31T11:32:55-07:00

Post by magick »

Image signatures are sensitive to the image depth, image colorspace, and whether the image has an active opacity channel or not. An image with image->matte set to False, for example, produces a different signature than one with image->matte set to True. Given the above could that account for the different signatures you are getting?
el_supremo
Posts: 1015
Joined: 2005-03-21T21:16:57-07:00

Post by el_supremo »

Given the above could that account for the different signatures you are getting?

Yes!
As far as I can tell there's only one statement that affects the matte and removing that didn't change anything.
BUT, it must have the matte set because if I make both versions write out the file as a PNG instead of GIF, then all signatures begin with 9E and the identify command also prints 9E for the disk image.
The reason that the sig in the MagickWand version doesn't change when writing a GIF is that MagickWriteImage clones the image and then uses WriteImage to write out the cloned image. This isolates MagickWand from the change that WriteImage must be making and explains why the MagickWand version prints the same sig before and after the write.

This brings up another question - should WriteImage have the side effect of changing the Image matte (and perhaps other things) in the image in memory? Changing the in-memory matte when writing a GIF but not when writing a PNG means that if a program needs to write out both formats the results will depend upon whether the GIF or the PNG is written first. I've verified this with further mods to the drawtest.c code. Writing GIF then PNG means the PNG does not have a matte. Writing the PNG first means it does have a matte.

Would it be better if WriteImage wrote out a clone of the image so that the original doesn't get changed? (If this is done then the cloning in MagickWriteImage can be removed)

Pete
User avatar
magick
Site Admin
Posts: 11064
Joined: 2003-05-31T11:32:55-07:00

Post by magick »

We thought that cloning in MagickCore might be best for the reasons you mentioned, but we choose not to because its quite expensive to modify a cloned image and you as the user could always clone the image yourself before calling WriteImage(). We clone in MagickWand because its a higher level API and we try to protect the user from side-effects.
Post Reply