blob: cc1c3bf0e832c3b69bf89a71ed244882a7ed5369 [file] [log] [blame]
cristy3e2860c2010-01-24 01:36:30 +00001/*
2%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3% %
4% %
5% %
6% FFFFF EEEEE AAA TTTTT U U RRRR EEEEE %
7% F E A A T U U R R E %
8% FFF EEE AAAAA T U U RRRR EEE %
9% F E A A T U U R R E %
10% F EEEEE A A T UUU R R EEEEE %
11% %
12% %
13% MagickCore Image Feature Methods %
14% %
15% Software Design %
16% John Cristy %
17% July 1992 %
18% %
19% %
20% Copyright 1999-2010 ImageMagick Studio LLC, a non-profit organization %
21% dedicated to making software imaging solutions freely available. %
22% %
23% You may not use this file except in compliance with the License. You may %
24% obtain a copy of the License at %
25% %
26% http://www.imagemagick.org/script/license.php %
27% %
28% Unless required by applicable law or agreed to in writing, software %
29% distributed under the License is distributed on an "AS IS" BASIS, %
30% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. %
31% See the License for the specific language governing permissions and %
32% limitations under the License. %
33% %
34%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
35%
36%
37%
38*/
39
40/*
41 Include declarations.
42*/
43#include "magick/studio.h"
44#include "magick/property.h"
45#include "magick/animate.h"
46#include "magick/blob.h"
47#include "magick/blob-private.h"
48#include "magick/cache.h"
49#include "magick/cache-private.h"
50#include "magick/cache-view.h"
51#include "magick/client.h"
52#include "magick/color.h"
53#include "magick/color-private.h"
54#include "magick/colorspace.h"
55#include "magick/colorspace-private.h"
56#include "magick/composite.h"
57#include "magick/composite-private.h"
58#include "magick/compress.h"
59#include "magick/constitute.h"
60#include "magick/deprecate.h"
61#include "magick/display.h"
62#include "magick/draw.h"
63#include "magick/enhance.h"
64#include "magick/exception.h"
65#include "magick/exception-private.h"
66#include "magick/feature.h"
67#include "magick/gem.h"
68#include "magick/geometry.h"
69#include "magick/list.h"
70#include "magick/image-private.h"
71#include "magick/magic.h"
72#include "magick/magick.h"
73#include "magick/memory_.h"
74#include "magick/module.h"
75#include "magick/monitor.h"
76#include "magick/monitor-private.h"
77#include "magick/option.h"
78#include "magick/paint.h"
79#include "magick/pixel-private.h"
80#include "magick/profile.h"
81#include "magick/quantize.h"
82#include "magick/random_.h"
83#include "magick/segment.h"
84#include "magick/semaphore.h"
85#include "magick/signature-private.h"
86#include "magick/string_.h"
87#include "magick/thread-private.h"
88#include "magick/timer.h"
89#include "magick/utility.h"
90#include "magick/version.h"
91
92/*
93%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
94% %
95% %
96% %
97% G e t I m a g e C h a n n e l F e a t u r e s %
98% %
99% %
100% %
101%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
102%
103% GetImageChannelFeatures() returns features for each channel in the
104% image. The features include the angular second momentum, contrast,
105% correlation, sum of squares: variance, inverse difference moment, sum
106% average, sum varience, sum entropy, entropy, difference variance, difference
107% entropy, information measures of correlation 1, information measures of
108% correlation 2, and maximum correlation coefficient. You can access the red
109% channel contrast, for example, like this:
110%
111% channel_features=GetImageChannelFeatures(image,excepton);
112% contrast=channel_features[RedChannel].contrast;
113%
114% Use MagickRelinquishMemory() to free the features buffer.
115%
116% The format of the GetImageChannelFeatures method is:
117%
118% ChannelFeatures *GetImageChannelFeatures(const Image *image,
119% ExceptionInfo *exception)
120%
121% A description of each parameter follows:
122%
123% o image: the image.
124%
125% o exception: return any errors or warnings in this structure.
126%
127*/
128MagickExport ChannelFeatures *GetImageChannelFeatures(const Image *image,
129 ExceptionInfo *exception)
130{
cristy2070fa52010-01-24 03:17:57 +0000131 CacheView
132 *image_view;
133
cristy3e2860c2010-01-24 01:36:30 +0000134 ChannelFeatures
135 *channel_features;
136
cristy2070fa52010-01-24 03:17:57 +0000137 LongPixelPacket
138 count,
139 *histogram;
140
cristy3e2860c2010-01-24 01:36:30 +0000141 long
142 y;
143
cristy2070fa52010-01-24 03:17:57 +0000144 MagickBooleanType
145 status;
146
147 register long
148 i;
149
cristy3e2860c2010-01-24 01:36:30 +0000150 size_t
151 length;
152
153 assert(image != (Image *) NULL);
154 assert(image->signature == MagickSignature);
155 if (image->debug != MagickFalse)
156 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
157 length=AllChannels+1UL;
158 channel_features=(ChannelFeatures *) AcquireQuantumMemory(length,
159 sizeof(*channel_features));
160 if (channel_features == (ChannelFeatures *) NULL)
161 ThrowFatalException(ResourceLimitFatalError,"MemoryAllocationFailed");
162 (void) ResetMagickMemory(channel_features,0,length*
163 sizeof(*channel_features));
cristy2070fa52010-01-24 03:17:57 +0000164 /*
165 Form histogram.
166 */
167 histogram=(LongPixelPacket *) AcquireQuantumMemory(MaxMap+1UL,
168 sizeof(*histogram));
169 if (histogram == (LongPixelPacket *) NULL)
170 {
171 (void) ThrowMagickException(exception,GetMagickModule(),
172 ResourceLimitError,"MemoryAllocationFailed","`%s'",image->filename);
173 channel_features=(ChannelFeatures *) RelinquishMagickMemory(
174 channel_features);
175 return(channel_features);
176 }
177 for (i=0; i <= (long) MaxMap; i++)
178 {
179 histogram[i].red=(~0);
180 histogram[i].green=(~0);
181 histogram[i].blue=(~0);
182 histogram[i].opacity=(~0);
183 histogram[i].index=(~0);
184 }
185 status=MagickTrue;
186 image_view=AcquireCacheView(image);
187#if defined(MAGICKCORE_OPENMP_SUPPORT)
188 #pragma omp parallel for schedule(dynamic,4) shared(status)
189#endif
cristy3e2860c2010-01-24 01:36:30 +0000190 for (y=0; y < (long) image->rows; y++)
191 {
192 register const IndexPacket
193 *restrict indexes;
194
195 register const PixelPacket
196 *restrict p;
197
198 register long
199 x;
200
cristy2070fa52010-01-24 03:17:57 +0000201 if (status == MagickFalse)
202 continue;
203 p=GetCacheViewVirtualPixels(image_view,0,y,image->columns,1,exception);
cristy3e2860c2010-01-24 01:36:30 +0000204 if (p == (const PixelPacket *) NULL)
cristy2070fa52010-01-24 03:17:57 +0000205 {
206 status=MagickFalse;
207 continue;
208 }
209 indexes=GetCacheViewVirtualIndexQueue(image_view);
cristy3e2860c2010-01-24 01:36:30 +0000210 for (x=0; x < (long) image->columns; x++)
211 {
cristy2070fa52010-01-24 03:17:57 +0000212 histogram[ScaleQuantumToMap(p->red)].red=ScaleQuantumToMap(p->red);
213 histogram[ScaleQuantumToMap(p->green)].green=ScaleQuantumToMap(p->green);
214 histogram[ScaleQuantumToMap(p->blue)].blue=ScaleQuantumToMap(p->blue);
215 if (image->matte != MagickFalse)
216 histogram[ScaleQuantumToMap(p->opacity)].opacity=
217 ScaleQuantumToMap(p->opacity);
218 if (image->colorspace == CMYKColorspace)
219 histogram[ScaleQuantumToMap(indexes[x])].index=
220 ScaleQuantumToMap(indexes[x]);
cristy3e2860c2010-01-24 01:36:30 +0000221 p++;
222 }
223 }
cristy2070fa52010-01-24 03:17:57 +0000224 (void) ResetMagickMemory(&count,0,sizeof(count));
225 for (i=0; i <= (long) MaxMap; i++)
226 {
227 if (histogram[i].red != ~0)
228 histogram[count.red++].red=histogram[i].red;
229 if (histogram[i].green != ~0)
230 histogram[count.green++].green=histogram[i].green;
231 if (histogram[i].blue != ~0)
232 histogram[count.blue++].blue=histogram[i].blue;
233 if (image->matte != MagickFalse)
234 if (histogram[i].opacity != ~0)
235 histogram[count.opacity++].opacity=histogram[i].opacity;
236 if (image->colorspace == CMYKColorspace)
237 if (histogram[i].index != ~0)
238 histogram[count.index++].index=histogram[i].index;
239 }
240 image_view=DestroyCacheView(image_view);
241 histogram=(LongPixelPacket *) RelinquishMagickMemory(histogram);
cristy3e2860c2010-01-24 01:36:30 +0000242 return(channel_features);
243}