17b6b37ee0712fc684e19cf3b7472cf9063b3d2f5dirk// This may look like C code, but it is really -*- C++ -*-
27b6b37ee0712fc684e19cf3b7472cf9063b3d2f5dirk//
377328896b876314656427663695bc7b2c9be3f74dirk// Copyright Dirk Lemstra 2014-2015
47b6b37ee0712fc684e19cf3b7472cf9063b3d2f5dirk//
57b6b37ee0712fc684e19cf3b7472cf9063b3d2f5dirk// Implementation of channel moments.
67b6b37ee0712fc684e19cf3b7472cf9063b3d2f5dirk//
77b6b37ee0712fc684e19cf3b7472cf9063b3d2f5dirk
87b6b37ee0712fc684e19cf3b7472cf9063b3d2f5dirk#define MAGICKCORE_IMPLEMENTATION  1
97b6b37ee0712fc684e19cf3b7472cf9063b3d2f5dirk#define MAGICK_PLUSPLUS_IMPLEMENTATION  1
107b6b37ee0712fc684e19cf3b7472cf9063b3d2f5dirk
117b6b37ee0712fc684e19cf3b7472cf9063b3d2f5dirk#include "Magick++/Include.h"
127b6b37ee0712fc684e19cf3b7472cf9063b3d2f5dirk#include "Magick++/Exception.h"
137b6b37ee0712fc684e19cf3b7472cf9063b3d2f5dirk#include "Magick++/Statistic.h"
1477328896b876314656427663695bc7b2c9be3f74dirk#include "Magick++/Image.h"
157b6b37ee0712fc684e19cf3b7472cf9063b3d2f5dirk
167b6b37ee0712fc684e19cf3b7472cf9063b3d2f5dirkusing namespace std;
177b6b37ee0712fc684e19cf3b7472cf9063b3d2f5dirk
187b6b37ee0712fc684e19cf3b7472cf9063b3d2f5dirkMagick::ChannelMoments::ChannelMoments(void)
19130da8409cb096ee6288a3ae7684ee5c7a328b0cdirk  : _channel(SyncPixelChannel),
20130da8409cb096ee6288a3ae7684ee5c7a328b0cdirk    _huInvariants(8),
217b6b37ee0712fc684e19cf3b7472cf9063b3d2f5dirk    _centroidX(0.0),
227b6b37ee0712fc684e19cf3b7472cf9063b3d2f5dirk    _centroidY(0.0),
237b6b37ee0712fc684e19cf3b7472cf9063b3d2f5dirk    _ellipseAxisX(0.0),
247b6b37ee0712fc684e19cf3b7472cf9063b3d2f5dirk    _ellipseAxisY(0.0),
257b6b37ee0712fc684e19cf3b7472cf9063b3d2f5dirk    _ellipseAngle(0.0),
267b6b37ee0712fc684e19cf3b7472cf9063b3d2f5dirk    _ellipseEccentricity(0.0),
277b6b37ee0712fc684e19cf3b7472cf9063b3d2f5dirk    _ellipseIntensity(0.0)
287b6b37ee0712fc684e19cf3b7472cf9063b3d2f5dirk{
297b6b37ee0712fc684e19cf3b7472cf9063b3d2f5dirk}
307b6b37ee0712fc684e19cf3b7472cf9063b3d2f5dirk
317b6b37ee0712fc684e19cf3b7472cf9063b3d2f5dirkMagick::ChannelMoments::ChannelMoments(const ChannelMoments &channelMoments_)
32130da8409cb096ee6288a3ae7684ee5c7a328b0cdirk  : _channel(channelMoments_._channel),
33130da8409cb096ee6288a3ae7684ee5c7a328b0cdirk    _huInvariants(channelMoments_._huInvariants),
347b6b37ee0712fc684e19cf3b7472cf9063b3d2f5dirk    _centroidX(channelMoments_._centroidX),
357b6b37ee0712fc684e19cf3b7472cf9063b3d2f5dirk    _centroidY(channelMoments_._centroidY),
367b6b37ee0712fc684e19cf3b7472cf9063b3d2f5dirk    _ellipseAxisX(channelMoments_._ellipseAxisX),
377b6b37ee0712fc684e19cf3b7472cf9063b3d2f5dirk    _ellipseAxisY(channelMoments_._ellipseAxisY),
387b6b37ee0712fc684e19cf3b7472cf9063b3d2f5dirk    _ellipseAngle(channelMoments_._ellipseAngle),
397b6b37ee0712fc684e19cf3b7472cf9063b3d2f5dirk    _ellipseEccentricity(channelMoments_._ellipseEccentricity),
407b6b37ee0712fc684e19cf3b7472cf9063b3d2f5dirk    _ellipseIntensity(channelMoments_._ellipseIntensity)
417b6b37ee0712fc684e19cf3b7472cf9063b3d2f5dirk{
427b6b37ee0712fc684e19cf3b7472cf9063b3d2f5dirk}
437b6b37ee0712fc684e19cf3b7472cf9063b3d2f5dirk
447b6b37ee0712fc684e19cf3b7472cf9063b3d2f5dirkMagick::ChannelMoments::~ChannelMoments(void)
457b6b37ee0712fc684e19cf3b7472cf9063b3d2f5dirk{
467b6b37ee0712fc684e19cf3b7472cf9063b3d2f5dirk}
477b6b37ee0712fc684e19cf3b7472cf9063b3d2f5dirk
487b6b37ee0712fc684e19cf3b7472cf9063b3d2f5dirkdouble Magick::ChannelMoments::centroidX(void) const
497b6b37ee0712fc684e19cf3b7472cf9063b3d2f5dirk{
507b6b37ee0712fc684e19cf3b7472cf9063b3d2f5dirk  return(_centroidX);
517b6b37ee0712fc684e19cf3b7472cf9063b3d2f5dirk}
527b6b37ee0712fc684e19cf3b7472cf9063b3d2f5dirk
537b6b37ee0712fc684e19cf3b7472cf9063b3d2f5dirkdouble Magick::ChannelMoments::centroidY(void) const
547b6b37ee0712fc684e19cf3b7472cf9063b3d2f5dirk{
557b6b37ee0712fc684e19cf3b7472cf9063b3d2f5dirk  return(_centroidY);
567b6b37ee0712fc684e19cf3b7472cf9063b3d2f5dirk}
577b6b37ee0712fc684e19cf3b7472cf9063b3d2f5dirk
587b6b37ee0712fc684e19cf3b7472cf9063b3d2f5dirkMagick::PixelChannel Magick::ChannelMoments::channel(void) const
597b6b37ee0712fc684e19cf3b7472cf9063b3d2f5dirk{
607b6b37ee0712fc684e19cf3b7472cf9063b3d2f5dirk  return(_channel);
617b6b37ee0712fc684e19cf3b7472cf9063b3d2f5dirk}
627b6b37ee0712fc684e19cf3b7472cf9063b3d2f5dirk
637b6b37ee0712fc684e19cf3b7472cf9063b3d2f5dirkdouble Magick::ChannelMoments::ellipseAxisX(void) const
647b6b37ee0712fc684e19cf3b7472cf9063b3d2f5dirk{
657b6b37ee0712fc684e19cf3b7472cf9063b3d2f5dirk  return(_ellipseAxisX);
667b6b37ee0712fc684e19cf3b7472cf9063b3d2f5dirk}
677b6b37ee0712fc684e19cf3b7472cf9063b3d2f5dirk
687b6b37ee0712fc684e19cf3b7472cf9063b3d2f5dirkdouble Magick::ChannelMoments::ellipseAxisY(void) const
697b6b37ee0712fc684e19cf3b7472cf9063b3d2f5dirk{
707b6b37ee0712fc684e19cf3b7472cf9063b3d2f5dirk  return(_ellipseAxisY);
717b6b37ee0712fc684e19cf3b7472cf9063b3d2f5dirk}
727b6b37ee0712fc684e19cf3b7472cf9063b3d2f5dirk
737b6b37ee0712fc684e19cf3b7472cf9063b3d2f5dirkdouble Magick::ChannelMoments::ellipseAngle(void) const
747b6b37ee0712fc684e19cf3b7472cf9063b3d2f5dirk{
757b6b37ee0712fc684e19cf3b7472cf9063b3d2f5dirk  return(_ellipseAngle);
767b6b37ee0712fc684e19cf3b7472cf9063b3d2f5dirk}
777b6b37ee0712fc684e19cf3b7472cf9063b3d2f5dirk
787b6b37ee0712fc684e19cf3b7472cf9063b3d2f5dirkdouble Magick::ChannelMoments::ellipseEccentricity(void) const
797b6b37ee0712fc684e19cf3b7472cf9063b3d2f5dirk{
807b6b37ee0712fc684e19cf3b7472cf9063b3d2f5dirk  return(_ellipseEccentricity);
817b6b37ee0712fc684e19cf3b7472cf9063b3d2f5dirk}
827b6b37ee0712fc684e19cf3b7472cf9063b3d2f5dirk
837b6b37ee0712fc684e19cf3b7472cf9063b3d2f5dirkdouble Magick::ChannelMoments::ellipseIntensity(void) const
847b6b37ee0712fc684e19cf3b7472cf9063b3d2f5dirk{
857b6b37ee0712fc684e19cf3b7472cf9063b3d2f5dirk  return(_ellipseIntensity);
867b6b37ee0712fc684e19cf3b7472cf9063b3d2f5dirk}
877b6b37ee0712fc684e19cf3b7472cf9063b3d2f5dirk
887b6b37ee0712fc684e19cf3b7472cf9063b3d2f5dirkdouble Magick::ChannelMoments::huInvariants(const size_t index_) const
897b6b37ee0712fc684e19cf3b7472cf9063b3d2f5dirk{
907b6b37ee0712fc684e19cf3b7472cf9063b3d2f5dirk  if (index_ > 7)
917b6b37ee0712fc684e19cf3b7472cf9063b3d2f5dirk    throw ErrorOption("Valid range for index is 0-7");
927b6b37ee0712fc684e19cf3b7472cf9063b3d2f5dirk
937b6b37ee0712fc684e19cf3b7472cf9063b3d2f5dirk  return(_huInvariants.at(index_));
947b6b37ee0712fc684e19cf3b7472cf9063b3d2f5dirk}
957b6b37ee0712fc684e19cf3b7472cf9063b3d2f5dirk
967b6b37ee0712fc684e19cf3b7472cf9063b3d2f5dirkbool Magick::ChannelMoments::isValid() const
977b6b37ee0712fc684e19cf3b7472cf9063b3d2f5dirk{
987b6b37ee0712fc684e19cf3b7472cf9063b3d2f5dirk  return(_channel != SyncPixelChannel);
997b6b37ee0712fc684e19cf3b7472cf9063b3d2f5dirk}
1007b6b37ee0712fc684e19cf3b7472cf9063b3d2f5dirk
1017b6b37ee0712fc684e19cf3b7472cf9063b3d2f5dirkMagick::ChannelMoments::ChannelMoments(const PixelChannel channel_,
1027b6b37ee0712fc684e19cf3b7472cf9063b3d2f5dirk  const MagickCore::ChannelMoments *channelMoments_)
103130da8409cb096ee6288a3ae7684ee5c7a328b0cdirk  : _channel(channel_),
104130da8409cb096ee6288a3ae7684ee5c7a328b0cdirk    _huInvariants(),
1057b6b37ee0712fc684e19cf3b7472cf9063b3d2f5dirk    _centroidX(channelMoments_->centroid.x),
1067b6b37ee0712fc684e19cf3b7472cf9063b3d2f5dirk    _centroidY(channelMoments_->centroid.y),
1077b6b37ee0712fc684e19cf3b7472cf9063b3d2f5dirk    _ellipseAxisX(channelMoments_->ellipse_axis.x),
1087b6b37ee0712fc684e19cf3b7472cf9063b3d2f5dirk    _ellipseAxisY(channelMoments_->ellipse_axis.y),
1097b6b37ee0712fc684e19cf3b7472cf9063b3d2f5dirk    _ellipseAngle(channelMoments_->ellipse_angle),
1107b6b37ee0712fc684e19cf3b7472cf9063b3d2f5dirk    _ellipseEccentricity(channelMoments_->ellipse_eccentricity),
1117b6b37ee0712fc684e19cf3b7472cf9063b3d2f5dirk    _ellipseIntensity(channelMoments_->ellipse_intensity)
1127b6b37ee0712fc684e19cf3b7472cf9063b3d2f5dirk{
113e316d154e7b050fab78dbf86b33f0797594939cadirk  register ssize_t
1147b6b37ee0712fc684e19cf3b7472cf9063b3d2f5dirk    i;
1157b6b37ee0712fc684e19cf3b7472cf9063b3d2f5dirk
1167b6b37ee0712fc684e19cf3b7472cf9063b3d2f5dirk  for (i=0; i<8; i++)
11757f71289ef12fb275c908972156e7e397d9e07bbcristy    _huInvariants.push_back(channelMoments_->invariant[i]);
1187b6b37ee0712fc684e19cf3b7472cf9063b3d2f5dirk}
1197b6b37ee0712fc684e19cf3b7472cf9063b3d2f5dirk
120e316d154e7b050fab78dbf86b33f0797594939cadirkMagick::ChannelPerceptualHash::ChannelPerceptualHash(void)
121e316d154e7b050fab78dbf86b33f0797594939cadirk  : _channel(SyncPixelChannel),
122e316d154e7b050fab78dbf86b33f0797594939cadirk    _srgbHuPhash(7),
123e316d154e7b050fab78dbf86b33f0797594939cadirk    _hclpHuPhash(7)
124e316d154e7b050fab78dbf86b33f0797594939cadirk{
125e316d154e7b050fab78dbf86b33f0797594939cadirk}
126e316d154e7b050fab78dbf86b33f0797594939cadirk
127e316d154e7b050fab78dbf86b33f0797594939cadirkMagick::ChannelPerceptualHash::ChannelPerceptualHash(
128e316d154e7b050fab78dbf86b33f0797594939cadirk  const ChannelPerceptualHash &channelPerceptualHash_)
129e316d154e7b050fab78dbf86b33f0797594939cadirk  : _channel(channelPerceptualHash_._channel),
130e316d154e7b050fab78dbf86b33f0797594939cadirk    _srgbHuPhash(channelPerceptualHash_._srgbHuPhash),
131e316d154e7b050fab78dbf86b33f0797594939cadirk    _hclpHuPhash(channelPerceptualHash_._hclpHuPhash)
132e316d154e7b050fab78dbf86b33f0797594939cadirk{
133e316d154e7b050fab78dbf86b33f0797594939cadirk}
134e316d154e7b050fab78dbf86b33f0797594939cadirk
135e316d154e7b050fab78dbf86b33f0797594939cadirkMagick::ChannelPerceptualHash::ChannelPerceptualHash(
136e316d154e7b050fab78dbf86b33f0797594939cadirk  const PixelChannel channel_,const std::string &hash_)
137e316d154e7b050fab78dbf86b33f0797594939cadirk  : _channel(channel_),
138e316d154e7b050fab78dbf86b33f0797594939cadirk    _srgbHuPhash(7),
139e316d154e7b050fab78dbf86b33f0797594939cadirk    _hclpHuPhash(7)
140e316d154e7b050fab78dbf86b33f0797594939cadirk{
141e316d154e7b050fab78dbf86b33f0797594939cadirk  register ssize_t
142e316d154e7b050fab78dbf86b33f0797594939cadirk    i;
143e316d154e7b050fab78dbf86b33f0797594939cadirk
144e316d154e7b050fab78dbf86b33f0797594939cadirk  if (hash_.length() != 70)
145e316d154e7b050fab78dbf86b33f0797594939cadirk    throw ErrorOption("Invalid hash length");
146e316d154e7b050fab78dbf86b33f0797594939cadirk
147e316d154e7b050fab78dbf86b33f0797594939cadirk  for (i=0; i<14; i++)
148e316d154e7b050fab78dbf86b33f0797594939cadirk  {
149b27956a2e5105465a555508ddb3aa87881bcf55edirk    unsigned int
150e316d154e7b050fab78dbf86b33f0797594939cadirk      hex;
151e316d154e7b050fab78dbf86b33f0797594939cadirk
152e316d154e7b050fab78dbf86b33f0797594939cadirk    double
153e316d154e7b050fab78dbf86b33f0797594939cadirk      value;
154e316d154e7b050fab78dbf86b33f0797594939cadirk
155e316d154e7b050fab78dbf86b33f0797594939cadirk    if (sscanf(hash_.substr(i*5,5).c_str(),"%05x",&hex) != 1)
156e316d154e7b050fab78dbf86b33f0797594939cadirk      throw ErrorOption("Invalid hash value");
157e316d154e7b050fab78dbf86b33f0797594939cadirk
1584620adfacf4d6efe93b83ea4b0c3f68bb47736e6dirk    value=((unsigned short)hex) / pow(10.0, (double)(hex >> 17));
159e316d154e7b050fab78dbf86b33f0797594939cadirk    if (hex & (1 << 16))
160e316d154e7b050fab78dbf86b33f0797594939cadirk      value=-value;
161e316d154e7b050fab78dbf86b33f0797594939cadirk    if (i < 7)
162e316d154e7b050fab78dbf86b33f0797594939cadirk      _srgbHuPhash[i]=value;
163e316d154e7b050fab78dbf86b33f0797594939cadirk    else
164e316d154e7b050fab78dbf86b33f0797594939cadirk      _hclpHuPhash[i-7]=value;
165e316d154e7b050fab78dbf86b33f0797594939cadirk  }
166e316d154e7b050fab78dbf86b33f0797594939cadirk}
167e316d154e7b050fab78dbf86b33f0797594939cadirk
168e316d154e7b050fab78dbf86b33f0797594939cadirkMagick::ChannelPerceptualHash::~ChannelPerceptualHash(void)
169e316d154e7b050fab78dbf86b33f0797594939cadirk{
170e316d154e7b050fab78dbf86b33f0797594939cadirk}
171e316d154e7b050fab78dbf86b33f0797594939cadirk
172e316d154e7b050fab78dbf86b33f0797594939cadirkMagick::ChannelPerceptualHash::operator std::string() const
173e316d154e7b050fab78dbf86b33f0797594939cadirk{
174e316d154e7b050fab78dbf86b33f0797594939cadirk  std::string
175e316d154e7b050fab78dbf86b33f0797594939cadirk    hash;
176e316d154e7b050fab78dbf86b33f0797594939cadirk
177e316d154e7b050fab78dbf86b33f0797594939cadirk  register ssize_t
178e316d154e7b050fab78dbf86b33f0797594939cadirk    i;
179e316d154e7b050fab78dbf86b33f0797594939cadirk
180e316d154e7b050fab78dbf86b33f0797594939cadirk  if (!isValid())
181e316d154e7b050fab78dbf86b33f0797594939cadirk    return(std::string());
182e316d154e7b050fab78dbf86b33f0797594939cadirk
183e316d154e7b050fab78dbf86b33f0797594939cadirk  for (i=0; i<14; i++)
184e316d154e7b050fab78dbf86b33f0797594939cadirk  {
185e316d154e7b050fab78dbf86b33f0797594939cadirk    char
186e316d154e7b050fab78dbf86b33f0797594939cadirk      buffer[6];
187e316d154e7b050fab78dbf86b33f0797594939cadirk
188e316d154e7b050fab78dbf86b33f0797594939cadirk    double
189e316d154e7b050fab78dbf86b33f0797594939cadirk      value;
190e316d154e7b050fab78dbf86b33f0797594939cadirk
191b27956a2e5105465a555508ddb3aa87881bcf55edirk    unsigned int
192e316d154e7b050fab78dbf86b33f0797594939cadirk      hex;
193e316d154e7b050fab78dbf86b33f0797594939cadirk
194e316d154e7b050fab78dbf86b33f0797594939cadirk    if (i < 7)
195e316d154e7b050fab78dbf86b33f0797594939cadirk      value=_srgbHuPhash[i];
196e316d154e7b050fab78dbf86b33f0797594939cadirk    else
197e316d154e7b050fab78dbf86b33f0797594939cadirk      value=_hclpHuPhash[i-7];
198e316d154e7b050fab78dbf86b33f0797594939cadirk
199e316d154e7b050fab78dbf86b33f0797594939cadirk    hex=0;
200e316d154e7b050fab78dbf86b33f0797594939cadirk    while(hex < 7 && fabs(value*10) < 65536)
201e316d154e7b050fab78dbf86b33f0797594939cadirk    {
202e316d154e7b050fab78dbf86b33f0797594939cadirk      value=value*10;
203e316d154e7b050fab78dbf86b33f0797594939cadirk      hex++;
204e316d154e7b050fab78dbf86b33f0797594939cadirk    }
205e316d154e7b050fab78dbf86b33f0797594939cadirk
206e316d154e7b050fab78dbf86b33f0797594939cadirk    hex=(hex<<1);
207e316d154e7b050fab78dbf86b33f0797594939cadirk    if (value < 0.0)
208e316d154e7b050fab78dbf86b33f0797594939cadirk      hex|=1;
209b27956a2e5105465a555508ddb3aa87881bcf55edirk    hex=(hex<<16)+(unsigned int)(value < 0.0 ? -(value - 0.5) : value + 0.5);
210e316d154e7b050fab78dbf86b33f0797594939cadirk    (void) FormatLocaleString(buffer,6,"%05x",hex);
211e316d154e7b050fab78dbf86b33f0797594939cadirk    hash+=std::string(buffer);
212e316d154e7b050fab78dbf86b33f0797594939cadirk  }
213e316d154e7b050fab78dbf86b33f0797594939cadirk  return(hash);
214e316d154e7b050fab78dbf86b33f0797594939cadirk}
215e316d154e7b050fab78dbf86b33f0797594939cadirk
216e316d154e7b050fab78dbf86b33f0797594939cadirkMagick::PixelChannel Magick::ChannelPerceptualHash::channel() const
217e316d154e7b050fab78dbf86b33f0797594939cadirk{
218e316d154e7b050fab78dbf86b33f0797594939cadirk  return(_channel);
219e316d154e7b050fab78dbf86b33f0797594939cadirk}
220e316d154e7b050fab78dbf86b33f0797594939cadirk
221e316d154e7b050fab78dbf86b33f0797594939cadirkbool Magick::ChannelPerceptualHash::isValid() const
222e316d154e7b050fab78dbf86b33f0797594939cadirk{
223e316d154e7b050fab78dbf86b33f0797594939cadirk  return(_channel != SyncPixelChannel);
224e316d154e7b050fab78dbf86b33f0797594939cadirk}
225e316d154e7b050fab78dbf86b33f0797594939cadirk
226e316d154e7b050fab78dbf86b33f0797594939cadirkdouble Magick::ChannelPerceptualHash::sumSquaredDifferences(
227e316d154e7b050fab78dbf86b33f0797594939cadirk  const ChannelPerceptualHash &channelPerceptualHash_)
228e316d154e7b050fab78dbf86b33f0797594939cadirk{
229e316d154e7b050fab78dbf86b33f0797594939cadirk  double
230e316d154e7b050fab78dbf86b33f0797594939cadirk    ssd;
231e316d154e7b050fab78dbf86b33f0797594939cadirk
232e316d154e7b050fab78dbf86b33f0797594939cadirk  register ssize_t
233e316d154e7b050fab78dbf86b33f0797594939cadirk    i;
234e316d154e7b050fab78dbf86b33f0797594939cadirk
235e316d154e7b050fab78dbf86b33f0797594939cadirk  ssd=0.0;
236e316d154e7b050fab78dbf86b33f0797594939cadirk  for (i=0; i<7; i++)
237e316d154e7b050fab78dbf86b33f0797594939cadirk  {
238e316d154e7b050fab78dbf86b33f0797594939cadirk    ssd+=((_srgbHuPhash[i]-channelPerceptualHash_._srgbHuPhash[i])*
239e316d154e7b050fab78dbf86b33f0797594939cadirk      (_srgbHuPhash[i]-channelPerceptualHash_._srgbHuPhash[i]));
240e316d154e7b050fab78dbf86b33f0797594939cadirk    ssd+=((_hclpHuPhash[i]-channelPerceptualHash_._hclpHuPhash[i])*
241e316d154e7b050fab78dbf86b33f0797594939cadirk      (_hclpHuPhash[i]-channelPerceptualHash_._hclpHuPhash[i]));
242e316d154e7b050fab78dbf86b33f0797594939cadirk  }
243e316d154e7b050fab78dbf86b33f0797594939cadirk  return(ssd);
244e316d154e7b050fab78dbf86b33f0797594939cadirk}
245e316d154e7b050fab78dbf86b33f0797594939cadirk
246e316d154e7b050fab78dbf86b33f0797594939cadirkdouble Magick::ChannelPerceptualHash::srgbHuPhash(const size_t index_) const
247e316d154e7b050fab78dbf86b33f0797594939cadirk{
248e316d154e7b050fab78dbf86b33f0797594939cadirk  if (index_ > 6)
249e316d154e7b050fab78dbf86b33f0797594939cadirk    throw ErrorOption("Valid range for index is 0-6");
250e316d154e7b050fab78dbf86b33f0797594939cadirk
251e316d154e7b050fab78dbf86b33f0797594939cadirk  return(_srgbHuPhash.at(index_));
252e316d154e7b050fab78dbf86b33f0797594939cadirk}
253e316d154e7b050fab78dbf86b33f0797594939cadirk
254e316d154e7b050fab78dbf86b33f0797594939cadirkdouble Magick::ChannelPerceptualHash::hclpHuPhash(const size_t index_) const
255e316d154e7b050fab78dbf86b33f0797594939cadirk{
256e316d154e7b050fab78dbf86b33f0797594939cadirk  if (index_ > 6)
257e316d154e7b050fab78dbf86b33f0797594939cadirk    throw ErrorOption("Valid range for index is 0-6");
258e316d154e7b050fab78dbf86b33f0797594939cadirk
259e316d154e7b050fab78dbf86b33f0797594939cadirk  return(_hclpHuPhash.at(index_));
260e316d154e7b050fab78dbf86b33f0797594939cadirk}
261e316d154e7b050fab78dbf86b33f0797594939cadirk
262e316d154e7b050fab78dbf86b33f0797594939cadirkMagick::ChannelPerceptualHash::ChannelPerceptualHash(
263e316d154e7b050fab78dbf86b33f0797594939cadirk  const PixelChannel channel_,
264e316d154e7b050fab78dbf86b33f0797594939cadirk  const MagickCore::ChannelPerceptualHash *channelPerceptualHash_)
265e316d154e7b050fab78dbf86b33f0797594939cadirk  : _channel(channel_),
266e316d154e7b050fab78dbf86b33f0797594939cadirk    _srgbHuPhash(7),
267e316d154e7b050fab78dbf86b33f0797594939cadirk    _hclpHuPhash(7)
268e316d154e7b050fab78dbf86b33f0797594939cadirk{
269e316d154e7b050fab78dbf86b33f0797594939cadirk  register ssize_t
270e316d154e7b050fab78dbf86b33f0797594939cadirk    i;
271e316d154e7b050fab78dbf86b33f0797594939cadirk
272e316d154e7b050fab78dbf86b33f0797594939cadirk  for (i=0; i<7; i++)
273e316d154e7b050fab78dbf86b33f0797594939cadirk  {
274e316d154e7b050fab78dbf86b33f0797594939cadirk    _srgbHuPhash[i]=channelPerceptualHash_->srgb_hu_phash[i];
275e316d154e7b050fab78dbf86b33f0797594939cadirk    _hclpHuPhash[i]=channelPerceptualHash_->hclp_hu_phash[i];
276e316d154e7b050fab78dbf86b33f0797594939cadirk  }
277e316d154e7b050fab78dbf86b33f0797594939cadirk}
278e316d154e7b050fab78dbf86b33f0797594939cadirk
2797b6b37ee0712fc684e19cf3b7472cf9063b3d2f5dirkMagick::ChannelStatistics::ChannelStatistics(void)
2807b6b37ee0712fc684e19cf3b7472cf9063b3d2f5dirk  : _channel(SyncPixelChannel),
2817b6b37ee0712fc684e19cf3b7472cf9063b3d2f5dirk    _area(0.0),
2827b6b37ee0712fc684e19cf3b7472cf9063b3d2f5dirk    _depth(0.0),
2836d0da8396cc07f9eee0b367dba6fd522d6a6be3fdirk    _entropy(0.0),
2847b6b37ee0712fc684e19cf3b7472cf9063b3d2f5dirk    _kurtosis(0.0),
2857b6b37ee0712fc684e19cf3b7472cf9063b3d2f5dirk    _maxima(0.0),
2867b6b37ee0712fc684e19cf3b7472cf9063b3d2f5dirk    _mean(0.0),
2877b6b37ee0712fc684e19cf3b7472cf9063b3d2f5dirk    _minima(0.0),
2887b6b37ee0712fc684e19cf3b7472cf9063b3d2f5dirk    _skewness(0.0),
2897b6b37ee0712fc684e19cf3b7472cf9063b3d2f5dirk    _standardDeviation(0.0),
2907b6b37ee0712fc684e19cf3b7472cf9063b3d2f5dirk    _sum(0.0),
2917b6b37ee0712fc684e19cf3b7472cf9063b3d2f5dirk    _sumCubed(0.0),
2927b6b37ee0712fc684e19cf3b7472cf9063b3d2f5dirk    _sumFourthPower(0.0),
2937b6b37ee0712fc684e19cf3b7472cf9063b3d2f5dirk    _sumSquared(0.0),
2947b6b37ee0712fc684e19cf3b7472cf9063b3d2f5dirk    _variance(0.0)
2957b6b37ee0712fc684e19cf3b7472cf9063b3d2f5dirk{
2967b6b37ee0712fc684e19cf3b7472cf9063b3d2f5dirk}
2977b6b37ee0712fc684e19cf3b7472cf9063b3d2f5dirk
2987b6b37ee0712fc684e19cf3b7472cf9063b3d2f5dirkMagick::ChannelStatistics::ChannelStatistics(
2997b6b37ee0712fc684e19cf3b7472cf9063b3d2f5dirk  const ChannelStatistics &channelStatistics_)
3007b6b37ee0712fc684e19cf3b7472cf9063b3d2f5dirk  : _channel(channelStatistics_._channel),
3017b6b37ee0712fc684e19cf3b7472cf9063b3d2f5dirk    _area(channelStatistics_._area),
3027b6b37ee0712fc684e19cf3b7472cf9063b3d2f5dirk    _depth(channelStatistics_._depth),
3036d0da8396cc07f9eee0b367dba6fd522d6a6be3fdirk    _entropy(channelStatistics_._entropy),
3047b6b37ee0712fc684e19cf3b7472cf9063b3d2f5dirk    _kurtosis(channelStatistics_._kurtosis),
3057b6b37ee0712fc684e19cf3b7472cf9063b3d2f5dirk    _maxima(channelStatistics_._maxima),
3067b6b37ee0712fc684e19cf3b7472cf9063b3d2f5dirk    _mean(channelStatistics_._mean),
3077b6b37ee0712fc684e19cf3b7472cf9063b3d2f5dirk    _minima(channelStatistics_._minima),
3087b6b37ee0712fc684e19cf3b7472cf9063b3d2f5dirk    _skewness(channelStatistics_._skewness),
3097b6b37ee0712fc684e19cf3b7472cf9063b3d2f5dirk    _standardDeviation(channelStatistics_._standardDeviation),
3107b6b37ee0712fc684e19cf3b7472cf9063b3d2f5dirk    _sum(channelStatistics_._sum),
3117b6b37ee0712fc684e19cf3b7472cf9063b3d2f5dirk    _sumCubed(channelStatistics_._sumCubed),
3127b6b37ee0712fc684e19cf3b7472cf9063b3d2f5dirk    _sumFourthPower(channelStatistics_._sumFourthPower),
3137b6b37ee0712fc684e19cf3b7472cf9063b3d2f5dirk    _sumSquared(channelStatistics_._sumSquared),
3147b6b37ee0712fc684e19cf3b7472cf9063b3d2f5dirk    _variance(channelStatistics_._variance)
3157b6b37ee0712fc684e19cf3b7472cf9063b3d2f5dirk{
3167b6b37ee0712fc684e19cf3b7472cf9063b3d2f5dirk}
3177b6b37ee0712fc684e19cf3b7472cf9063b3d2f5dirk
3187b6b37ee0712fc684e19cf3b7472cf9063b3d2f5dirkMagick::ChannelStatistics::~ChannelStatistics(void)
3197b6b37ee0712fc684e19cf3b7472cf9063b3d2f5dirk{
3207b6b37ee0712fc684e19cf3b7472cf9063b3d2f5dirk}
3217b6b37ee0712fc684e19cf3b7472cf9063b3d2f5dirk
3227b6b37ee0712fc684e19cf3b7472cf9063b3d2f5dirkdouble Magick::ChannelStatistics::area() const
3237b6b37ee0712fc684e19cf3b7472cf9063b3d2f5dirk{
3247b6b37ee0712fc684e19cf3b7472cf9063b3d2f5dirk  return(_area);
3257b6b37ee0712fc684e19cf3b7472cf9063b3d2f5dirk}
3267b6b37ee0712fc684e19cf3b7472cf9063b3d2f5dirk
3277b6b37ee0712fc684e19cf3b7472cf9063b3d2f5dirkMagick::PixelChannel Magick::ChannelStatistics::channel() const
3287b6b37ee0712fc684e19cf3b7472cf9063b3d2f5dirk{
3297b6b37ee0712fc684e19cf3b7472cf9063b3d2f5dirk  return(_channel);
3307b6b37ee0712fc684e19cf3b7472cf9063b3d2f5dirk}
3317b6b37ee0712fc684e19cf3b7472cf9063b3d2f5dirk
3327b6b37ee0712fc684e19cf3b7472cf9063b3d2f5dirksize_t Magick::ChannelStatistics::depth() const
3337b6b37ee0712fc684e19cf3b7472cf9063b3d2f5dirk{
3347b6b37ee0712fc684e19cf3b7472cf9063b3d2f5dirk  return(_depth);
3357b6b37ee0712fc684e19cf3b7472cf9063b3d2f5dirk}
3367b6b37ee0712fc684e19cf3b7472cf9063b3d2f5dirk
3376d0da8396cc07f9eee0b367dba6fd522d6a6be3fdirkdouble Magick::ChannelStatistics::entropy() const
3386d0da8396cc07f9eee0b367dba6fd522d6a6be3fdirk{
3396d0da8396cc07f9eee0b367dba6fd522d6a6be3fdirk  return(_entropy);
3406d0da8396cc07f9eee0b367dba6fd522d6a6be3fdirk}
3416d0da8396cc07f9eee0b367dba6fd522d6a6be3fdirk
3427b6b37ee0712fc684e19cf3b7472cf9063b3d2f5dirkbool Magick::ChannelStatistics::isValid() const
3437b6b37ee0712fc684e19cf3b7472cf9063b3d2f5dirk{
3447b6b37ee0712fc684e19cf3b7472cf9063b3d2f5dirk  return(_channel != SyncPixelChannel);
3457b6b37ee0712fc684e19cf3b7472cf9063b3d2f5dirk}
3467b6b37ee0712fc684e19cf3b7472cf9063b3d2f5dirk
3477b6b37ee0712fc684e19cf3b7472cf9063b3d2f5dirkdouble Magick::ChannelStatistics::kurtosis() const
3487b6b37ee0712fc684e19cf3b7472cf9063b3d2f5dirk{
3497b6b37ee0712fc684e19cf3b7472cf9063b3d2f5dirk  return(_kurtosis);
3507b6b37ee0712fc684e19cf3b7472cf9063b3d2f5dirk}
3517b6b37ee0712fc684e19cf3b7472cf9063b3d2f5dirk
3527b6b37ee0712fc684e19cf3b7472cf9063b3d2f5dirkdouble Magick::ChannelStatistics::maxima() const
3537b6b37ee0712fc684e19cf3b7472cf9063b3d2f5dirk{
3547b6b37ee0712fc684e19cf3b7472cf9063b3d2f5dirk  return(_maxima);
3557b6b37ee0712fc684e19cf3b7472cf9063b3d2f5dirk}
3567b6b37ee0712fc684e19cf3b7472cf9063b3d2f5dirk
3577b6b37ee0712fc684e19cf3b7472cf9063b3d2f5dirkdouble Magick::ChannelStatistics::mean() const
3587b6b37ee0712fc684e19cf3b7472cf9063b3d2f5dirk{
3597b6b37ee0712fc684e19cf3b7472cf9063b3d2f5dirk  return(_mean);
3607b6b37ee0712fc684e19cf3b7472cf9063b3d2f5dirk}
3617b6b37ee0712fc684e19cf3b7472cf9063b3d2f5dirk
3627b6b37ee0712fc684e19cf3b7472cf9063b3d2f5dirkdouble Magick::ChannelStatistics::minima() const
3637b6b37ee0712fc684e19cf3b7472cf9063b3d2f5dirk{
3647b6b37ee0712fc684e19cf3b7472cf9063b3d2f5dirk  return(_minima);
3657b6b37ee0712fc684e19cf3b7472cf9063b3d2f5dirk}
3667b6b37ee0712fc684e19cf3b7472cf9063b3d2f5dirk
3677b6b37ee0712fc684e19cf3b7472cf9063b3d2f5dirkdouble Magick::ChannelStatistics::skewness() const
3687b6b37ee0712fc684e19cf3b7472cf9063b3d2f5dirk{
3697b6b37ee0712fc684e19cf3b7472cf9063b3d2f5dirk  return(_skewness);
3707b6b37ee0712fc684e19cf3b7472cf9063b3d2f5dirk}
3717b6b37ee0712fc684e19cf3b7472cf9063b3d2f5dirk
3727b6b37ee0712fc684e19cf3b7472cf9063b3d2f5dirkdouble Magick::ChannelStatistics::standardDeviation() const
3737b6b37ee0712fc684e19cf3b7472cf9063b3d2f5dirk{
3747b6b37ee0712fc684e19cf3b7472cf9063b3d2f5dirk  return(_standardDeviation);
3757b6b37ee0712fc684e19cf3b7472cf9063b3d2f5dirk}
3767b6b37ee0712fc684e19cf3b7472cf9063b3d2f5dirk
3777b6b37ee0712fc684e19cf3b7472cf9063b3d2f5dirkdouble Magick::ChannelStatistics::sum() const
3787b6b37ee0712fc684e19cf3b7472cf9063b3d2f5dirk{
3797b6b37ee0712fc684e19cf3b7472cf9063b3d2f5dirk  return(_sum);
3807b6b37ee0712fc684e19cf3b7472cf9063b3d2f5dirk}
3817b6b37ee0712fc684e19cf3b7472cf9063b3d2f5dirk
3827b6b37ee0712fc684e19cf3b7472cf9063b3d2f5dirkdouble Magick::ChannelStatistics::sumCubed() const
3837b6b37ee0712fc684e19cf3b7472cf9063b3d2f5dirk{
3847b6b37ee0712fc684e19cf3b7472cf9063b3d2f5dirk  return(_sumCubed);
3857b6b37ee0712fc684e19cf3b7472cf9063b3d2f5dirk}
3867b6b37ee0712fc684e19cf3b7472cf9063b3d2f5dirk
3877b6b37ee0712fc684e19cf3b7472cf9063b3d2f5dirkdouble Magick::ChannelStatistics::sumFourthPower() const
3887b6b37ee0712fc684e19cf3b7472cf9063b3d2f5dirk{
3897b6b37ee0712fc684e19cf3b7472cf9063b3d2f5dirk  return(_sumFourthPower);
3907b6b37ee0712fc684e19cf3b7472cf9063b3d2f5dirk}
3917b6b37ee0712fc684e19cf3b7472cf9063b3d2f5dirk
3927b6b37ee0712fc684e19cf3b7472cf9063b3d2f5dirkdouble Magick::ChannelStatistics::sumSquared() const
3937b6b37ee0712fc684e19cf3b7472cf9063b3d2f5dirk{
3947b6b37ee0712fc684e19cf3b7472cf9063b3d2f5dirk  return(_sumSquared);
3957b6b37ee0712fc684e19cf3b7472cf9063b3d2f5dirk}
3967b6b37ee0712fc684e19cf3b7472cf9063b3d2f5dirk
3977b6b37ee0712fc684e19cf3b7472cf9063b3d2f5dirkdouble Magick::ChannelStatistics::variance() const
3987b6b37ee0712fc684e19cf3b7472cf9063b3d2f5dirk{
3997b6b37ee0712fc684e19cf3b7472cf9063b3d2f5dirk  return(_variance);
4007b6b37ee0712fc684e19cf3b7472cf9063b3d2f5dirk}
4017b6b37ee0712fc684e19cf3b7472cf9063b3d2f5dirk
4027b6b37ee0712fc684e19cf3b7472cf9063b3d2f5dirkMagick::ChannelStatistics::ChannelStatistics(const PixelChannel channel_,
4037b6b37ee0712fc684e19cf3b7472cf9063b3d2f5dirk  const MagickCore::ChannelStatistics *channelStatistics_)
4047b6b37ee0712fc684e19cf3b7472cf9063b3d2f5dirk  : _channel(channel_),
4057b6b37ee0712fc684e19cf3b7472cf9063b3d2f5dirk    _area(channelStatistics_->area),
4067b6b37ee0712fc684e19cf3b7472cf9063b3d2f5dirk    _depth(channelStatistics_->depth),
4076d0da8396cc07f9eee0b367dba6fd522d6a6be3fdirk    _entropy(channelStatistics_->entropy),
4087b6b37ee0712fc684e19cf3b7472cf9063b3d2f5dirk    _kurtosis(channelStatistics_->kurtosis),
4097b6b37ee0712fc684e19cf3b7472cf9063b3d2f5dirk    _maxima(channelStatistics_->maxima),
4107b6b37ee0712fc684e19cf3b7472cf9063b3d2f5dirk    _mean(channelStatistics_->mean),
4117b6b37ee0712fc684e19cf3b7472cf9063b3d2f5dirk    _minima(channelStatistics_->minima),
4127b6b37ee0712fc684e19cf3b7472cf9063b3d2f5dirk    _skewness(channelStatistics_->skewness),
4137b6b37ee0712fc684e19cf3b7472cf9063b3d2f5dirk    _standardDeviation(channelStatistics_->standard_deviation),
4147b6b37ee0712fc684e19cf3b7472cf9063b3d2f5dirk    _sum(channelStatistics_->sum),
4157b6b37ee0712fc684e19cf3b7472cf9063b3d2f5dirk    _sumCubed(channelStatistics_->sum_cubed),
4167b6b37ee0712fc684e19cf3b7472cf9063b3d2f5dirk    _sumFourthPower(channelStatistics_->sum_fourth_power),
4177b6b37ee0712fc684e19cf3b7472cf9063b3d2f5dirk    _sumSquared(channelStatistics_->sum_squared),
4187b6b37ee0712fc684e19cf3b7472cf9063b3d2f5dirk    _variance(channelStatistics_->variance)
4197b6b37ee0712fc684e19cf3b7472cf9063b3d2f5dirk{
4207b6b37ee0712fc684e19cf3b7472cf9063b3d2f5dirk}
4217b6b37ee0712fc684e19cf3b7472cf9063b3d2f5dirk
4227b6b37ee0712fc684e19cf3b7472cf9063b3d2f5dirkMagick::ImageMoments::ImageMoments(void)
4237b6b37ee0712fc684e19cf3b7472cf9063b3d2f5dirk  : _channels()
4247b6b37ee0712fc684e19cf3b7472cf9063b3d2f5dirk{
4257b6b37ee0712fc684e19cf3b7472cf9063b3d2f5dirk}
4267b6b37ee0712fc684e19cf3b7472cf9063b3d2f5dirk
4277b6b37ee0712fc684e19cf3b7472cf9063b3d2f5dirkMagick::ImageMoments::ImageMoments(const ImageMoments &imageMoments_)
4287b6b37ee0712fc684e19cf3b7472cf9063b3d2f5dirk  : _channels(imageMoments_._channels)
4297b6b37ee0712fc684e19cf3b7472cf9063b3d2f5dirk{
4307b6b37ee0712fc684e19cf3b7472cf9063b3d2f5dirk}
4317b6b37ee0712fc684e19cf3b7472cf9063b3d2f5dirk
4327b6b37ee0712fc684e19cf3b7472cf9063b3d2f5dirkMagick::ImageMoments::~ImageMoments(void)
4337b6b37ee0712fc684e19cf3b7472cf9063b3d2f5dirk{
4347b6b37ee0712fc684e19cf3b7472cf9063b3d2f5dirk}
4357b6b37ee0712fc684e19cf3b7472cf9063b3d2f5dirk
4367b6b37ee0712fc684e19cf3b7472cf9063b3d2f5dirkMagick::ChannelMoments Magick::ImageMoments::channel(
4377b6b37ee0712fc684e19cf3b7472cf9063b3d2f5dirk  const PixelChannel channel_) const
4387b6b37ee0712fc684e19cf3b7472cf9063b3d2f5dirk{
4397b6b37ee0712fc684e19cf3b7472cf9063b3d2f5dirk  for (std::vector<ChannelMoments>::const_iterator it = _channels.begin();
4407b6b37ee0712fc684e19cf3b7472cf9063b3d2f5dirk       it != _channels.end(); ++it)
4417b6b37ee0712fc684e19cf3b7472cf9063b3d2f5dirk  {
4427b6b37ee0712fc684e19cf3b7472cf9063b3d2f5dirk    if (it->channel() == channel_)
4437b6b37ee0712fc684e19cf3b7472cf9063b3d2f5dirk      return(*it);
4447b6b37ee0712fc684e19cf3b7472cf9063b3d2f5dirk  }
4457b6b37ee0712fc684e19cf3b7472cf9063b3d2f5dirk  return(ChannelMoments());
4467b6b37ee0712fc684e19cf3b7472cf9063b3d2f5dirk}
4477b6b37ee0712fc684e19cf3b7472cf9063b3d2f5dirk
44877328896b876314656427663695bc7b2c9be3f74dirkMagick::ImageMoments::ImageMoments(const Image &image_)
4497b6b37ee0712fc684e19cf3b7472cf9063b3d2f5dirk  : _channels()
4507b6b37ee0712fc684e19cf3b7472cf9063b3d2f5dirk{
4517b6b37ee0712fc684e19cf3b7472cf9063b3d2f5dirk  MagickCore::ChannelMoments*
4527b6b37ee0712fc684e19cf3b7472cf9063b3d2f5dirk    channel_moments;
4537b6b37ee0712fc684e19cf3b7472cf9063b3d2f5dirk
4547b6b37ee0712fc684e19cf3b7472cf9063b3d2f5dirk  GetPPException;
45577328896b876314656427663695bc7b2c9be3f74dirk  channel_moments=GetImageMoments(image_.constImage(),exceptionInfo);
4567b6b37ee0712fc684e19cf3b7472cf9063b3d2f5dirk  if (channel_moments != (MagickCore::ChannelMoments *) NULL)
4577b6b37ee0712fc684e19cf3b7472cf9063b3d2f5dirk    {
4587b6b37ee0712fc684e19cf3b7472cf9063b3d2f5dirk      register ssize_t
4597b6b37ee0712fc684e19cf3b7472cf9063b3d2f5dirk        i;
4607b6b37ee0712fc684e19cf3b7472cf9063b3d2f5dirk
46177328896b876314656427663695bc7b2c9be3f74dirk      for (i=0; i < (ssize_t) GetPixelChannels(image_.constImage()); i++)
4627b6b37ee0712fc684e19cf3b7472cf9063b3d2f5dirk      {
46377328896b876314656427663695bc7b2c9be3f74dirk        PixelChannel channel=GetPixelChannelChannel(image_.constImage(),i);
46477328896b876314656427663695bc7b2c9be3f74dirk        PixelTrait traits=GetPixelChannelTraits(image_.constImage(),channel);
4657b6b37ee0712fc684e19cf3b7472cf9063b3d2f5dirk        if (traits == UndefinedPixelTrait)
4667b6b37ee0712fc684e19cf3b7472cf9063b3d2f5dirk          continue;
4677b6b37ee0712fc684e19cf3b7472cf9063b3d2f5dirk        if ((traits & UpdatePixelTrait) == 0)
4687b6b37ee0712fc684e19cf3b7472cf9063b3d2f5dirk          continue;
4697b6b37ee0712fc684e19cf3b7472cf9063b3d2f5dirk        _channels.push_back(Magick::ChannelMoments(channel,
4707b6b37ee0712fc684e19cf3b7472cf9063b3d2f5dirk          &channel_moments[channel]));
4717b6b37ee0712fc684e19cf3b7472cf9063b3d2f5dirk      }
4727b6b37ee0712fc684e19cf3b7472cf9063b3d2f5dirk      _channels.push_back(Magick::ChannelMoments(CompositePixelChannel,
4737b6b37ee0712fc684e19cf3b7472cf9063b3d2f5dirk        &channel_moments[CompositePixelChannel]));
4747b6b37ee0712fc684e19cf3b7472cf9063b3d2f5dirk      channel_moments=(MagickCore::ChannelMoments *) RelinquishMagickMemory(
4757b6b37ee0712fc684e19cf3b7472cf9063b3d2f5dirk        channel_moments);
4767b6b37ee0712fc684e19cf3b7472cf9063b3d2f5dirk    }
47777328896b876314656427663695bc7b2c9be3f74dirk  ThrowPPException(image_.quiet());
4787b6b37ee0712fc684e19cf3b7472cf9063b3d2f5dirk}
4797b6b37ee0712fc684e19cf3b7472cf9063b3d2f5dirk
480e316d154e7b050fab78dbf86b33f0797594939cadirkMagick::ImagePerceptualHash::ImagePerceptualHash(void)
481e316d154e7b050fab78dbf86b33f0797594939cadirk  : _channels()
482e316d154e7b050fab78dbf86b33f0797594939cadirk{
483e316d154e7b050fab78dbf86b33f0797594939cadirk}
484e316d154e7b050fab78dbf86b33f0797594939cadirk
485e316d154e7b050fab78dbf86b33f0797594939cadirkMagick::ImagePerceptualHash::ImagePerceptualHash(
486e316d154e7b050fab78dbf86b33f0797594939cadirk  const ImagePerceptualHash &imagePerceptualHash_)
487e316d154e7b050fab78dbf86b33f0797594939cadirk  : _channels(imagePerceptualHash_._channels)
488e316d154e7b050fab78dbf86b33f0797594939cadirk{
489e316d154e7b050fab78dbf86b33f0797594939cadirk}
490e316d154e7b050fab78dbf86b33f0797594939cadirk
491e316d154e7b050fab78dbf86b33f0797594939cadirkMagick::ImagePerceptualHash::ImagePerceptualHash(const std::string &hash_)
492e316d154e7b050fab78dbf86b33f0797594939cadirk  : _channels()
493e316d154e7b050fab78dbf86b33f0797594939cadirk{
494e316d154e7b050fab78dbf86b33f0797594939cadirk  if (hash_.length() != 210)
495e316d154e7b050fab78dbf86b33f0797594939cadirk    throw ErrorOption("Invalid hash length");
496e316d154e7b050fab78dbf86b33f0797594939cadirk
497e316d154e7b050fab78dbf86b33f0797594939cadirk  _channels.push_back(Magick::ChannelPerceptualHash(RedPixelChannel,
498e316d154e7b050fab78dbf86b33f0797594939cadirk    hash_.substr(0, 70)));
499e316d154e7b050fab78dbf86b33f0797594939cadirk  _channels.push_back(Magick::ChannelPerceptualHash(GreenPixelChannel,
500e316d154e7b050fab78dbf86b33f0797594939cadirk    hash_.substr(70, 70)));
501e316d154e7b050fab78dbf86b33f0797594939cadirk  _channels.push_back(Magick::ChannelPerceptualHash(BluePixelChannel,
502e316d154e7b050fab78dbf86b33f0797594939cadirk    hash_.substr(140, 70)));
503e316d154e7b050fab78dbf86b33f0797594939cadirk}
504e316d154e7b050fab78dbf86b33f0797594939cadirk
505e316d154e7b050fab78dbf86b33f0797594939cadirkMagick::ImagePerceptualHash::~ImagePerceptualHash(void)
506e316d154e7b050fab78dbf86b33f0797594939cadirk{
507e316d154e7b050fab78dbf86b33f0797594939cadirk}
508e316d154e7b050fab78dbf86b33f0797594939cadirk
509e316d154e7b050fab78dbf86b33f0797594939cadirkMagick::ImagePerceptualHash::operator std::string() const
510e316d154e7b050fab78dbf86b33f0797594939cadirk{
511e316d154e7b050fab78dbf86b33f0797594939cadirk  if (!isValid())
512e316d154e7b050fab78dbf86b33f0797594939cadirk    return(std::string());
513e316d154e7b050fab78dbf86b33f0797594939cadirk
514e316d154e7b050fab78dbf86b33f0797594939cadirk  return static_cast<std::string>(_channels[0]) +
515e316d154e7b050fab78dbf86b33f0797594939cadirk    static_cast<std::string>(_channels[1]) +
516e316d154e7b050fab78dbf86b33f0797594939cadirk    static_cast<std::string>(_channels[2]);
517e316d154e7b050fab78dbf86b33f0797594939cadirk}
518e316d154e7b050fab78dbf86b33f0797594939cadirk
519e316d154e7b050fab78dbf86b33f0797594939cadirkMagick::ChannelPerceptualHash Magick::ImagePerceptualHash::channel(
520e316d154e7b050fab78dbf86b33f0797594939cadirk  const PixelChannel channel_) const
521e316d154e7b050fab78dbf86b33f0797594939cadirk{
522e316d154e7b050fab78dbf86b33f0797594939cadirk  for (std::vector<ChannelPerceptualHash>::const_iterator it =
523e316d154e7b050fab78dbf86b33f0797594939cadirk       _channels.begin(); it != _channels.end(); ++it)
524e316d154e7b050fab78dbf86b33f0797594939cadirk  {
525e316d154e7b050fab78dbf86b33f0797594939cadirk    if (it->channel() == channel_)
526e316d154e7b050fab78dbf86b33f0797594939cadirk      return(*it);
527e316d154e7b050fab78dbf86b33f0797594939cadirk  }
528e316d154e7b050fab78dbf86b33f0797594939cadirk  return(ChannelPerceptualHash());
529e316d154e7b050fab78dbf86b33f0797594939cadirk}
530e316d154e7b050fab78dbf86b33f0797594939cadirk
531e316d154e7b050fab78dbf86b33f0797594939cadirkbool Magick::ImagePerceptualHash::isValid() const
532e316d154e7b050fab78dbf86b33f0797594939cadirk{
533e316d154e7b050fab78dbf86b33f0797594939cadirk  if (_channels.size() != 3)
534e316d154e7b050fab78dbf86b33f0797594939cadirk    return(false);
535e316d154e7b050fab78dbf86b33f0797594939cadirk
536e316d154e7b050fab78dbf86b33f0797594939cadirk  if (_channels[0].channel() != RedPixelChannel)
537e316d154e7b050fab78dbf86b33f0797594939cadirk    return(false);
538e316d154e7b050fab78dbf86b33f0797594939cadirk
539e316d154e7b050fab78dbf86b33f0797594939cadirk  if (_channels[1].channel() != GreenPixelChannel)
540e316d154e7b050fab78dbf86b33f0797594939cadirk    return(false);
541e316d154e7b050fab78dbf86b33f0797594939cadirk
542e316d154e7b050fab78dbf86b33f0797594939cadirk  if (_channels[2].channel() != BluePixelChannel)
543e316d154e7b050fab78dbf86b33f0797594939cadirk    return(false);
544e316d154e7b050fab78dbf86b33f0797594939cadirk
545e316d154e7b050fab78dbf86b33f0797594939cadirk  return(true);
546e316d154e7b050fab78dbf86b33f0797594939cadirk}
547e316d154e7b050fab78dbf86b33f0797594939cadirk
548e316d154e7b050fab78dbf86b33f0797594939cadirkdouble Magick::ImagePerceptualHash::sumSquaredDifferences(
549e316d154e7b050fab78dbf86b33f0797594939cadirk      const ImagePerceptualHash &channelPerceptualHash_)
550e316d154e7b050fab78dbf86b33f0797594939cadirk{
551e316d154e7b050fab78dbf86b33f0797594939cadirk  double
552e316d154e7b050fab78dbf86b33f0797594939cadirk    ssd;
553e316d154e7b050fab78dbf86b33f0797594939cadirk
554e316d154e7b050fab78dbf86b33f0797594939cadirk  register ssize_t
555e316d154e7b050fab78dbf86b33f0797594939cadirk    i;
556e316d154e7b050fab78dbf86b33f0797594939cadirk
557e316d154e7b050fab78dbf86b33f0797594939cadirk  if (!isValid())
558e316d154e7b050fab78dbf86b33f0797594939cadirk    throw ErrorOption("instance is not valid");
559e316d154e7b050fab78dbf86b33f0797594939cadirk  if (!channelPerceptualHash_.isValid())
560e316d154e7b050fab78dbf86b33f0797594939cadirk    throw ErrorOption("channelPerceptualHash_ is not valid");
561e316d154e7b050fab78dbf86b33f0797594939cadirk
562e316d154e7b050fab78dbf86b33f0797594939cadirk  ssd=0.0;
563e316d154e7b050fab78dbf86b33f0797594939cadirk  for (i=0; i<3; i++)
564e316d154e7b050fab78dbf86b33f0797594939cadirk  {
565e316d154e7b050fab78dbf86b33f0797594939cadirk    ssd+=_channels[i].sumSquaredDifferences(_channels[i]);
566e316d154e7b050fab78dbf86b33f0797594939cadirk  }
567e316d154e7b050fab78dbf86b33f0797594939cadirk  return(ssd);
568e316d154e7b050fab78dbf86b33f0797594939cadirk}
569e316d154e7b050fab78dbf86b33f0797594939cadirk
570e316d154e7b050fab78dbf86b33f0797594939cadirkMagick::ImagePerceptualHash::ImagePerceptualHash(
57177328896b876314656427663695bc7b2c9be3f74dirk  const Image &image_)
572e316d154e7b050fab78dbf86b33f0797594939cadirk  : _channels()
573e316d154e7b050fab78dbf86b33f0797594939cadirk{
574e316d154e7b050fab78dbf86b33f0797594939cadirk  MagickCore::ChannelPerceptualHash*
575e316d154e7b050fab78dbf86b33f0797594939cadirk    channel_perceptual_hash;
576e316d154e7b050fab78dbf86b33f0797594939cadirk
577e316d154e7b050fab78dbf86b33f0797594939cadirk  PixelTrait
578e316d154e7b050fab78dbf86b33f0797594939cadirk    traits;
579e316d154e7b050fab78dbf86b33f0797594939cadirk
580e316d154e7b050fab78dbf86b33f0797594939cadirk  GetPPException;
58177328896b876314656427663695bc7b2c9be3f74dirk  channel_perceptual_hash=GetImagePerceptualHash(image_.constImage(),
58277328896b876314656427663695bc7b2c9be3f74dirk    exceptionInfo);
583e316d154e7b050fab78dbf86b33f0797594939cadirk  if (channel_perceptual_hash != (MagickCore::ChannelPerceptualHash *) NULL)
584e316d154e7b050fab78dbf86b33f0797594939cadirk    {
58577328896b876314656427663695bc7b2c9be3f74dirk      traits=GetPixelChannelTraits(image_.constImage(),RedPixelChannel);
586e316d154e7b050fab78dbf86b33f0797594939cadirk      if ((traits & UpdatePixelTrait) != 0)
587e316d154e7b050fab78dbf86b33f0797594939cadirk        _channels.push_back(Magick::ChannelPerceptualHash(RedPixelChannel,
588e316d154e7b050fab78dbf86b33f0797594939cadirk          &channel_perceptual_hash[RedPixelChannel]));
58977328896b876314656427663695bc7b2c9be3f74dirk      traits=GetPixelChannelTraits(image_.constImage(),GreenPixelChannel);
590e316d154e7b050fab78dbf86b33f0797594939cadirk      if ((traits & UpdatePixelTrait) != 0)
591e316d154e7b050fab78dbf86b33f0797594939cadirk        _channels.push_back(Magick::ChannelPerceptualHash(GreenPixelChannel,
592e316d154e7b050fab78dbf86b33f0797594939cadirk          &channel_perceptual_hash[GreenPixelChannel]));
59377328896b876314656427663695bc7b2c9be3f74dirk      traits=GetPixelChannelTraits(image_.constImage(),BluePixelChannel);
594e316d154e7b050fab78dbf86b33f0797594939cadirk      if ((traits & UpdatePixelTrait) != 0)
595e316d154e7b050fab78dbf86b33f0797594939cadirk        _channels.push_back(Magick::ChannelPerceptualHash(BluePixelChannel,
596e316d154e7b050fab78dbf86b33f0797594939cadirk          &channel_perceptual_hash[BluePixelChannel]));
597e316d154e7b050fab78dbf86b33f0797594939cadirk      channel_perceptual_hash=(MagickCore::ChannelPerceptualHash *)
598e316d154e7b050fab78dbf86b33f0797594939cadirk        RelinquishMagickMemory(channel_perceptual_hash);
599e316d154e7b050fab78dbf86b33f0797594939cadirk    }
6000e671c22538976a0aa0b21ae338e05f33a27cb10dirk  ThrowPPException(image_.quiet());
601e316d154e7b050fab78dbf86b33f0797594939cadirk}
602e316d154e7b050fab78dbf86b33f0797594939cadirk
6037b6b37ee0712fc684e19cf3b7472cf9063b3d2f5dirkMagick::ImageStatistics::ImageStatistics(void)
6047b6b37ee0712fc684e19cf3b7472cf9063b3d2f5dirk  : _channels()
6057b6b37ee0712fc684e19cf3b7472cf9063b3d2f5dirk{
6067b6b37ee0712fc684e19cf3b7472cf9063b3d2f5dirk}
6077b6b37ee0712fc684e19cf3b7472cf9063b3d2f5dirk
6087b6b37ee0712fc684e19cf3b7472cf9063b3d2f5dirkMagick::ImageStatistics::ImageStatistics(
6097b6b37ee0712fc684e19cf3b7472cf9063b3d2f5dirk  const ImageStatistics &imageStatistics_)
6107b6b37ee0712fc684e19cf3b7472cf9063b3d2f5dirk  : _channels(imageStatistics_._channels)
6117b6b37ee0712fc684e19cf3b7472cf9063b3d2f5dirk{
6127b6b37ee0712fc684e19cf3b7472cf9063b3d2f5dirk}
6137b6b37ee0712fc684e19cf3b7472cf9063b3d2f5dirk
6147b6b37ee0712fc684e19cf3b7472cf9063b3d2f5dirkMagick::ImageStatistics::~ImageStatistics(void)
6157b6b37ee0712fc684e19cf3b7472cf9063b3d2f5dirk{
6167b6b37ee0712fc684e19cf3b7472cf9063b3d2f5dirk}
6177b6b37ee0712fc684e19cf3b7472cf9063b3d2f5dirk
6187b6b37ee0712fc684e19cf3b7472cf9063b3d2f5dirkMagick::ChannelStatistics Magick::ImageStatistics::channel(
6197b6b37ee0712fc684e19cf3b7472cf9063b3d2f5dirk  const PixelChannel channel_) const
6207b6b37ee0712fc684e19cf3b7472cf9063b3d2f5dirk{
6217b6b37ee0712fc684e19cf3b7472cf9063b3d2f5dirk  for (std::vector<ChannelStatistics>::const_iterator it = _channels.begin();
6227b6b37ee0712fc684e19cf3b7472cf9063b3d2f5dirk       it != _channels.end(); ++it)
6237b6b37ee0712fc684e19cf3b7472cf9063b3d2f5dirk  {
6247b6b37ee0712fc684e19cf3b7472cf9063b3d2f5dirk    if (it->channel() == channel_)
6257b6b37ee0712fc684e19cf3b7472cf9063b3d2f5dirk      return(*it);
6267b6b37ee0712fc684e19cf3b7472cf9063b3d2f5dirk  }
6277b6b37ee0712fc684e19cf3b7472cf9063b3d2f5dirk  return(ChannelStatistics());
6287b6b37ee0712fc684e19cf3b7472cf9063b3d2f5dirk}
6297b6b37ee0712fc684e19cf3b7472cf9063b3d2f5dirk
63077328896b876314656427663695bc7b2c9be3f74dirkMagick::ImageStatistics::ImageStatistics(const Image &image_)
6317b6b37ee0712fc684e19cf3b7472cf9063b3d2f5dirk  : _channels()
6327b6b37ee0712fc684e19cf3b7472cf9063b3d2f5dirk{
6337b6b37ee0712fc684e19cf3b7472cf9063b3d2f5dirk  MagickCore::ChannelStatistics*
6347b6b37ee0712fc684e19cf3b7472cf9063b3d2f5dirk    channel_statistics;
6357b6b37ee0712fc684e19cf3b7472cf9063b3d2f5dirk
6367b6b37ee0712fc684e19cf3b7472cf9063b3d2f5dirk  GetPPException;
63777328896b876314656427663695bc7b2c9be3f74dirk  channel_statistics=GetImageStatistics(image_.constImage(),exceptionInfo);
6387b6b37ee0712fc684e19cf3b7472cf9063b3d2f5dirk  if (channel_statistics != (MagickCore::ChannelStatistics *) NULL)
6397b6b37ee0712fc684e19cf3b7472cf9063b3d2f5dirk    {
6407b6b37ee0712fc684e19cf3b7472cf9063b3d2f5dirk      register ssize_t
6417b6b37ee0712fc684e19cf3b7472cf9063b3d2f5dirk        i;
6427b6b37ee0712fc684e19cf3b7472cf9063b3d2f5dirk
64377328896b876314656427663695bc7b2c9be3f74dirk      for (i=0; i < (ssize_t) GetPixelChannels(image_.constImage()); i++)
6447b6b37ee0712fc684e19cf3b7472cf9063b3d2f5dirk      {
64577328896b876314656427663695bc7b2c9be3f74dirk        PixelChannel channel=GetPixelChannelChannel(image_.constImage(),i);
64677328896b876314656427663695bc7b2c9be3f74dirk        PixelTrait traits=GetPixelChannelTraits(image_.constImage(),channel);
6477b6b37ee0712fc684e19cf3b7472cf9063b3d2f5dirk        if (traits == UndefinedPixelTrait)
6487b6b37ee0712fc684e19cf3b7472cf9063b3d2f5dirk          continue;
6497b6b37ee0712fc684e19cf3b7472cf9063b3d2f5dirk        if ((traits & UpdatePixelTrait) == 0)
6507b6b37ee0712fc684e19cf3b7472cf9063b3d2f5dirk          continue;
6517b6b37ee0712fc684e19cf3b7472cf9063b3d2f5dirk        _channels.push_back(Magick::ChannelStatistics(channel,
6527b6b37ee0712fc684e19cf3b7472cf9063b3d2f5dirk          &channel_statistics[channel]));
6537b6b37ee0712fc684e19cf3b7472cf9063b3d2f5dirk      }
6547b6b37ee0712fc684e19cf3b7472cf9063b3d2f5dirk      _channels.push_back(Magick::ChannelStatistics(CompositePixelChannel,
6557b6b37ee0712fc684e19cf3b7472cf9063b3d2f5dirk        &channel_statistics[CompositePixelChannel]));
6567b6b37ee0712fc684e19cf3b7472cf9063b3d2f5dirk      channel_statistics=(MagickCore::ChannelStatistics *) RelinquishMagickMemory(
6577b6b37ee0712fc684e19cf3b7472cf9063b3d2f5dirk        channel_statistics);
6587b6b37ee0712fc684e19cf3b7472cf9063b3d2f5dirk    }
65977328896b876314656427663695bc7b2c9be3f74dirk  ThrowPPException(image_.quiet());
66057f71289ef12fb275c908972156e7e397d9e07bbcristy}
661