Page 1 of 2

Expose FilterImage through the Magick++ Image interface

Posted: 2015-03-23T18:43:44-07:00
by hwright
FilterImage isn't part of Magick++'s Image class. This appears to be an oversight, the following patch fixes the issue.

This patch is against trunk, but it'd be nice to get it into the next 6.9.1 release.

Code: Select all

Index: Magick++/lib/Image.cpp
===================================================================
--- Magick++/lib/Image.cpp	(revision 18267)
+++ Magick++/lib/Image.cpp	(working copy)
@@ -2847,6 +2847,25 @@
   extent(geometry);
 }
 
+void Magick::Image::filter(const std::string &kernel_)
+{
+  KernelInfo
+    *kernel;
+
+  MagickCore::Image
+    *newImage;
+
+  kernel=AcquireKernelInfo(kernel_.c_str());
+  if (kernel == (KernelInfo *)NULL)
+    throwExceptionExplicit(OptionError,"Unable to parse kernel.");
+
+  GetPPException;
+  newImage=FilterImage(constImage(),kernel,exceptionInfo);
+  replaceImage(newImage);
+  kernel=DestroyKernelInfo(kernel);
+  ThrowImageException;
+}
+
 void Magick::Image::flip(void)
 {
   MagickCore::Image
Index: Magick++/lib/Magick++/Image.h
===================================================================
--- Magick++/lib/Magick++/Image.h	(revision 18267)
+++ Magick++/lib/Magick++/Image.h	(working copy)
@@ -861,6 +861,11 @@
       const GravityType gravity_);
     void extent(const Geometry &geometry_,const GravityType gravity_);
 
+    // Filter image.  Applies a user-specified filter to the image.
+    // kernel_ is a string containing a list of doubles separated by
+    // commas representing the filter kernel.
+    void filter(const std::string &kernel_);
+
     // Flip image (reflect each scanline in the vertical direction)
     void flip(void);
 

Re: Expose FilterImage through the Magick++ Image interface

Posted: 2015-03-24T13:51:59-07:00
by dlemstra
FilterImage is legacy. It allowed a user to supply a custom kernel / filter to the image. This was deprecated when MorphologyImage was introduced by Anthony. Magick++ supports MorphologyImage (morphology methods) so FilterImage (filter) is not needed. ImageMagick 7 (the trunk) no longer has the FilterImage method.

Re: Expose FilterImage through the Magick++ Image interface

Posted: 2015-03-25T10:48:55-07:00
by hwright
MorphologyImage isn't a drop-in replacement for FilterImage, and the functionality that FilterImage exposed isn't available through the C++ interface. FilterImageChannel is still used in wand/mogrify.c shipped with 6.9.1-0, so presumably it still has some utility for pre-ImageMagick 7 releases.

What since MorphologyImage isn't a perfect replacement for FilterImage, what do you suggest instead to accomplish the same task?

Re: Expose FilterImage through the Magick++ Image interface

Posted: 2015-03-25T11:51:47-07:00
by magick
Use the ConvolveMorphology method with MorphologyImage(). It should produce the same results as FilterImage().

Re: Expose FilterImage through the Magick++ Image interface

Posted: 2015-03-25T13:53:10-07:00
by hwenjing
Hi we did try ConvolveMorphology with MorphologyImage(), the result is actually very close to (if not exactly same) as the current ConvolveImage() which is very different from FilterImage(). If needed I can sent you the result images. Please advice on this.

Re: Expose FilterImage through the Magick++ Image interface

Posted: 2015-03-25T14:19:15-07:00
by hwenjing
Please see the difference we detected from ConvolveImage() and FilterImage():
https://docs.google.com/document/d/11FD ... sp=sharing
And also please notice: if we use "convert" command line with "conlvolve" args, it actually calls FilterImage() underneath.

Re: Expose FilterImage through the Magick++ Image interface

Posted: 2015-03-25T16:02:52-07:00
by magick
Use the Correlate Morphology method rather than Convolve. This PerlMagick script returns a distortion of 0 when we compare the Morphology() method to the FilterImage() method:

Code: Select all

use Image::Magick;

$image=Image::Magick->new();

$image->Read('orig.png');
$image->Filter(kernel=>'-1.0, -2.0, -1.0, 0.0, 0.0, 0.0, 1.0, 2.0, 1.0');
$filter_image=$image->Clone();

$image=Image::Magick->new();
$image->Read('orig.png');
$image->Morphology(kernel=>'-1.0, -2.0, -1.0, 0.0, 0.0, 0.0, 1.0, 2.0, 1.0', method=>'Correlate');
$morphology_image=$image->Clone();
$difference_image=$morphology_image->Compare(image=>$filter_image);
print $difference_image->Get('error');

Re: Expose FilterImage through the Magick++ Image interface

Posted: 2015-03-26T10:21:38-07:00
by hwenjing
I replaced ConvolveMorphology with CorrelateMorphology within our C++ code and got the results very close to each other which is still very far from FilterImage() result
Attached the result image at the end:
https://docs.google.com/document/d/11FD ... sp=sharing

I am not sure about the distance between the above perl code and the c++ code we use.

Could you please test it with the "convert" command line tool provided in c++?
convert ./input.png -convolve '-1.0, -2.0, -1.0, 0.0, 0.0, 0.0, 1.0, 2.0, 1.0' ~/output.png

The command above actually calls FilterImageChannel() underneath (yes, name is confusing) and that result is exactly what we need.
But ConvolveMorphology and CorrelateMorphology generate a very different result from the command above.

Re: Expose FilterImage through the Magick++ Image interface

Posted: 2015-03-26T12:35:31-07:00
by magick
We got the expected results with Magick++ (both IMv6 and IMv7). Run this program, do you get the expected result too?

Code: Select all

#include <Magick++.h> 
#include <iostream> 

using namespace std; 
using namespace Magick; 

int main(int argc,char **argv) 
{ 
  InitializeMagick(*argv);

  Image image;
  try { 
    image.read( "input.png" );
    image.morphology(CorrelateMorphology,
      "-1.0, -2.0, -1.0, 0.0, 0.0, 0.0, 1.0, 2.0, 1.0",1);
    image.write( "output.png" ); 
  } 
  catch( Exception &error_ ) 
    { 
      cout << "Caught exception: " << error_.what() << endl; 
      return 1; 
    } 
  return 0; 
}
Build with this command:
  • c++ `Magick++-config --cxxflags --cppflags` -O2 -o filter filter.cpp `Magick++-config --ldflags --libs`

Re: Expose FilterImage through the Magick++ Image interface

Posted: 2015-03-26T14:03:26-07:00
by hwenjing
Just retried what you suggested above with v_6.9.0.6
See the last page of this link:
https://docs.google.com/document/d/11FD ... sp=sharing

the filter(...) was the new API which calls FilterImage(...)
The result from them are very different.

Could you let us know what is your output.png in your tests? Thanks.

Re: Expose FilterImage through the Magick++ Image interface

Posted: 2015-03-26T17:18:38-07:00
by magick
We're using ImageMagick 6.9.1-0 and the very latest ImageMagick 7.0.0-0. See http://magick.imagemagick.org/output.png, the output of the Morphology() method.

Re: Expose FilterImage through the Magick++ Image interface

Posted: 2015-03-26T17:45:12-07:00
by hwenjing
In that case looks like a gap between v_6.9.0-6 (our current version) and v_6.9.1-0 on morphology() then.
Hyrum, this is FYI.
Looks like with v_6.9.1-0 and above, we have chance to get rid of filter().

Re: Expose FilterImage through the Magick++ Image interface

Posted: 2015-03-27T10:00:09-07:00
by hwenjing
Hello ImageMagick,
As we are very surprise on the big difference between 6.9.0-6 and 6.9.0-1 on morphology(), would you mind to run the same script on 6.9.0-6 and let us know what is the result on your side?
Thanks,
Wenjing

Re: Expose FilterImage through the Magick++ Image interface

Posted: 2015-03-27T10:01:32-07:00
by hwenjing
typo above. I meant the difference between 6.9.0-6 and "6.9.1-0"
As we currently testing 6.9.0-6 which generates a very different result then what yo got on 6.9.1-0

Re: Expose FilterImage through the Magick++ Image interface

Posted: 2015-03-27T13:05:33-07:00
by magick
With 6.9.0-6, we get the same results as 6.9.1-0. Not sure why its failing for you.