return(n);
}
-static ssize_t PrintChannelPerceptualHash(FILE *file,const PixelChannel channel,
- const char *name,const ChannelPerceptualHash *channel_phash)
+static ssize_t PrintChannelPerceptualHash(Image *image,FILE *file,
+ const ChannelPerceptualHash *channel_phash)
{
register ssize_t
i;
ssize_t
n;
- n=FormatLocaleFile(file," %s:\n",name);
- for (i=0; i < MaximumNumberOfPerceptualHashes; i++)
- n+=FormatLocaleFile(file," PH%.20g: %.*g, %.*g\n",i+1.0,
- GetMagickPrecision(),channel_phash[channel].srgb_hu_phash[i],
- GetMagickPrecision(),channel_phash[channel].hclp_hu_phash[i]);
+ (void) FormatLocaleFile(file," Channel perceptual hash: ");
+ for (i=0; i < (ssize_t) channel_phash[0].number_colorspaces; i++)
+ {
+ (void) FormatLocaleFile(file,"%s",CommandOptionToMnemonic(
+ MagickColorspaceOptions,(ssize_t) channel_phash[0].colorspace[i]));
+ if (i < (ssize_t) (channel_phash[0].number_colorspaces-1))
+ (void) FormatLocaleFile(file,", ");
+ }
+ (void) FormatLocaleFile(file,"\n");
+ for (i=0; i < (ssize_t) GetPixelChannels(image); i++)
+ {
+ const char
+ *name;
+
+ register ssize_t
+ j;
+
+ PixelChannel channel=GetPixelChannelChannel(image,i);
+ PixelTrait traits=GetPixelChannelTraits(image,channel);
+ if (traits == UndefinedPixelTrait)
+ continue;
+ switch (channel)
+ {
+ case RedPixelChannel:
+ {
+ name="Red";
+ if (image->colorspace == CMYKColorspace)
+ name="Cyan";
+ if (image->colorspace == GRAYColorspace)
+ name="Gray";
+ break;
+ }
+ case GreenPixelChannel:
+ {
+ name="Green";
+ if (image->colorspace == CMYKColorspace)
+ name="Magenta";
+ break;
+ }
+ case BluePixelChannel:
+ {
+ name="Blue";
+ if (image->colorspace == CMYKColorspace)
+ name="Yellow";
+ break;
+ }
+ case BlackPixelChannel:
+ {
+ name="Black";
+ if (image->storage_class == PseudoClass)
+ name="Index";
+ break;
+ }
+ case IndexPixelChannel:
+ {
+ name="Index";
+ break;
+ }
+ case AlphaPixelChannel:
+ {
+ name="Alpha";
+ break;
+ }
+ case ReadMaskPixelChannel:
+ {
+ name="ReadMask";
+ break;
+ }
+ case WriteMaskPixelChannel:
+ {
+ name="WriteMask";
+ break;
+ }
+ case MetaPixelChannel:
+ {
+ name="Meta";
+ break;
+ }
+ default:
+ name="Undefined";
+ }
+ n=FormatLocaleFile(file," %s:\n",name);
+ for (j=0; j < MaximumNumberOfPerceptualHashes; j++)
+ {
+ register ssize_t
+ k;
+
+ n+=FormatLocaleFile(file," PH%.20g: ",(double) j+1);
+ for (k=0; k < (ssize_t) channel_phash[0].number_colorspaces; k++)
+ {
+ n+=FormatLocaleFile(file,"%.*g",GetMagickPrecision(),
+ channel_phash[channel].phash[k][j]);
+ if (k < (ssize_t) (channel_phash[0].number_colorspaces-1))
+ n+=FormatLocaleFile(file,", ");
+ }
+ n+=FormatLocaleFile(file,"\n");
+ }
+ }
return(n);
}
channel_statistics[AlphaPixelChannel].depth);
scale=1.0;
if (image->depth <= MAGICKCORE_QUANTUM_DEPTH)
- scale=(double) QuantumRange/((size_t) QuantumRange >> ((size_t)
- MAGICKCORE_QUANTUM_DEPTH-image->depth));
+ scale=(double) (QuantumRange/((size_t) QuantumRange >> ((size_t)
+ MAGICKCORE_QUANTUM_DEPTH-image->depth)));
}
if (channel_statistics != (ChannelStatistics *) NULL)
{
}
if (channel_phash != (ChannelPerceptualHash *) NULL)
{
- (void) FormatLocaleFile(file," Channel perceptual hash:\n");
- (void) PrintChannelPerceptualHash(file,RedPixelChannel,"Red, Hue",
- channel_phash);
- (void) PrintChannelPerceptualHash(file,GreenPixelChannel,"Green, Chroma",
- channel_phash);
- (void) PrintChannelPerceptualHash(file,BluePixelChannel,"Blue, Luma",
- channel_phash);
- if (image->alpha_trait != UndefinedPixelTrait)
- (void) PrintChannelPerceptualHash(file,AlphaPixelChannel,"Alpha, Alpha",
- channel_phash);
+ (void) PrintChannelPerceptualHash(image,file,channel_phash);
channel_phash=(ChannelPerceptualHash *) RelinquishMagickMemory(
channel_phash);
}
Include declarations.
*/
#include "MagickCore/studio.h"
-#include "MagickCore/property.h"
#include "MagickCore/accelerate-private.h"
#include "MagickCore/animate.h"
+#include "MagickCore/artifact.h"
#include "MagickCore/blob.h"
#include "MagickCore/blob-private.h"
#include "MagickCore/cache.h"
#include "MagickCore/paint.h"
#include "MagickCore/pixel-accessor.h"
#include "MagickCore/profile.h"
+#include "MagickCore/property.h"
#include "MagickCore/quantize.h"
#include "MagickCore/quantum-private.h"
#include "MagickCore/random_.h"
{
#define Log10Epsilon (1.0e-11)
- if (fabs(x) < Log10Epsilon)
- return(log10(Log10Epsilon));
- return(log10(fabs(x)));
+ if (fabs(x) < Log10Epsilon)
+ return(log10(Log10Epsilon));
+ return(log10(fabs(x)));
}
-MagickExport ChannelPerceptualHash *GetImagePerceptualHash(
- const Image *image,ExceptionInfo *exception)
+MagickExport ChannelPerceptualHash *GetImagePerceptualHash(const Image *image,
+ ExceptionInfo *exception)
{
- ChannelMoments
- *moments;
-
ChannelPerceptualHash
*perceptual_hash;
- Image
- *hash_image;
+ char
+ *colorspaces,
+ *q;
+
+ const char
+ *artifact;
MagickBooleanType
status;
+ register char
+ *p;
+
register ssize_t
i;
- ssize_t
- channel;
-
- /*
- Blur then transform to sRGB colorspace.
- */
- hash_image=BlurImage(image,0.0,1.0,exception);
- if (hash_image == (Image *) NULL)
- return((ChannelPerceptualHash *) NULL);
- hash_image->depth=8;
- status=TransformImageColorspace(hash_image,sRGBColorspace,exception);
- if (status == MagickFalse)
- return((ChannelPerceptualHash *) NULL);
- moments=GetImageMoments(hash_image,exception);
- hash_image=DestroyImage(hash_image);
- if (moments == (ChannelMoments *) NULL)
- return((ChannelPerceptualHash *) NULL);
perceptual_hash=(ChannelPerceptualHash *) AcquireQuantumMemory(
MaxPixelChannels+1UL,sizeof(*perceptual_hash));
if (perceptual_hash == (ChannelPerceptualHash *) NULL)
return((ChannelPerceptualHash *) NULL);
- for (channel=0; channel <= MaxPixelChannels; channel++)
- for (i=0; i < MaximumNumberOfImageMoments; i++)
- perceptual_hash[channel].srgb_hu_phash[i]=
- (-MagickLog10(moments[channel].invariant[i]));
- moments=(ChannelMoments *) RelinquishMagickMemory(moments);
- /*
- Blur then transform to HCLp colorspace.
- */
- hash_image=BlurImage(image,0.0,1.0,exception);
- if (hash_image == (Image *) NULL)
- {
- perceptual_hash=(ChannelPerceptualHash *) RelinquishMagickMemory(
- perceptual_hash);
- return((ChannelPerceptualHash *) NULL);
- }
- hash_image->depth=8;
- status=TransformImageColorspace(hash_image,HCLpColorspace,exception);
- if (status == MagickFalse)
- {
- perceptual_hash=(ChannelPerceptualHash *) RelinquishMagickMemory(
- perceptual_hash);
- return((ChannelPerceptualHash *) NULL);
- }
- moments=GetImageMoments(hash_image,exception);
- hash_image=DestroyImage(hash_image);
- if (moments == (ChannelMoments *) NULL)
- {
- perceptual_hash=(ChannelPerceptualHash *) RelinquishMagickMemory(
- perceptual_hash);
- return((ChannelPerceptualHash *) NULL);
- }
- for (channel=0; channel <= MaxPixelChannels; channel++)
- for (i=0; i < MaximumNumberOfImageMoments; i++)
- perceptual_hash[channel].hclp_hu_phash[i]=
- (-MagickLog10(moments[channel].invariant[i]));
- moments=(ChannelMoments *) RelinquishMagickMemory(moments);
+ artifact=GetImageArtifact(image,"phash:colorspaces");
+ if (artifact != NULL)
+ colorspaces=AcquireString(artifact);
+ else
+ colorspaces=AcquireString("sRGB,HCLp");
+ q=colorspaces;
+ for (i=0; (p=StringToken(",",&q)) != (char *) NULL; i++)
+ {
+ ChannelMoments
+ *moments;
+
+ Image
+ *hash_image;
+
+
+ size_t
+ j;
+
+ ssize_t
+ channel,
+ colorspace;
+
+ if (i >= MaximumNumberOfPerceptualColorspaces)
+ break;
+ colorspace=ParseCommandOption(MagickColorspaceOptions,MagickFalse,p);
+ if (colorspace < 0)
+ break;
+ perceptual_hash[0].colorspace[i]=(ColorspaceType) colorspace;
+ hash_image=BlurImage(image,0.0,1.0,exception);
+ if (hash_image == (Image *) NULL)
+ break;
+ hash_image->depth=8;
+ status=TransformImageColorspace(hash_image,(ColorspaceType) colorspace,
+ exception);
+ if (status == MagickFalse)
+ break;
+ moments=GetImageMoments(hash_image,exception);
+ hash_image=DestroyImage(hash_image);
+ if (moments == (ChannelMoments *) NULL)
+ break;
+ for (channel=0; channel <= MaxPixelChannels; channel++)
+ for (j=0; j < MaximumNumberOfImageMoments; j++)
+ perceptual_hash[channel].phash[i][j]=
+ (-MagickLog10(moments[channel].invariant[j]));
+ moments=(ChannelMoments *) RelinquishMagickMemory(moments);
+ }
+ perceptual_hash[0].number_colorspaces=(size_t) i;
+ colorspaces=DestroyString(colorspaces);
return(perceptual_hash);
}
\f