attribute.c

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

Generated on 19 Nov 2009 for MagickCore by  doxygen 1.6.1