]> granicus.if.org Git - imagemagick/blob - magick/feature.c
(no commit message)
[imagemagick] / magick / feature.c
1 /*
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 \f
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 \f
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 */
128 MagickExport ChannelFeatures *GetImageChannelFeatures(const Image *image,
129   ExceptionInfo *exception)
130 {
131   typedef struct _SpatialDependenceMatrix
132   {
133     LongPixelPacket
134       tone[4];
135   } SpatialDependenceMatrix;
136
137   CacheView
138     *image_view;
139
140   ChannelFeatures
141     *channel_features;
142
143   LongPixelPacket
144     tone,
145     *tones;
146
147   long
148     y;
149
150   MagickBooleanType
151     status;
152
153   register long
154     i;
155
156   size_t
157     length;
158
159   SpatialDependenceMatrix
160     **pixels;
161
162   unsigned long
163     number_tones;
164
165   assert(image != (Image *) NULL);
166   assert(image->signature == MagickSignature);
167   if (image->debug != MagickFalse)
168     (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
169   length=AllChannels+1UL;
170   channel_features=(ChannelFeatures *) AcquireQuantumMemory(length,
171     sizeof(*channel_features));
172   if (channel_features == (ChannelFeatures *) NULL)
173     ThrowFatalException(ResourceLimitFatalError,"MemoryAllocationFailed");
174   (void) ResetMagickMemory(channel_features,0,length*
175     sizeof(*channel_features));
176   /*
177     Form tones.
178   */
179   tones=(LongPixelPacket *) AcquireQuantumMemory(MaxMap+1UL,sizeof(*tones));
180   if (tones == (LongPixelPacket *) NULL)
181     {
182       (void) ThrowMagickException(exception,GetMagickModule(),
183         ResourceLimitError,"MemoryAllocationFailed","`%s'",image->filename);
184       channel_features=(ChannelFeatures *) RelinquishMagickMemory(
185         channel_features);
186       return(channel_features);
187     }
188   for (i=0; i <= (long) MaxMap; i++)
189   {
190     tones[i].red=(~0UL);
191     tones[i].green=(~0UL);
192     tones[i].blue=(~0UL);
193     tones[i].opacity=(~0UL);
194     tones[i].index=(~0UL);
195   }
196   status=MagickTrue;
197   image_view=AcquireCacheView(image);
198 #if defined(MAGICKCORE_OPENMP_SUPPORT)
199   #pragma omp parallel for schedule(dynamic,4) shared(status)
200 #endif
201   for (y=0; y < (long) image->rows; y++)
202   {
203     register const IndexPacket
204       *restrict indexes;
205
206     register const PixelPacket
207       *restrict p;
208
209     register long
210       x;
211
212     if (status == MagickFalse)
213       continue;
214     p=GetCacheViewVirtualPixels(image_view,0,y,image->columns,1,exception);
215     if (p == (const PixelPacket *) NULL)
216       {
217         status=MagickFalse;
218         continue;
219       }
220     indexes=GetCacheViewVirtualIndexQueue(image_view);
221     for (x=0; x < (long) image->columns; x++)
222     {
223       tones[ScaleQuantumToMap(p->red)].red=ScaleQuantumToMap(p->red);
224       tones[ScaleQuantumToMap(p->green)].green=ScaleQuantumToMap(p->green);
225       tones[ScaleQuantumToMap(p->blue)].blue=ScaleQuantumToMap(p->blue);
226       if (image->matte != MagickFalse)
227         tones[ScaleQuantumToMap(p->opacity)].opacity=
228           ScaleQuantumToMap(p->opacity);
229       if (image->colorspace == CMYKColorspace)
230         tones[ScaleQuantumToMap(indexes[x])].index=
231           ScaleQuantumToMap(indexes[x]);
232       p++;
233     }
234   }
235   image_view=DestroyCacheView(image_view);
236   if (status == MagickFalse)
237     {
238       tones=(LongPixelPacket *) RelinquishMagickMemory(tones);
239       channel_features=(ChannelFeatures *) RelinquishMagickMemory(
240         channel_features);
241       return(channel_features);
242     }
243   (void) ResetMagickMemory(&tone,0,sizeof(tone));
244   for (i=0; i <= (long) MaxMap; i++)
245   {
246     if (tones[i].red != ~0UL)
247       tones[tone.red++].red=tones[i].red;
248     if (tones[i].green != ~0UL)
249       tones[tone.green++].green=tones[i].green;
250     if (tones[i].blue != ~0UL)
251       tones[tone.blue++].blue=tones[i].blue;
252     if (image->matte != MagickFalse)
253       if (tones[i].opacity != ~0UL)
254         tones[tone.opacity++].opacity=tones[i].opacity;
255     if (image->colorspace == CMYKColorspace)
256       if (tones[i].index != ~0UL)
257         tones[tone.index++].index=tones[i].index;
258   }
259   /*
260     Allocate spatial dependence matrix.
261   */
262   number_tones=tone.red;
263   if (tone.green > number_tones)
264     number_tones=tone.green;
265   if (tone.blue > number_tones)
266     number_tones=tone.blue;
267   if (image->matte != MagickFalse)
268     if (tone.opacity > number_tones)
269       number_tones=tone.opacity;
270   if (image->colorspace == CMYKColorspace)
271     if (tone.index > number_tones)
272       number_tones=tone.index;
273   pixels=(SpatialDependenceMatrix **) AcquireQuantumMemory(number_tones,
274     sizeof(**pixels));
275   if (pixels == (SpatialDependenceMatrix **) NULL)
276     {
277       (void) ThrowMagickException(exception,GetMagickModule(),
278         ResourceLimitError,"MemoryAllocationFailed","`%s'",image->filename);
279       tones=(LongPixelPacket *) RelinquishMagickMemory(tones);
280       channel_features=(ChannelFeatures *) RelinquishMagickMemory(
281         channel_features);
282       return(channel_features);
283     }
284   for (i=0; i <= (long) number_tones; i++)
285   {
286     pixels[i]=(SpatialDependenceMatrix *) AcquireQuantumMemory(number_tones,
287       sizeof(*pixels));
288     if (pixels[i] == (SpatialDependenceMatrix *) NULL)
289       break;
290     (void) ResetMagickMemory(pixels[i],0,number_tones*sizeof(*pixels));
291   }
292   if (i <= (long) number_tones)
293     {
294       (void) ThrowMagickException(exception,GetMagickModule(),
295         ResourceLimitError,"MemoryAllocationFailed","`%s'",image->filename);
296       for (i--; i >= 0; i--)
297         pixels[i]=(SpatialDependenceMatrix *) RelinquishMagickMemory(pixels[i]);
298       pixels=(SpatialDependenceMatrix **) RelinquishMagickMemory(pixels);
299       tones=(LongPixelPacket *) RelinquishMagickMemory(tones);
300       channel_features=(ChannelFeatures *) RelinquishMagickMemory(
301         channel_features);
302       return(channel_features);
303     }
304   /*
305     Initialize spatial dependence matrix.
306   */
307   status=MagickTrue;
308   image_view=AcquireCacheView(image);
309 #if defined(MAGICKCORE_OPENMP_SUPPORT)
310   #pragma omp parallel for schedule(dynamic,4) shared(status)
311 #endif
312   for (y=0; y < (long) image->rows; y++)
313   {
314     long
315       u,
316       v;
317
318     register const IndexPacket
319       *restrict indexes;
320
321     register const PixelPacket
322       *restrict p;
323
324     register long
325       x;
326
327     if (status == MagickFalse)
328       continue;
329     p=GetCacheViewVirtualPixels(image_view,0,y,image->columns,1,exception);
330     if (p == (const PixelPacket *) NULL)
331       {
332         status=MagickFalse;
333         continue;
334       }
335     indexes=GetCacheViewVirtualIndexQueue(image_view);
336     for (x=0; x < (long) image->columns; x++)
337     {
338       for (i=0; i < 4; i++)
339       {
340       }
341     }
342   }
343   image_view=DestroyCacheView(image_view);
344   if (status == MagickFalse)
345     {
346       (void) ThrowMagickException(exception,GetMagickModule(),
347         ResourceLimitError,"MemoryAllocationFailed","`%s'",image->filename);
348       for (i=0; i <= (long) number_tones; i++)
349         pixels[i]=(SpatialDependenceMatrix *) RelinquishMagickMemory(pixels[i]);
350       pixels=(SpatialDependenceMatrix **) RelinquishMagickMemory(pixels);
351       tones=(LongPixelPacket *) RelinquishMagickMemory(tones);
352       channel_features=(ChannelFeatures *) RelinquishMagickMemory(
353         channel_features);
354       return(channel_features);
355     }
356   /*
357     Relinquish resources.
358   */
359   for (i=0; i <= (long) number_tones; i++)
360     pixels[i]=(SpatialDependenceMatrix *) RelinquishMagickMemory(pixels[i]);
361   pixels=(SpatialDependenceMatrix **) RelinquishMagickMemory(pixels);
362   tones=(LongPixelPacket *) RelinquishMagickMemory(tones);
363   return(channel_features);
364 }