146
146
bounds.x=(long) image->columns;
147
147
bounds.y=(long) image->rows;
148
148
GetMagickPixelPacket(image,&target[0]);
149
image_view=AcquireCacheViewThreadSet(image);
150
p=AcquireCacheViewPixels(image_view[0],0,0,1,1,exception);
149
image_view=AcquireCacheView(image);
150
p=GetCacheViewVirtualPixels(image_view,0,0,1,1,exception);
151
151
if (p == (const PixelPacket *) NULL)
153
image_view=DestroyCacheViewThreadSet(image_view);
153
image_view=DestroyCacheView(image_view);
156
SetMagickPixelPacket(image,p,GetCacheViewIndexes(image_view[0]),&target[0]);
156
SetMagickPixelPacket(image,p,GetCacheViewAuthenticIndexQueue(image_view),
157
158
GetMagickPixelPacket(image,&target[1]);
158
p=AcquireCacheViewPixels(image_view[0],(long) image->columns-1,0,1,1,
159
p=GetCacheViewVirtualPixels(image_view,(long) image->columns-1,0,1,1,
160
SetMagickPixelPacket(image,p,GetCacheViewIndexes(image_view[0]),&target[1]);
161
SetMagickPixelPacket(image,p,GetCacheViewAuthenticIndexQueue(image_view),
161
163
GetMagickPixelPacket(image,&target[2]);
162
p=AcquireCacheViewPixels(image_view[0],0,(long) image->rows-1,1,1,exception);
163
SetMagickPixelPacket(image,p,GetCacheViewIndexes(image_view[0]),&target[2]);
164
p=GetCacheViewVirtualPixels(image_view,0,(long) image->rows-1,1,1,exception);
165
SetMagickPixelPacket(image,p,GetCacheViewAuthenticIndexQueue(image_view),
164
167
status=MagickTrue;
165
168
GetMagickPixelPacket(image,&zero);
166
169
#if defined(MAGICKCORE_OPENMP_SUPPORT)
167
#pragma omp parallel for schedule(static,64) shared(status)
170
#pragma omp parallel for schedule(dynamic,4) shared(status)
169
172
for (y=0; y < (long) image->rows; y++)
171
174
MagickPixelPacket
180
register const IndexPacket
174
183
register const PixelPacket
184
189
if (status == MagickFalse)
186
id=GetCacheViewThreadId();
187
p=AcquireCacheViewPixels(image_view[id],0,y,image->columns,1,exception);
191
#if defined(HAVE_OPENMP)
192
# pragma omp critical (MagickCore_GetImageBoundingBox)
195
p=GetCacheViewVirtualPixels(image_view,0,y,image->columns,1,exception);
188
196
if (p == (const PixelPacket *) NULL)
190
198
status=MagickFalse;
193
indexes=GetCacheViewIndexes(image_view[id]);
201
indexes=GetCacheViewVirtualIndexQueue(image_view);
195
203
for (x=0; x < (long) image->columns; x++)
197
205
SetMagickPixelPacket(image,p,indexes+x,&pixel);
198
if ((x < bounds.x) &&
206
if ((x < bounding_box.x) &&
199
207
(IsMagickColorSimilar(&pixel,&target[0]) == MagickFalse))
201
if ((x > (long) bounds.width) &&
209
if ((x > (long) bounding_box.width) &&
202
210
(IsMagickColorSimilar(&pixel,&target[1]) == MagickFalse))
203
bounds.width=(unsigned long) x;
204
if ((y < bounds.y) &&
211
bounding_box.width=(unsigned long) x;
212
if ((y < bounding_box.y) &&
205
213
(IsMagickColorSimilar(&pixel,&target[0]) == MagickFalse))
207
if ((y > (long) bounds.height) &&
215
if ((y > (long) bounding_box.height) &&
208
216
(IsMagickColorSimilar(&pixel,&target[2]) == MagickFalse))
209
bounds.height=(unsigned long) y;
217
bounding_box.height=(unsigned long) y;
220
#if defined(HAVE_OPENMP)
221
# pragma omp critical (MagickCore_GetImageBoundingBox)
224
if (bounding_box.x < bounds.x)
225
bounds.x=bounding_box.x;
226
if (bounding_box.y < bounds.y)
227
bounds.y=bounding_box.y;
228
if (bounding_box.width > bounds.width)
229
bounds.width=bounding_box.width;
230
if (bounding_box.height > bounds.height)
231
bounds.height=bounding_box.height;
213
image_view=DestroyCacheViewThreadSet(image_view);
234
image_view=DestroyCacheView(image_view);
214
235
if ((bounds.width == 0) || (bounds.height == 0))
215
236
(void) ThrowMagickException(exception,GetMagickModule(),OptionWarning,
216
237
"GeometryDoesNotContainImage","`%s'",image->filename);
301
324
p=image->colormap;
302
325
#if defined(MAGICKCORE_OPENMP_SUPPORT)
303
#pragma omp parallel for schedule(static,64) shared(status)
326
#pragma omp parallel for schedule(dynamic,4) shared(status)
305
328
for (i=0; i < (long) image->colors; i++)
307
330
if (status == MagickFalse)
309
id=GetCacheViewThreadId();
332
id=GetPixelCacheThreadId();
310
333
while (current_depth[id] < MAGICKCORE_QUANTUM_DEPTH)
319
scale=GetQuantumScale(current_depth[id]);
342
range=GetQuantumRange(current_depth[id]);
320
343
if ((channel & RedChannel) != 0)
321
344
status|=p->red != ScaleAnyToQuantum(ScaleQuantumToAny(p->red,
322
current_depth[id],scale),current_depth[id],scale);
323
346
if ((channel & GreenChannel) != 0)
324
347
status|=p->green != ScaleAnyToQuantum(ScaleQuantumToAny(p->green,
325
current_depth[id],scale),current_depth[id],scale);
326
349
if ((channel & BlueChannel) != 0)
327
350
status|=p->blue != ScaleAnyToQuantum(ScaleQuantumToAny(p->blue,
328
current_depth[id],scale),current_depth[id],scale);
331
354
current_depth[id]++;
358
381
if (status == MagickFalse)
360
id=GetCacheViewThreadId();
361
p=AcquireCacheViewPixels(image_view[id],0,y,image->columns,1,exception);
383
id=GetPixelCacheThreadId();
384
p=GetCacheViewVirtualPixels(image_view,0,y,image->columns,1,exception);
362
385
if (p == (const PixelPacket *) NULL)
364
indexes=AcquireCacheViewIndexes(image_view[id]);
387
indexes=GetCacheViewVirtualIndexQueue(image_view);
365
388
for (x=0; x < (long) image->columns; x++)
367
390
while (current_depth[id] < MAGICKCORE_QUANTUM_DEPTH)
376
scale=GetQuantumScale(current_depth[id]);
399
range=GetQuantumRange(current_depth[id]);
377
400
if ((channel & RedChannel) != 0)
378
status|=p->red != ScaleAnyToQuantum(ScaleQuantumToAny(p->red,
379
current_depth[id],scale),current_depth[id],scale);
401
status|=p->red != ScaleAnyToQuantum(ScaleQuantumToAny(p->red,range),
380
403
if ((channel & GreenChannel) != 0)
381
404
status|=p->green != ScaleAnyToQuantum(ScaleQuantumToAny(p->green,
382
current_depth[id],scale),current_depth[id],scale);
383
406
if ((channel & BlueChannel) != 0)
384
status|=p->blue != ScaleAnyToQuantum(ScaleQuantumToAny(p->blue,
385
current_depth[id],scale),current_depth[id],scale);
407
status|=p->blue != ScaleAnyToQuantum(ScaleQuantumToAny(p->blue,range),
386
409
if (((channel & OpacityChannel) != 0) && (image->matte != MagickFalse))
387
410
status|=p->opacity != ScaleAnyToQuantum(ScaleQuantumToAny(p->opacity,
388
current_depth[id],scale),current_depth[id],scale);
389
412
if (((channel & IndexChannel) != 0) &&
390
413
(image->colorspace == CMYKColorspace))
391
414
status|=indexes[x] != ScaleAnyToQuantum(ScaleQuantumToAny(indexes[x],
392
current_depth[id],scale),current_depth[id],scale);
395
418
current_depth[id]++;
623
% G e t I m a g e C h a n n e l K u r t o s i s %
627
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
629
% GetImageChannelKurtosis() returns the kurtosis and skewness of one or more
632
% The format of the GetImageChannelKurtosis method is:
634
% MagickBooleanType GetImageChannelKurtosis(const Image *image,
635
% const ChannelType channel,double *kurtosis,double *skewness,
636
% ExceptionInfo *exception)
638
% A description of each parameter follows:
640
% o image: the image.
642
% o channel: the channel.
644
% o kurtosis: the kurtosis of the channel.
646
% o skewness: the skewness of the channel.
648
% o exception: return any errors or warnings in this structure.
652
MagickExport MagickBooleanType GetImageKurtosis(const Image *image,
653
double *kurtosis,double *skewness,ExceptionInfo *exception)
658
status=GetImageChannelKurtosis(image,AllChannels,kurtosis,skewness,
663
MagickExport MagickBooleanType GetImageChannelKurtosis(const Image *image,
664
const ChannelType channel,double *kurtosis,double *skewness,
665
ExceptionInfo *exception)
678
register const IndexPacket
681
register const PixelPacket
687
assert(image != (Image *) NULL);
688
assert(image->signature == MagickSignature);
689
if (image->debug != MagickFalse)
690
(void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
695
standard_deviation=0.0;
698
sum_fourth_power=0.0;
699
for (y=0; y < (long) image->rows; y++)
701
p=GetVirtualPixels(image,0,y,image->columns,1,exception);
702
if (p == (const PixelPacket *) NULL)
704
indexes=GetVirtualIndexQueue(image);
705
for (x=0; x < (long) image->columns; x++)
707
if ((channel & RedChannel) != 0)
710
sum_squares+=(double) p->red*p->red;
711
sum_cubes+=(double) p->red*p->red*p->red;
712
sum_fourth_power+=(double) p->red*p->red*p->red*p->red;
715
if ((channel & GreenChannel) != 0)
718
sum_squares+=(double) p->green*p->green;
719
sum_cubes+=(double) p->green*p->green*p->green;
720
sum_fourth_power+=(double) p->green*p->green*p->green*p->green;
723
if ((channel & BlueChannel) != 0)
726
sum_squares+=(double) p->blue*p->blue;
727
sum_cubes+=(double) p->blue*p->blue*p->blue;
728
sum_fourth_power+=(double) p->blue*p->blue*p->blue*p->blue;
731
if ((channel & OpacityChannel) != 0)
734
sum_squares+=(double) p->opacity*p->opacity;
735
sum_cubes+=(double) p->opacity*p->opacity*p->opacity;
736
sum_fourth_power+=(double) p->opacity*p->opacity*p->opacity*
740
if (((channel & IndexChannel) != 0) &&
741
(image->colorspace == CMYKColorspace))
744
sum_squares+=(double) indexes[x]*indexes[x];
745
sum_cubes+=(double) indexes[x]*indexes[x]*indexes[x];
746
sum_fourth_power+=(double) indexes[x]*indexes[x]*indexes[x]*
753
if (y < (long) image->rows)
760
sum_fourth_power/=area;
762
standard_deviation=sqrt(sum_squares-(mean*mean));
763
if (standard_deviation != 0.0)
765
*kurtosis=sum_fourth_power-4.0*mean*sum_cubes+6.0*mean*mean*sum_squares-
766
3.0*mean*mean*mean*mean;
767
*kurtosis/=standard_deviation*standard_deviation*standard_deviation*
770
*skewness=sum_cubes-3.0*mean*sum_squares+2.0*mean*mean*mean;
771
*skewness/=standard_deviation*standard_deviation*standard_deviation;
773
return(y == (long) image->rows ? MagickTrue : MagickFalse);
777
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
602
781
% G e t I m a g e C h a n n e l R a n g e %
811
992
channel_statistics[i].minima=1.0E+37;
812
993
channel_statistics[i].mean=0.0;
813
994
channel_statistics[i].standard_deviation=0.0;
995
channel_statistics[i].kurtosis=0.0;
996
channel_statistics[i].skewness=0.0;
815
998
y=(long) image->rows;
816
999
for (y=0; y < (long) image->rows; y++)
818
p=AcquireImagePixels(image,0,y,image->columns,1,exception);
1001
p=GetVirtualPixels(image,0,y,image->columns,1,exception);
819
1002
if (p == (const PixelPacket *) NULL)
821
indexes=AcquireIndexes(image);
1004
indexes=GetVirtualIndexQueue(image);
822
1005
for (x=0; x < (long) image->columns; )
824
1007
if (channel_statistics[RedChannel].depth != MAGICKCORE_QUANTUM_DEPTH)
826
1009
depth=channel_statistics[RedChannel].depth;
827
scale=GetQuantumScale(depth);
828
status=p->red != ScaleAnyToQuantum(ScaleQuantumToAny(p->red,depth,
829
scale),depth,scale) ? MagickTrue : MagickFalse;
1010
range=GetQuantumRange(depth);
1011
status=p->red != ScaleAnyToQuantum(ScaleQuantumToAny(p->red,range),
1012
range) ? MagickTrue : MagickFalse;
830
1013
if (status != MagickFalse)
832
1015
channel_statistics[RedChannel].depth++;
889
1072
if ((double) p->red > channel_statistics[RedChannel].maxima)
890
1073
channel_statistics[RedChannel].maxima=(double) p->red;
891
1074
channel_statistics[RedChannel].mean+=p->red;
892
channel_statistics[RedChannel].standard_deviation+=(double)
1075
channel_statistics[RedChannel].standard_deviation+=(double) p->red*p->red;
1076
channel_statistics[RedChannel].kurtosis+=(double) p->red*p->red*
1078
channel_statistics[RedChannel].skewness+=(double) p->red*p->red*p->red;
894
1079
if ((double) p->green < channel_statistics[GreenChannel].minima)
895
1080
channel_statistics[GreenChannel].minima=(double) p->green;
896
1081
if ((double) p->green > channel_statistics[GreenChannel].maxima)
897
1082
channel_statistics[GreenChannel].maxima=(double) p->green;
898
1083
channel_statistics[GreenChannel].mean+=p->green;
899
channel_statistics[GreenChannel].standard_deviation+=(double)
1084
channel_statistics[GreenChannel].standard_deviation+=(double) p->green*
1086
channel_statistics[GreenChannel].kurtosis+=(double) p->green*p->green*
900
1087
p->green*p->green;
1088
channel_statistics[GreenChannel].skewness+=(double) p->green*p->green*
901
1090
if ((double) p->blue < channel_statistics[BlueChannel].minima)
902
1091
channel_statistics[BlueChannel].minima=(double) p->blue;
903
1092
if ((double) p->blue > channel_statistics[BlueChannel].maxima)
904
1093
channel_statistics[BlueChannel].maxima=(double) p->blue;
905
1094
channel_statistics[BlueChannel].mean+=p->blue;
906
channel_statistics[BlueChannel].standard_deviation+=(double)
1095
channel_statistics[BlueChannel].standard_deviation+=(double) p->blue*
1097
channel_statistics[BlueChannel].kurtosis+=(double) p->blue*p->blue*
907
1098
p->blue*p->blue;
1099
channel_statistics[BlueChannel].skewness+=(double) p->blue*p->blue*
908
1101
if ((double) p->opacity < channel_statistics[OpacityChannel].minima)
909
1102
channel_statistics[OpacityChannel].minima=(double) p->opacity;
910
1103
if ((double) p->opacity > channel_statistics[OpacityChannel].maxima)
944
1147
channel_statistics[AllChannels].mean+=channel_statistics[i].mean;
945
1148
channel_statistics[AllChannels].standard_deviation+=
946
1149
channel_statistics[i].standard_deviation;
1150
channel_statistics[AllChannels].kurtosis+=channel_statistics[i].kurtosis;
1151
channel_statistics[AllChannels].skewness+=channel_statistics[i].skewness;
949
1154
if (image->colorspace == CMYKColorspace)
951
1156
channel_statistics[AllChannels].mean/=channels;
952
1157
channel_statistics[AllChannels].standard_deviation/=channels;
1158
channel_statistics[AllChannels].kurtosis/=channels;
1159
channel_statistics[AllChannels].skewness/=channels;
953
1160
for (i=0; i <= AllChannels; i++)
1163
sum_squares=channel_statistics[i].standard_deviation;
1165
sum_cubes=channel_statistics[i].skewness;
954
1166
channel_statistics[i].standard_deviation=sqrt(
955
1167
channel_statistics[i].standard_deviation-
956
1168
(channel_statistics[i].mean*channel_statistics[i].mean));
1169
if (channel_statistics[i].standard_deviation == 0.0)
1171
channel_statistics[i].kurtosis=0.0;
1172
channel_statistics[i].skewness=0.0;
1176
channel_statistics[i].skewness=(channel_statistics[i].skewness-
1177
3.0*channel_statistics[i].mean*sum_squares+
1178
2.0*channel_statistics[i].mean*channel_statistics[i].mean*
1179
channel_statistics[i].mean)/
1180
(channel_statistics[i].standard_deviation*
1181
channel_statistics[i].standard_deviation*
1182
channel_statistics[i].standard_deviation);
1183
channel_statistics[i].kurtosis=(channel_statistics[i].kurtosis-
1184
4.0*channel_statistics[i].mean*sum_cubes+
1185
6.0*channel_statistics[i].mean*channel_statistics[i].mean*sum_squares-
1186
3.0*channel_statistics[i].mean*channel_statistics[i].mean*
1187
1.0*channel_statistics[i].mean*channel_statistics[i].mean)/
1188
(channel_statistics[i].standard_deviation*
1189
channel_statistics[i].standard_deviation*
1190
channel_statistics[i].standard_deviation*
1191
channel_statistics[i].standard_deviation)-3.0;
957
1194
return(channel_statistics);
1092
1332
if (status == MagickFalse)
1094
id=GetCacheViewThreadId();
1095
q=GetCacheViewPixels(image_view[id],0,y,image->columns,1);
1334
q=GetCacheViewAuthenticPixels(image_view,0,y,image->columns,1,
1096
1336
if (q == (PixelPacket *) NULL)
1098
1338
status=MagickFalse;
1101
indexes=GetCacheViewIndexes(image_view[id]);
1341
indexes=GetCacheViewAuthenticIndexQueue(image_view);
1102
1342
for (x=0; x < (long) image->columns; x++)
1104
1344
if ((channel & RedChannel) != 0)
1105
q->red=ScaleAnyToQuantum(ScaleQuantumToAny(q->red,depth,scale),depth,
1345
q->red=ScaleAnyToQuantum(ScaleQuantumToAny(q->red,range),range);
1107
1346
if ((channel & GreenChannel) != 0)
1108
q->green=ScaleAnyToQuantum(ScaleQuantumToAny(q->green,depth,scale),
1347
q->green=ScaleAnyToQuantum(ScaleQuantumToAny(q->green,range),range);
1110
1348
if ((channel & BlueChannel) != 0)
1111
q->blue=ScaleAnyToQuantum(ScaleQuantumToAny(q->blue,depth,scale),
1349
q->blue=ScaleAnyToQuantum(ScaleQuantumToAny(q->blue,range),range);
1113
1350
if (((channel & OpacityChannel) != 0) && (image->matte != MagickFalse))
1114
q->opacity=ScaleAnyToQuantum(ScaleQuantumToAny(q->opacity,depth,scale),
1351
q->opacity=ScaleAnyToQuantum(ScaleQuantumToAny(q->opacity,range),range);
1116
1352
if (((channel & IndexChannel) != 0) &&
1117
1353
(image->colorspace == CMYKColorspace))
1118
indexes[x]=ScaleAnyToQuantum(ScaleQuantumToAny(indexes[x],depth,scale),
1354
indexes[x]=ScaleAnyToQuantum(ScaleQuantumToAny(indexes[x],range),range);
1122
if (SyncCacheViewPixels(image_view[id]) == MagickFalse)
1357
if (SyncCacheViewAuthenticPixels(image_view,exception) == MagickFalse)
1124
1359
status=MagickFalse;
1128
image_view=DestroyCacheViewThreadSet(image_view);
1363
image_view=DestroyCacheView(image_view);
1129
1364
if (image->storage_class == PseudoClass)
1140
1375
p=image->colormap;
1141
scale=GetQuantumScale(depth);
1376
range=GetQuantumRange(depth);
1142
1377
#if defined(MAGICKCORE_OPENMP_SUPPORT)
1143
#pragma omp parallel for schedule(static,64) shared(status)
1378
#pragma omp parallel for schedule(dynamic,4) shared(status)
1145
1380
for (i=0; i < (long) image->colors; i++)
1147
1382
if ((channel & RedChannel) != 0)
1148
p->red=ScaleAnyToQuantum(ScaleQuantumToAny(p->red,depth,
1149
scale),depth,scale);
1383
p->red=ScaleAnyToQuantum(ScaleQuantumToAny(p->red,range),range);
1150
1384
if ((channel & GreenChannel) != 0)
1151
p->green=ScaleAnyToQuantum(ScaleQuantumToAny(p->green,depth,
1152
scale),depth,scale);
1385
p->green=ScaleAnyToQuantum(ScaleQuantumToAny(p->green,range),range);
1153
1386
if ((channel & BlueChannel) != 0)
1154
p->blue=ScaleAnyToQuantum(ScaleQuantumToAny(p->blue,depth,
1155
scale),depth,scale);
1387
p->blue=ScaleAnyToQuantum(ScaleQuantumToAny(p->blue,range),range);
1156
1388
if ((channel & OpacityChannel) != 0)
1157
p->opacity=ScaleAnyToQuantum(ScaleQuantumToAny(p->opacity,depth,
1158
scale),depth,scale);
1389
p->opacity=ScaleAnyToQuantum(ScaleQuantumToAny(p->opacity,range),