Expose FilterImage through the Magick++ Image interface

Questions and postings pertaining to the development of ImageMagick, feature enhancements, and ImageMagick internals. ImageMagick source code and algorithms are discussed here. Usage questions which are too arcane for the normal user list should also be posted here.
hwright
Posts: 6
Joined: 2015-02-20T10:24:16-07:00
Authentication code: 6789

Expose FilterImage through the Magick++ Image interface

Post 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);
 
-Hyrum
User avatar
dlemstra
Posts: 1570
Joined: 2013-05-04T15:28:54-07:00
Authentication code: 6789
Contact:

Re: Expose FilterImage through the Magick++ Image interface

Post 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.
.NET + ImageMagick = Magick.NET https://github.com/dlemstra/Magick.NET, @MagickNET, Donate
hwright
Posts: 6
Joined: 2015-02-20T10:24:16-07:00
Authentication code: 6789

Re: Expose FilterImage through the Magick++ Image interface

Post 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?
-Hyrum
User avatar
magick
Site Admin
Posts: 11064
Joined: 2003-05-31T11:32:55-07:00

Re: Expose FilterImage through the Magick++ Image interface

Post by magick »

Use the ConvolveMorphology method with MorphologyImage(). It should produce the same results as FilterImage().
hwenjing
Posts: 8
Joined: 2015-03-25T13:05:02-07:00
Authentication code: 6789

Re: Expose FilterImage through the Magick++ Image interface

Post 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.
hwenjing
Posts: 8
Joined: 2015-03-25T13:05:02-07:00
Authentication code: 6789

Re: Expose FilterImage through the Magick++ Image interface

Post 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.
User avatar
magick
Site Admin
Posts: 11064
Joined: 2003-05-31T11:32:55-07:00

Re: Expose FilterImage through the Magick++ Image interface

Post 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');
hwenjing
Posts: 8
Joined: 2015-03-25T13:05:02-07:00
Authentication code: 6789

Re: Expose FilterImage through the Magick++ Image interface

Post 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.
User avatar
magick
Site Admin
Posts: 11064
Joined: 2003-05-31T11:32:55-07:00

Re: Expose FilterImage through the Magick++ Image interface

Post 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`
hwenjing
Posts: 8
Joined: 2015-03-25T13:05:02-07:00
Authentication code: 6789

Re: Expose FilterImage through the Magick++ Image interface

Post 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.
User avatar
magick
Site Admin
Posts: 11064
Joined: 2003-05-31T11:32:55-07:00

Re: Expose FilterImage through the Magick++ Image interface

Post 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.
hwenjing
Posts: 8
Joined: 2015-03-25T13:05:02-07:00
Authentication code: 6789

Re: Expose FilterImage through the Magick++ Image interface

Post 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().
hwenjing
Posts: 8
Joined: 2015-03-25T13:05:02-07:00
Authentication code: 6789

Re: Expose FilterImage through the Magick++ Image interface

Post 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
hwenjing
Posts: 8
Joined: 2015-03-25T13:05:02-07:00
Authentication code: 6789

Re: Expose FilterImage through the Magick++ Image interface

Post 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
User avatar
magick
Site Admin
Posts: 11064
Joined: 2003-05-31T11:32:55-07:00

Re: Expose FilterImage through the Magick++ Image interface

Post by magick »

With 6.9.0-6, we get the same results as 6.9.1-0. Not sure why its failing for you.
Post Reply