00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039
00040
00041
00042
00043 #include "magick/studio.h"
00044 #include "magick/property.h"
00045 #include "magick/animate.h"
00046 #include "magick/blob.h"
00047 #include "magick/blob-private.h"
00048 #include "magick/cache.h"
00049 #include "magick/cache-private.h"
00050 #include "magick/cache-view.h"
00051 #include "magick/client.h"
00052 #include "magick/color.h"
00053 #include "magick/color-private.h"
00054 #include "magick/colorspace.h"
00055 #include "magick/colorspace-private.h"
00056 #include "magick/composite.h"
00057 #include "magick/composite-private.h"
00058 #include "magick/compress.h"
00059 #include "magick/constitute.h"
00060 #include "magick/deprecate.h"
00061 #include "magick/display.h"
00062 #include "magick/draw.h"
00063 #include "magick/enhance.h"
00064 #include "magick/exception.h"
00065 #include "magick/exception-private.h"
00066 #include "magick/gem.h"
00067 #include "magick/geometry.h"
00068 #include "magick/list.h"
00069 #include "magick/image-private.h"
00070 #include "magick/magic.h"
00071 #include "magick/magick.h"
00072 #include "magick/memory_.h"
00073 #include "magick/module.h"
00074 #include "magick/monitor.h"
00075 #include "magick/option.h"
00076 #include "magick/paint.h"
00077 #include "magick/pixel-private.h"
00078 #include "magick/profile.h"
00079 #include "magick/quantize.h"
00080 #include "magick/random_.h"
00081 #include "magick/segment.h"
00082 #include "magick/semaphore.h"
00083 #include "magick/signature-private.h"
00084 #include "magick/statistic.h"
00085 #include "magick/string_.h"
00086 #include "magick/timer.h"
00087 #include "magick/utility.h"
00088 #include "magick/version.h"
00089
00090
00091
00092
00093
00094
00095
00096
00097
00098
00099
00100
00101
00102
00103
00104
00105
00106
00107
00108
00109
00110
00111
00112
00113
00114
00115
00116
00117
00118 MagickExport RectangleInfo GetImageBoundingBox(const Image *image,
00119 ExceptionInfo *exception)
00120 {
00121 long
00122 y;
00123
00124 MagickBooleanType
00125 status;
00126
00127 MagickPixelPacket
00128 target[3],
00129 zero;
00130
00131 RectangleInfo
00132 bounds;
00133
00134 register const PixelPacket
00135 *p;
00136
00137 ViewInfo
00138 *image_view;
00139
00140 assert(image != (Image *) NULL);
00141 assert(image->signature == MagickSignature);
00142 if (image->debug != MagickFalse)
00143 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
00144 bounds.width=0;
00145 bounds.height=0;
00146 bounds.x=(long) image->columns;
00147 bounds.y=(long) image->rows;
00148 GetMagickPixelPacket(image,&target[0]);
00149 image_view=AcquireCacheView(image);
00150 p=GetCacheViewVirtualPixels(image_view,0,0,1,1,exception);
00151 if (p == (const PixelPacket *) NULL)
00152 {
00153 image_view=DestroyCacheView(image_view);
00154 return(bounds);
00155 }
00156 SetMagickPixelPacket(image,p,GetCacheViewAuthenticIndexQueue(image_view),
00157 &target[0]);
00158 GetMagickPixelPacket(image,&target[1]);
00159 p=GetCacheViewVirtualPixels(image_view,(long) image->columns-1,0,1,1,
00160 exception);
00161 SetMagickPixelPacket(image,p,GetCacheViewAuthenticIndexQueue(image_view),
00162 &target[1]);
00163 GetMagickPixelPacket(image,&target[2]);
00164 p=GetCacheViewVirtualPixels(image_view,0,(long) image->rows-1,1,1,
00165 exception);
00166 SetMagickPixelPacket(image,p,GetCacheViewAuthenticIndexQueue(image_view),
00167 &target[2]);
00168 status=MagickTrue;
00169 GetMagickPixelPacket(image,&zero);
00170 #if defined(MAGICKCORE_OPENMP_SUPPORT)
00171 #pragma omp parallel for schedule(dynamic,8) shared(status)
00172 #endif
00173 for (y=0; y < (long) image->rows; y++)
00174 {
00175 MagickPixelPacket
00176 pixel;
00177
00178 register const IndexPacket
00179 *indexes;
00180
00181 register const PixelPacket
00182 *p;
00183
00184 register long
00185 x;
00186
00187 if (status == MagickFalse)
00188 continue;
00189 p=GetCacheViewVirtualPixels(image_view,0,y,image->columns,1,exception);
00190 if (p == (const PixelPacket *) NULL)
00191 {
00192 status=MagickFalse;
00193 continue;
00194 }
00195 indexes=GetCacheViewVirtualIndexQueue(image_view);
00196 pixel=zero;
00197 for (x=0; x < (long) image->columns; x++)
00198 {
00199 SetMagickPixelPacket(image,p,indexes+x,&pixel);
00200 if ((x < bounds.x) &&
00201 (IsMagickColorSimilar(&pixel,&target[0]) == MagickFalse))
00202 bounds.x=x;
00203 if ((x > (long) bounds.width) &&
00204 (IsMagickColorSimilar(&pixel,&target[1]) == MagickFalse))
00205 bounds.width=(unsigned long) x;
00206 if ((y < bounds.y) &&
00207 (IsMagickColorSimilar(&pixel,&target[0]) == MagickFalse))
00208 bounds.y=y;
00209 if ((y > (long) bounds.height) &&
00210 (IsMagickColorSimilar(&pixel,&target[2]) == MagickFalse))
00211 bounds.height=(unsigned long) y;
00212 p++;
00213 }
00214 }
00215 image_view=DestroyCacheView(image_view);
00216 if ((bounds.width == 0) || (bounds.height == 0))
00217 (void) ThrowMagickException(exception,GetMagickModule(),OptionWarning,
00218 "GeometryDoesNotContainImage","`%s'",image->filename);
00219 else
00220 {
00221 bounds.width-=(bounds.x-1);
00222 bounds.height-=(bounds.y-1);
00223 }
00224 return(bounds);
00225 }
00226
00227
00228
00229
00230
00231
00232
00233
00234
00235
00236
00237
00238
00239
00240
00241
00242
00243
00244
00245
00246
00247
00248
00249
00250
00251
00252
00253
00254
00255
00256 MagickExport unsigned long GetImageDepth(const Image *image,
00257 ExceptionInfo *exception)
00258 {
00259 return(GetImageChannelDepth(image,AllChannels,exception));
00260 }
00261
00262 MagickExport unsigned long GetImageChannelDepth(const Image *image,
00263 const ChannelType channel,ExceptionInfo *exception)
00264 {
00265 long
00266 y;
00267
00268 MagickBooleanType
00269 status;
00270
00271 register long
00272 id;
00273
00274 unsigned long
00275 *current_depth,
00276 depth,
00277 number_threads;
00278
00279 ViewInfo
00280 *image_view;
00281
00282
00283
00284
00285 assert(image != (Image *) NULL);
00286 assert(image->signature == MagickSignature);
00287 if (image->debug != MagickFalse)
00288 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
00289 number_threads=GetPixelCacheMaximumThreads();
00290 current_depth=(unsigned long *) AcquireQuantumMemory(number_threads,
00291 sizeof(*current_depth));
00292 if (current_depth == (unsigned long *) NULL)
00293 ThrowFatalException(ResourceLimitFatalError,"MemoryAllocationFailed");
00294 status=MagickTrue;
00295 for (id=0; id < (long) number_threads; id++)
00296 current_depth[id]=1;
00297 if ((image->storage_class == PseudoClass) && (image->matte == MagickFalse))
00298 {
00299 register const PixelPacket
00300 *p;
00301
00302 register long
00303 i;
00304
00305 p=image->colormap;
00306 #if defined(MAGICKCORE_OPENMP_SUPPORT)
00307 #pragma omp parallel for schedule(dynamic,8) shared(status)
00308 #endif
00309 for (i=0; i < (long) image->colors; i++)
00310 {
00311 if (status == MagickFalse)
00312 continue;
00313 id=GetPixelCacheThreadId();
00314 while (current_depth[id] < MAGICKCORE_QUANTUM_DEPTH)
00315 {
00316 MagickStatusType
00317 status;
00318
00319 QuantumAny
00320 scale;
00321
00322 status=0;
00323 scale=GetQuantumScale(current_depth[id]);
00324 if ((channel & RedChannel) != 0)
00325 status|=p->red != ScaleAnyToQuantum(ScaleQuantumToAny(p->red,
00326 current_depth[id],scale),current_depth[id],scale);
00327 if ((channel & GreenChannel) != 0)
00328 status|=p->green != ScaleAnyToQuantum(ScaleQuantumToAny(p->green,
00329 current_depth[id],scale),current_depth[id],scale);
00330 if ((channel & BlueChannel) != 0)
00331 status|=p->blue != ScaleAnyToQuantum(ScaleQuantumToAny(p->blue,
00332 current_depth[id],scale),current_depth[id],scale);
00333 if (status == 0)
00334 break;
00335 current_depth[id]++;
00336 }
00337 p++;
00338 }
00339 depth=current_depth[0];
00340 for (id=1; id < (long) number_threads; id++)
00341 if (depth < current_depth[id])
00342 depth=current_depth[id];
00343 current_depth=(unsigned long *) RelinquishMagickMemory(current_depth);
00344 return(depth);
00345 }
00346 image_view=AcquireCacheView(image);
00347 #if defined(MAGICKCORE_OPENMP_SUPPORT)
00348 #pragma omp parallel for schedule(dynamic,8) shared(status)
00349 #endif
00350 for (y=0; y < (long) image->rows; y++)
00351 {
00352 register const IndexPacket
00353 *indexes;
00354
00355 register const PixelPacket
00356 *p;
00357
00358 register long
00359 id,
00360 x;
00361
00362 if (status == MagickFalse)
00363 continue;
00364 id=GetPixelCacheThreadId();
00365 p=GetCacheViewVirtualPixels(image_view,0,y,image->columns,1,exception);
00366 if (p == (const PixelPacket *) NULL)
00367 continue;
00368 indexes=GetCacheViewVirtualIndexQueue(image_view);
00369 for (x=0; x < (long) image->columns; x++)
00370 {
00371 while (current_depth[id] < MAGICKCORE_QUANTUM_DEPTH)
00372 {
00373 MagickStatusType
00374 status;
00375
00376 QuantumAny
00377 scale;
00378
00379 status=0;
00380 scale=GetQuantumScale(current_depth[id]);
00381 if ((channel & RedChannel) != 0)
00382 status|=p->red != ScaleAnyToQuantum(ScaleQuantumToAny(p->red,
00383 current_depth[id],scale),current_depth[id],scale);
00384 if ((channel & GreenChannel) != 0)
00385 status|=p->green != ScaleAnyToQuantum(ScaleQuantumToAny(p->green,
00386 current_depth[id],scale),current_depth[id],scale);
00387 if ((channel & BlueChannel) != 0)
00388 status|=p->blue != ScaleAnyToQuantum(ScaleQuantumToAny(p->blue,
00389 current_depth[id],scale),current_depth[id],scale);
00390 if (((channel & OpacityChannel) != 0) && (image->matte != MagickFalse))
00391 status|=p->opacity != ScaleAnyToQuantum(ScaleQuantumToAny(p->opacity,
00392 current_depth[id],scale),current_depth[id],scale);
00393 if (((channel & IndexChannel) != 0) &&
00394 (image->colorspace == CMYKColorspace))
00395 status|=indexes[x] != ScaleAnyToQuantum(ScaleQuantumToAny(indexes[x],
00396 current_depth[id],scale),current_depth[id],scale);
00397 if (status == 0)
00398 break;
00399 current_depth[id]++;
00400 }
00401 p++;
00402 }
00403 if (current_depth[id] == MAGICKCORE_QUANTUM_DEPTH)
00404 status=MagickFalse;
00405 }
00406 image_view=DestroyCacheView(image_view);
00407 depth=current_depth[0];
00408 for (id=1; id < (long) number_threads; id++)
00409 if (depth < current_depth[id])
00410 depth=current_depth[id];
00411 current_depth=(unsigned long *) RelinquishMagickMemory(current_depth);
00412 return(depth);
00413 }
00414
00415
00416
00417
00418
00419
00420
00421
00422
00423
00424
00425
00426
00427
00428
00429
00430
00431
00432
00433
00434
00435
00436
00437
00438
00439
00440
00441
00442
00443
00444
00445
00446
00447
00448 MagickExport MagickBooleanType GetImageExtrema(const Image *image,
00449 unsigned long *minima,unsigned long *maxima,ExceptionInfo *exception)
00450 {
00451 return(GetImageChannelExtrema(image,AllChannels,minima,maxima,exception));
00452 }
00453
00454 MagickExport MagickBooleanType GetImageChannelExtrema(const Image *image,
00455 const ChannelType channel,unsigned long *minima,unsigned long *maxima,
00456 ExceptionInfo *exception)
00457 {
00458 double
00459 max,
00460 min;
00461
00462 MagickBooleanType
00463 status;
00464
00465 assert(image != (Image *) NULL);
00466 assert(image->signature == MagickSignature);
00467 if (image->debug != MagickFalse)
00468 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
00469 status=GetImageChannelRange(image,channel,&min,&max,exception);
00470 *minima=(unsigned long) (min+0.5);
00471 *maxima=(unsigned long) (max+0.5);
00472 return(status);
00473 }
00474
00475
00476
00477
00478
00479
00480
00481
00482
00483
00484
00485
00486
00487
00488
00489
00490
00491
00492
00493
00494
00495
00496
00497
00498
00499
00500
00501
00502
00503
00504
00505
00506
00507
00508
00509 MagickExport MagickBooleanType GetImageMean(const Image *image,double *mean,
00510 double *standard_deviation,ExceptionInfo *exception)
00511 {
00512 MagickBooleanType
00513 status;
00514
00515 status=GetImageChannelMean(image,AllChannels,mean,standard_deviation,
00516 exception);
00517 return(status);
00518 }
00519
00520 MagickExport MagickBooleanType GetImageChannelMean(const Image *image,
00521 const ChannelType channel,double *mean,double *standard_deviation,
00522 ExceptionInfo *exception)
00523 {
00524 #define PixelSquared(x) ((x)*(x))
00525
00526 double
00527 area;
00528
00529 long
00530 y;
00531
00532 register const IndexPacket
00533 *indexes;
00534
00535 register const PixelPacket
00536 *p;
00537
00538 register long
00539 x;
00540
00541 assert(image != (Image *) NULL);
00542 assert(image->signature == MagickSignature);
00543 if (image->debug != MagickFalse)
00544 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
00545 *mean=0.0;
00546 *standard_deviation=0.0;
00547 area=0.0;
00548 for (y=0; y < (long) image->rows; y++)
00549 {
00550 p=GetVirtualPixels(image,0,y,image->columns,1,exception);
00551 if (p == (const PixelPacket *) NULL)
00552 break;
00553 indexes=GetVirtualIndexQueue(image);
00554 for (x=0; x < (long) image->columns; x++)
00555 {
00556 if ((channel & RedChannel) != 0)
00557 {
00558 *mean+=p->red;
00559 *standard_deviation+=(double) p->red*p->red;
00560 area++;
00561 }
00562 if ((channel & GreenChannel) != 0)
00563 {
00564 *mean+=p->green;
00565 *standard_deviation+=(double) p->green*p->green;
00566 area++;
00567 }
00568 if ((channel & BlueChannel) != 0)
00569 {
00570 *mean+=p->blue;
00571 *standard_deviation+=(double) p->blue*p->blue;
00572 area++;
00573 }
00574 if ((channel & OpacityChannel) != 0)
00575 {
00576 *mean+=p->opacity;
00577 *standard_deviation+=(double) p->opacity*p->opacity;
00578 area++;
00579 }
00580 if (((channel & IndexChannel) != 0) &&
00581 (image->colorspace == CMYKColorspace))
00582 {
00583 *mean+=indexes[x];
00584 *standard_deviation+=(double) indexes[x]*indexes[x];
00585 area++;
00586 }
00587 p++;
00588 }
00589 }
00590 if (y < (long) image->rows)
00591 return(MagickFalse);
00592 if (area != 0)
00593 {
00594 *mean/=area;
00595 *standard_deviation/=area;
00596 }
00597 *standard_deviation=sqrt(*standard_deviation-(*mean*(*mean)));
00598 return(y == (long) image->rows ? MagickTrue : MagickFalse);
00599 }
00600
00601
00602
00603
00604
00605
00606
00607
00608
00609
00610
00611
00612
00613
00614
00615
00616
00617
00618
00619
00620
00621
00622
00623
00624
00625
00626
00627
00628
00629
00630
00631
00632
00633
00634 MagickExport MagickBooleanType GetImageRange(const Image *image,
00635 double *minima,double *maxima,ExceptionInfo *exception)
00636 {
00637 return(GetImageChannelRange(image,AllChannels,minima,maxima,exception));
00638 }
00639
00640 MagickExport MagickBooleanType GetImageChannelRange(const Image *image,
00641 const ChannelType channel,double *minima,double *maxima,
00642 ExceptionInfo *exception)
00643 {
00644 long
00645 y;
00646
00647 MagickPixelPacket
00648 pixel;
00649
00650 register const IndexPacket
00651 *indexes;
00652
00653 register const PixelPacket
00654 *p;
00655
00656 register long
00657 x;
00658
00659 assert(image != (Image *) NULL);
00660 assert(image->signature == MagickSignature);
00661 if (image->debug != MagickFalse)
00662 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
00663 *maxima=(-1.0E-37);
00664 *minima=1.0E+37;
00665 GetMagickPixelPacket(image,&pixel);
00666 for (y=0; y < (long) image->rows; y++)
00667 {
00668 p=GetVirtualPixels(image,0,y,image->columns,1,exception);
00669 if (p == (const PixelPacket *) NULL)
00670 break;
00671 indexes=GetVirtualIndexQueue(image);
00672 for (x=0; x < (long) image->columns; x++)
00673 {
00674 SetMagickPixelPacket(image,p,indexes+x,&pixel);
00675 if ((channel & RedChannel) != 0)
00676 {
00677 if (pixel.red < *minima)
00678 *minima=(double) pixel.red;
00679 if (pixel.red > *maxima)
00680 *maxima=(double) pixel.red;
00681 }
00682 if ((channel & GreenChannel) != 0)
00683 {
00684 if (pixel.green < *minima)
00685 *minima=(double) pixel.green;
00686 if (pixel.green > *maxima)
00687 *maxima=(double) pixel.green;
00688 }
00689 if ((channel & BlueChannel) != 0)
00690 {
00691 if (pixel.blue < *minima)
00692 *minima=(double) pixel.blue;
00693 if (pixel.blue > *maxima)
00694 *maxima=(double) pixel.blue;
00695 }
00696 if ((channel & OpacityChannel) != 0)
00697 {
00698 if (pixel.opacity < *minima)
00699 *minima=(double) pixel.opacity;
00700 if (pixel.opacity > *maxima)
00701 *maxima=(double) pixel.opacity;
00702 }
00703 if (((channel & IndexChannel) != 0) &&
00704 (image->colorspace == CMYKColorspace))
00705 {
00706 if ((double) indexes[x] < *minima)
00707 *minima=(double) indexes[x];
00708 if ((double) indexes[x] > *maxima)
00709 *maxima=(double) indexes[x];
00710 }
00711 p++;
00712 }
00713 }
00714 return(y == (long) image->rows ? MagickTrue : MagickFalse);
00715 }
00716
00717
00718
00719
00720
00721
00722
00723
00724
00725
00726
00727
00728
00729
00730
00731
00732
00733
00734
00735
00736
00737
00738
00739
00740
00741
00742
00743
00744
00745
00746
00747
00748
00749
00750
00751 static inline double MagickMax(const double x,const double y)
00752 {
00753 if (x > y)
00754 return(x);
00755 return(y);
00756 }
00757
00758 static inline double MagickMin(const double x,const double y)
00759 {
00760 if (x < y)
00761 return(x);
00762 return(y);
00763 }
00764
00765 MagickExport ChannelStatistics *GetImageChannelStatistics(const Image *image,
00766 ExceptionInfo *exception)
00767 {
00768 ChannelStatistics
00769 *channel_statistics;
00770
00771 double
00772 area;
00773
00774 long
00775 y;
00776
00777 MagickStatusType
00778 status;
00779
00780 QuantumAny
00781 scale;
00782
00783 register const IndexPacket
00784 *indexes;
00785
00786 register const PixelPacket
00787 *p;
00788
00789 register long
00790 i,
00791 x;
00792
00793 size_t
00794 length;
00795
00796 unsigned long
00797 channels,
00798 depth;
00799
00800 assert(image != (Image *) NULL);
00801 assert(image->signature == MagickSignature);
00802 if (image->debug != MagickFalse)
00803 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
00804 length=AllChannels+1UL;
00805 channel_statistics=(ChannelStatistics *) AcquireQuantumMemory(length,
00806 sizeof(*channel_statistics));
00807 if (channel_statistics == (ChannelStatistics *) NULL)
00808 ThrowFatalException(ResourceLimitFatalError,"MemoryAllocationFailed");
00809 (void) ResetMagickMemory(channel_statistics,0,length*
00810 sizeof(*channel_statistics));
00811 for (i=0; i <= AllChannels; i++)
00812 {
00813 channel_statistics[i].depth=1;
00814 channel_statistics[i].maxima=(-1.0E-37);
00815 channel_statistics[i].minima=1.0E+37;
00816 channel_statistics[i].mean=0.0;
00817 channel_statistics[i].standard_deviation=0.0;
00818 }
00819 y=(long) image->rows;
00820 for (y=0; y < (long) image->rows; y++)
00821 {
00822 p=GetVirtualPixels(image,0,y,image->columns,1,exception);
00823 if (p == (const PixelPacket *) NULL)
00824 break;
00825 indexes=GetVirtualIndexQueue(image);
00826 for (x=0; x < (long) image->columns; )
00827 {
00828 if (channel_statistics[RedChannel].depth != MAGICKCORE_QUANTUM_DEPTH)
00829 {
00830 depth=channel_statistics[RedChannel].depth;
00831 scale=GetQuantumScale(depth);
00832 status=p->red != ScaleAnyToQuantum(ScaleQuantumToAny(p->red,depth,
00833 scale),depth,scale) ? MagickTrue : MagickFalse;
00834 if (status != MagickFalse)
00835 {
00836 channel_statistics[RedChannel].depth++;
00837 continue;
00838 }
00839 }
00840 if (channel_statistics[GreenChannel].depth != MAGICKCORE_QUANTUM_DEPTH)
00841 {
00842 depth=channel_statistics[GreenChannel].depth;
00843 scale=GetQuantumScale(depth);
00844 status=p->green != ScaleAnyToQuantum(ScaleQuantumToAny(p->green,
00845 depth,scale),depth,scale) ? MagickTrue : MagickFalse;
00846 if (status != MagickFalse)
00847 {
00848 channel_statistics[GreenChannel].depth++;
00849 continue;
00850 }
00851 }
00852 if (channel_statistics[BlueChannel].depth != MAGICKCORE_QUANTUM_DEPTH)
00853 {
00854 depth=channel_statistics[BlueChannel].depth;
00855 scale=GetQuantumScale(depth);
00856 status=p->blue != ScaleAnyToQuantum(ScaleQuantumToAny(p->blue,
00857 depth,scale),depth,scale) ? MagickTrue : MagickFalse;
00858 if (status != MagickFalse)
00859 {
00860 channel_statistics[BlueChannel].depth++;
00861 continue;
00862 }
00863 }
00864 if (channel_statistics[OpacityChannel].depth != MAGICKCORE_QUANTUM_DEPTH)
00865 {
00866 depth=channel_statistics[OpacityChannel].depth;
00867 scale=GetQuantumScale(depth);
00868 status=p->opacity != ScaleAnyToQuantum(ScaleQuantumToAny(p->opacity,
00869 depth,scale),depth,scale) ? MagickTrue : MagickFalse;
00870 if (status != MagickFalse)
00871 {
00872 channel_statistics[OpacityChannel].depth++;
00873 continue;
00874 }
00875 }
00876 if (image->colorspace == CMYKColorspace)
00877 {
00878 if (channel_statistics[BlackChannel].depth != MAGICKCORE_QUANTUM_DEPTH)
00879 {
00880 depth=channel_statistics[BlackChannel].depth;
00881 scale=GetQuantumScale(depth);
00882 status=indexes[x] != ScaleAnyToQuantum(ScaleQuantumToAny(
00883 indexes[x],depth,scale),depth,scale) ? MagickTrue : MagickFalse;
00884 if (status != MagickFalse)
00885 {
00886 channel_statistics[BlackChannel].depth++;
00887 continue;
00888 }
00889 }
00890 }
00891 if ((double) p->red < channel_statistics[RedChannel].minima)
00892 channel_statistics[RedChannel].minima=(double) p->red;
00893 if ((double) p->red > channel_statistics[RedChannel].maxima)
00894 channel_statistics[RedChannel].maxima=(double) p->red;
00895 channel_statistics[RedChannel].mean+=p->red;
00896 channel_statistics[RedChannel].standard_deviation+=(double)
00897 p->red*p->red;
00898 if ((double) p->green < channel_statistics[GreenChannel].minima)
00899 channel_statistics[GreenChannel].minima=(double) p->green;
00900 if ((double) p->green > channel_statistics[GreenChannel].maxima)
00901 channel_statistics[GreenChannel].maxima=(double) p->green;
00902 channel_statistics[GreenChannel].mean+=p->green;
00903 channel_statistics[GreenChannel].standard_deviation+=(double)
00904 p->green*p->green;
00905 if ((double) p->blue < channel_statistics[BlueChannel].minima)
00906 channel_statistics[BlueChannel].minima=(double) p->blue;
00907 if ((double) p->blue > channel_statistics[BlueChannel].maxima)
00908 channel_statistics[BlueChannel].maxima=(double) p->blue;
00909 channel_statistics[BlueChannel].mean+=p->blue;
00910 channel_statistics[BlueChannel].standard_deviation+=(double)
00911 p->blue*p->blue;
00912 if ((double) p->opacity < channel_statistics[OpacityChannel].minima)
00913 channel_statistics[OpacityChannel].minima=(double) p->opacity;
00914 if ((double) p->opacity > channel_statistics[OpacityChannel].maxima)
00915 channel_statistics[OpacityChannel].maxima=(double) p->opacity;
00916 channel_statistics[OpacityChannel].mean+=p->opacity;
00917 channel_statistics[OpacityChannel].standard_deviation+=(double)
00918 p->opacity*p->opacity;
00919 if (image->colorspace == CMYKColorspace)
00920 {
00921 if ((double) indexes[x] < channel_statistics[BlackChannel].minima)
00922 channel_statistics[BlackChannel].minima=(double) indexes[x];
00923 if ((double) indexes[x] > channel_statistics[BlackChannel].maxima)
00924 channel_statistics[BlackChannel].maxima=(double) indexes[x];
00925 channel_statistics[BlackChannel].mean+=indexes[x];
00926 channel_statistics[BlackChannel].standard_deviation+=(double)
00927 indexes[x]*indexes[x];
00928 }
00929 x++;
00930 p++;
00931 }
00932 }
00933 area=(double) image->columns*image->rows;
00934 for (i=0; i < AllChannels; i++)
00935 {
00936 channel_statistics[i].mean/=area;
00937 channel_statistics[i].standard_deviation/=area;
00938 }
00939 for (i=0; i < AllChannels; i++)
00940 {
00941 channel_statistics[AllChannels].depth=(unsigned long) MagickMax((double)
00942 channel_statistics[AllChannels].depth,(double)
00943 channel_statistics[i].depth);
00944 channel_statistics[AllChannels].minima=MagickMin(
00945 channel_statistics[AllChannels].minima,channel_statistics[i].minima);
00946 channel_statistics[AllChannels].maxima=MagickMax(
00947 channel_statistics[AllChannels].maxima,channel_statistics[i].maxima);
00948 channel_statistics[AllChannels].mean+=channel_statistics[i].mean;
00949 channel_statistics[AllChannels].standard_deviation+=
00950 channel_statistics[i].standard_deviation;
00951 }
00952 channels=4;
00953 if (image->colorspace == CMYKColorspace)
00954 channels++;
00955 channel_statistics[AllChannels].mean/=channels;
00956 channel_statistics[AllChannels].standard_deviation/=channels;
00957 for (i=0; i <= AllChannels; i++)
00958 channel_statistics[i].standard_deviation=sqrt(
00959 channel_statistics[i].standard_deviation-
00960 (channel_statistics[i].mean*channel_statistics[i].mean));
00961 return(channel_statistics);
00962 }
00963
00964
00965
00966
00967
00968
00969
00970
00971
00972
00973
00974
00975
00976
00977
00978
00979
00980
00981