MagickCore  6.7.5
decorate.c
Go to the documentation of this file.
00001 /*
00002 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
00003 %                                                                             %
00004 %                                                                             %
00005 %                                                                             %
00006 %            DDDD   EEEEE   CCCC   OOO   RRRR    AAA   TTTTT  EEEEE           %
00007 %            D   D  E      C      O   O  R   R  A   A    T    E               %
00008 %            D   D  EEE    C      O   O  RRRR   AAAAA    T    EEE             %
00009 %            D   D  E      C      O   O  R R    A   A    T    E               %
00010 %            DDDD   EEEEE   CCCC   OOO   R  R   A   A    T    EEEEE           %
00011 %                                                                             %
00012 %                                                                             %
00013 %                     MagickCore Image Decoration Methods                     %
00014 %                                                                             %
00015 %                                Software Design                              %
00016 %                                  John Cristy                                %
00017 %                                   July 1992                                 %
00018 %                                                                             %
00019 %                                                                             %
00020 %  Copyright 1999-2012 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 "MagickCore/studio.h"
00044 #include "MagickCore/cache-view.h"
00045 #include "MagickCore/color-private.h"
00046 #include "MagickCore/colorspace-private.h"
00047 #include "MagickCore/composite.h"
00048 #include "MagickCore/decorate.h"
00049 #include "MagickCore/exception.h"
00050 #include "MagickCore/exception-private.h"
00051 #include "MagickCore/image.h"
00052 #include "MagickCore/memory_.h"
00053 #include "MagickCore/monitor.h"
00054 #include "MagickCore/monitor-private.h"
00055 #include "MagickCore/pixel-accessor.h"
00056 #include "MagickCore/quantum.h"
00057 #include "MagickCore/quantum-private.h"
00058 #include "MagickCore/thread-private.h"
00059 #include "MagickCore/transform.h"
00060 
00061 /*
00062   Define declarations.
00063 */
00064 #define AccentuateModulate  ScaleCharToQuantum(80)
00065 #define HighlightModulate  ScaleCharToQuantum(125)
00066 #define ShadowModulate  ScaleCharToQuantum(135)
00067 #define DepthModulate  ScaleCharToQuantum(185)
00068 #define TroughModulate  ScaleCharToQuantum(110)
00069 
00070 /*
00071 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
00072 %                                                                             %
00073 %                                                                             %
00074 %                                                                             %
00075 %   B o r d e r I m a g e                                                     %
00076 %                                                                             %
00077 %                                                                             %
00078 %                                                                             %
00079 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
00080 %
00081 %  BorderImage() surrounds the image with a border of the color defined by
00082 %  the bordercolor member of the image structure.  The width and height
00083 %  of the border are defined by the corresponding members of the border_info
00084 %  structure.
00085 %
00086 %  The format of the BorderImage method is:
00087 %
00088 %      Image *BorderImage(const Image *image,const RectangleInfo *border_info,
00089 %        const CompositeOperator compose,ExceptionInfo *exception)
00090 %
00091 %  A description of each parameter follows:
00092 %
00093 %    o image: the image.
00094 %
00095 %    o border_info:  define the width and height of the border.
00096 %
00097 %    o compose:  the composite operator.
00098 %
00099 %    o exception: return any errors or warnings in this structure.
00100 %
00101 */
00102 MagickExport Image *BorderImage(const Image *image,
00103   const RectangleInfo *border_info,const CompositeOperator compose,
00104   ExceptionInfo *exception)
00105 {
00106   Image
00107     *border_image,
00108     *clone_image;
00109 
00110   FrameInfo
00111     frame_info;
00112 
00113   assert(image != (const Image *) NULL);
00114   assert(image->signature == MagickSignature);
00115   if (image->debug != MagickFalse)
00116     (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
00117   assert(border_info != (RectangleInfo *) NULL);
00118   frame_info.width=image->columns+(border_info->width << 1);
00119   frame_info.height=image->rows+(border_info->height << 1);
00120   frame_info.x=(ssize_t) border_info->width;
00121   frame_info.y=(ssize_t) border_info->height;
00122   frame_info.inner_bevel=0;
00123   frame_info.outer_bevel=0;
00124   clone_image=CloneImage(image,0,0,MagickTrue,exception);
00125   if (clone_image == (Image *) NULL)
00126     return((Image *) NULL);
00127   clone_image->matte_color=image->border_color;
00128   border_image=FrameImage(clone_image,&frame_info,compose,exception);
00129   clone_image=DestroyImage(clone_image);
00130   if (border_image != (Image *) NULL)
00131     border_image->matte_color=image->matte_color;
00132   return(border_image);
00133 }
00134 
00135 /*
00136 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
00137 %                                                                             %
00138 %                                                                             %
00139 %                                                                             %
00140 %   F r a m e I m a g e                                                       %
00141 %                                                                             %
00142 %                                                                             %
00143 %                                                                             %
00144 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
00145 %
00146 %  FrameImage() adds a simulated three-dimensional border around the image.
00147 %  The color of the border is defined by the matte_color member of image.
00148 %  Members width and height of frame_info specify the border width of the
00149 %  vertical and horizontal sides of the frame.  Members inner and outer
00150 %  indicate the width of the inner and outer shadows of the frame.
00151 %
00152 %  The format of the FrameImage method is:
00153 %
00154 %      Image *FrameImage(const Image *image,const FrameInfo *frame_info,
00155 %        const CompositeOperator compose,ExceptionInfo *exception)
00156 %
00157 %  A description of each parameter follows:
00158 %
00159 %    o image: the image.
00160 %
00161 %    o frame_info: Define the width and height of the frame and its bevels.
00162 %
00163 %    o compose: the composite operator.
00164 %
00165 %    o exception: return any errors or warnings in this structure.
00166 %
00167 */
00168 MagickExport Image *FrameImage(const Image *image,const FrameInfo *frame_info,
00169   const CompositeOperator compose,ExceptionInfo *exception)
00170 {
00171 #define FrameImageTag  "Frame/Image"
00172 
00173   CacheView
00174     *image_view,
00175     *frame_view;
00176 
00177   Image
00178     *frame_image;
00179 
00180   MagickBooleanType
00181     status;
00182 
00183   MagickOffsetType
00184     progress;
00185 
00186   PixelInfo
00187     accentuate,
00188     highlight,
00189     interior,
00190     matte,
00191     shadow,
00192     trough;
00193 
00194   register ssize_t
00195     x;
00196 
00197   size_t
00198     bevel_width,
00199     height,
00200     width;
00201 
00202   ssize_t
00203     y;
00204 
00205   /*
00206     Check frame geometry.
00207   */
00208   assert(image != (Image *) NULL);
00209   assert(image->signature == MagickSignature);
00210   if (image->debug != MagickFalse)
00211     (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
00212   assert(frame_info != (FrameInfo *) NULL);
00213   if ((frame_info->outer_bevel < 0) || (frame_info->inner_bevel < 0))
00214     ThrowImageException(OptionError,"FrameIsLessThanImageSize");
00215   bevel_width=(size_t) (frame_info->outer_bevel+frame_info->inner_bevel);
00216   width=frame_info->width-frame_info->x-bevel_width;
00217   height=frame_info->height-frame_info->y-bevel_width;
00218   if ((width < image->columns) || (height < image->rows))
00219     ThrowImageException(OptionError,"FrameIsLessThanImageSize");
00220   /*
00221     Initialize framed image attributes.
00222   */
00223   frame_image=CloneImage(image,frame_info->width,frame_info->height,MagickTrue,
00224     exception);
00225   if (frame_image == (Image *) NULL)
00226     return((Image *) NULL);
00227   if (SetImageStorageClass(frame_image,DirectClass,exception) == MagickFalse)
00228     {
00229       frame_image=DestroyImage(frame_image);
00230       return((Image *) NULL);
00231     }
00232   if (frame_image->matte_color.alpha != OpaqueAlpha)
00233     frame_image->matte=MagickTrue;
00234   frame_image->page=image->page;
00235   if ((image->page.width != 0) && (image->page.height != 0))
00236     {
00237       frame_image->page.width+=frame_image->columns-image->columns;
00238       frame_image->page.height+=frame_image->rows-image->rows;
00239     }
00240   /*
00241     Initialize 3D effects color.
00242   */
00243   interior=image->border_color;
00244   matte=image->matte_color;
00245   accentuate=matte;
00246   accentuate.red=(MagickRealType) (QuantumScale*((QuantumRange-
00247     AccentuateModulate)*matte.red+(QuantumRange*AccentuateModulate)));
00248   accentuate.green=(MagickRealType) (QuantumScale*((QuantumRange-
00249     AccentuateModulate)*matte.green+(QuantumRange*AccentuateModulate)));
00250   accentuate.blue=(MagickRealType) (QuantumScale*((QuantumRange-
00251     AccentuateModulate)*matte.blue+(QuantumRange*AccentuateModulate)));
00252   accentuate.black=(MagickRealType) (QuantumScale*((QuantumRange-
00253     AccentuateModulate)*matte.black+(QuantumRange*AccentuateModulate)));
00254   accentuate.alpha=matte.alpha;
00255   highlight=matte;
00256   highlight.red=(MagickRealType) (QuantumScale*((QuantumRange-
00257     HighlightModulate)*matte.red+(QuantumRange*HighlightModulate)));
00258   highlight.green=(MagickRealType) (QuantumScale*((QuantumRange-
00259     HighlightModulate)*matte.green+(QuantumRange*HighlightModulate)));
00260   highlight.blue=(MagickRealType) (QuantumScale*((QuantumRange-
00261     HighlightModulate)*matte.blue+(QuantumRange*HighlightModulate)));
00262   highlight.black=(MagickRealType) (QuantumScale*((QuantumRange-
00263     HighlightModulate)*matte.black+(QuantumRange*HighlightModulate)));
00264   highlight.alpha=matte.alpha;
00265   shadow=matte;
00266   shadow.red=QuantumScale*matte.red*ShadowModulate;
00267   shadow.green=QuantumScale*matte.green*ShadowModulate;
00268   shadow.blue=QuantumScale*matte.blue*ShadowModulate;
00269   shadow.black=QuantumScale*matte.black*ShadowModulate;
00270   shadow.alpha=matte.alpha;
00271   trough=matte;
00272   trough.red=QuantumScale*matte.red*TroughModulate;
00273   trough.green=QuantumScale*matte.green*TroughModulate;
00274   trough.blue=QuantumScale*matte.blue*TroughModulate;
00275   trough.black=QuantumScale*matte.black*TroughModulate;
00276   trough.alpha=matte.alpha;
00277   status=MagickTrue;
00278   progress=0;
00279   image_view=AcquireCacheView(image);
00280   frame_view=AcquireCacheView(frame_image);
00281   height=(size_t) (frame_info->outer_bevel+(frame_info->y-bevel_width)+
00282     frame_info->inner_bevel);
00283   if (height != 0)
00284     {
00285       register ssize_t
00286         x;
00287 
00288       register Quantum
00289         *restrict q;
00290 
00291       /*
00292         Draw top of ornamental border.
00293       */
00294       q=QueueCacheViewAuthenticPixels(frame_view,0,0,frame_image->columns,
00295         height,exception);
00296       if (q != (Quantum *) NULL)
00297         {
00298           /*
00299             Draw top of ornamental border.
00300           */
00301           for (y=0; y < (ssize_t) frame_info->outer_bevel; y++)
00302           {
00303             for (x=0; x < (ssize_t) (frame_image->columns-y); x++)
00304             {
00305               if (x < y)
00306                 SetPixelInfoPixel(frame_image,&highlight,q);
00307               else
00308                 SetPixelInfoPixel(frame_image,&accentuate,q);
00309               q+=GetPixelChannels(frame_image);
00310             }
00311             for ( ; x < (ssize_t) frame_image->columns; x++)
00312             {
00313               SetPixelInfoPixel(frame_image,&shadow,q);
00314               q+=GetPixelChannels(frame_image);
00315             }
00316           }
00317           for (y=0; y < (ssize_t) (frame_info->y-bevel_width); y++)
00318           {
00319             for (x=0; x < (ssize_t) frame_info->outer_bevel; x++)
00320             {
00321               SetPixelInfoPixel(frame_image,&highlight,q);
00322               q+=GetPixelChannels(frame_image);
00323             }
00324             width=frame_image->columns-2*frame_info->outer_bevel;
00325             for (x=0; x < (ssize_t) width; x++)
00326             {
00327               SetPixelInfoPixel(frame_image,&matte,q);
00328               q+=GetPixelChannels(frame_image);
00329             }
00330             for (x=0; x < (ssize_t) frame_info->outer_bevel; x++)
00331             {
00332               SetPixelInfoPixel(frame_image,&shadow,q);
00333               q+=GetPixelChannels(frame_image);
00334             }
00335           }
00336           for (y=0; y < (ssize_t) frame_info->inner_bevel; y++)
00337           {
00338             for (x=0; x < (ssize_t) frame_info->outer_bevel; x++)
00339             {
00340               SetPixelInfoPixel(frame_image,&highlight,q);
00341               q+=GetPixelChannels(frame_image);
00342             }
00343             for (x=0; x < (ssize_t) (frame_info->x-bevel_width); x++)
00344             {
00345               SetPixelInfoPixel(frame_image,&matte,q);
00346               q+=GetPixelChannels(frame_image);
00347             }
00348             width=image->columns+((size_t) frame_info->inner_bevel << 1)-
00349               y;
00350             for (x=0; x < (ssize_t) width; x++)
00351             {
00352               if (x < y)
00353                 SetPixelInfoPixel(frame_image,&shadow,q);
00354               else
00355                 SetPixelInfoPixel(frame_image,&trough,q);
00356               q+=GetPixelChannels(frame_image);
00357             }
00358             for ( ; x < (ssize_t) (image->columns+2*frame_info->inner_bevel); x++)
00359             {
00360               SetPixelInfoPixel(frame_image,&highlight,q);
00361               q+=GetPixelChannels(frame_image);
00362             }
00363             width=frame_info->width-frame_info->x-image->columns-bevel_width;
00364             for (x=0; x < (ssize_t) width; x++)
00365             {
00366               SetPixelInfoPixel(frame_image,&matte,q);
00367               q+=GetPixelChannels(frame_image);
00368             }
00369             for (x=0; x < (ssize_t) frame_info->outer_bevel; x++)
00370             {
00371               SetPixelInfoPixel(frame_image,&shadow,q);
00372               q+=GetPixelChannels(frame_image);
00373             }
00374           }
00375           (void) SyncCacheViewAuthenticPixels(frame_view,exception);
00376         }
00377     }
00378   /*
00379     Draw sides of ornamental border.
00380   */
00381 #if defined(MAGICKCORE_OPENMP_SUPPORT) 
00382   #pragma omp parallel for schedule(static) shared(progress,status)
00383 #endif
00384   for (y=0; y < (ssize_t) image->rows; y++)
00385   {
00386     register ssize_t
00387       x;
00388 
00389     register Quantum
00390       *restrict q;
00391 
00392     size_t
00393       width;
00394 
00395     /*
00396       Initialize scanline with matte color.
00397     */
00398     if (status == MagickFalse)
00399       continue;
00400     q=QueueCacheViewAuthenticPixels(frame_view,0,frame_info->y+y,
00401       frame_image->columns,1,exception);
00402     if (q == (Quantum *) NULL)
00403       {
00404         status=MagickFalse;
00405         continue;
00406       }
00407     for (x=0; x < (ssize_t) frame_info->outer_bevel; x++)
00408     {
00409       SetPixelInfoPixel(frame_image,&highlight,q);
00410       q+=GetPixelChannels(frame_image);
00411     }
00412     for (x=0; x < (ssize_t) (frame_info->x-bevel_width); x++)
00413     {
00414       SetPixelInfoPixel(frame_image,&matte,q);
00415       q+=GetPixelChannels(frame_image);
00416     }
00417     for (x=0; x < (ssize_t) frame_info->inner_bevel; x++)
00418     {
00419       SetPixelInfoPixel(frame_image,&shadow,q);
00420       q+=GetPixelChannels(frame_image);
00421     }
00422     /*
00423       Set frame interior to interior color.
00424     */
00425     if ((compose != CopyCompositeOp) && ((compose != OverCompositeOp) ||
00426         (image->matte != MagickFalse)))
00427       for (x=0; x < (ssize_t) image->columns; x++)
00428       {
00429         SetPixelInfoPixel(frame_image,&interior,q);
00430         q+=GetPixelChannels(frame_image);
00431       }
00432     else
00433       {
00434         register const Quantum
00435           *p;
00436 
00437         p=GetCacheViewVirtualPixels(image_view,0,y,image->columns,1,exception);
00438         if (p == (const Quantum *) NULL)
00439           {
00440             status=MagickFalse;
00441             continue;
00442           }
00443         for (x=0; x < (ssize_t) image->columns; x++)
00444         {
00445           if ((GetPixelRedTraits(image) & UpdatePixelTrait) != 0)
00446             SetPixelRed(frame_image,GetPixelRed(image,p),q);
00447           if ((GetPixelGreenTraits(image) & UpdatePixelTrait) != 0)
00448             SetPixelGreen(frame_image,GetPixelGreen(image,p),q);
00449           if ((GetPixelBlueTraits(image) & UpdatePixelTrait) != 0)
00450             SetPixelBlue(frame_image,GetPixelBlue(image,p),q);
00451           if ((GetPixelBlackTraits(image) & UpdatePixelTrait) != 0)
00452             SetPixelBlack(frame_image,GetPixelBlack(image,p),q);
00453           if ((GetPixelAlphaTraits(image) & UpdatePixelTrait) != 0)
00454             SetPixelAlpha(frame_image,GetPixelAlpha(image,p),q);
00455           p+=GetPixelChannels(image);
00456           q+=GetPixelChannels(frame_image);
00457         }
00458       }
00459     for (x=0; x < (ssize_t) frame_info->inner_bevel; x++)
00460     {
00461       SetPixelInfoPixel(frame_image,&highlight,q);
00462       q+=GetPixelChannels(frame_image);
00463     }
00464     width=frame_info->width-frame_info->x-image->columns-bevel_width;
00465     for (x=0; x < (ssize_t) width; x++)
00466     {
00467       SetPixelInfoPixel(frame_image,&matte,q);
00468       q+=GetPixelChannels(frame_image);
00469     }
00470     for (x=0; x < (ssize_t) frame_info->outer_bevel; x++)
00471     {
00472       SetPixelInfoPixel(frame_image,&shadow,q);
00473       q+=GetPixelChannels(frame_image);
00474     }
00475     if (SyncCacheViewAuthenticPixels(frame_view,exception) == MagickFalse)
00476       status=MagickFalse;
00477     if (image->progress_monitor != (MagickProgressMonitor) NULL)
00478       {
00479         MagickBooleanType
00480           proceed;
00481 
00482 #if defined(MAGICKCORE_OPENMP_SUPPORT) 
00483         #pragma omp critical (MagickCore_FrameImage)
00484 #endif
00485         proceed=SetImageProgress(image,FrameImageTag,progress++,image->rows);
00486         if (proceed == MagickFalse)
00487           status=MagickFalse;
00488       }
00489   }
00490   height=(size_t) (frame_info->inner_bevel+frame_info->height-
00491     frame_info->y-image->rows-bevel_width+frame_info->outer_bevel);
00492   if (height != 0)
00493     {
00494       register ssize_t
00495         x;
00496 
00497       register Quantum
00498         *restrict q;
00499 
00500       /*
00501         Draw bottom of ornamental border.
00502       */
00503       q=QueueCacheViewAuthenticPixels(frame_view,0,(ssize_t) (frame_image->rows-
00504         height),frame_image->columns,height,exception);
00505       if (q != (Quantum *) NULL)
00506         {
00507           /*
00508             Draw bottom of ornamental border.
00509           */
00510           for (y=frame_info->inner_bevel-1; y >= 0; y--)
00511           {
00512             for (x=0; x < (ssize_t) frame_info->outer_bevel; x++)
00513             {
00514               SetPixelInfoPixel(frame_image,&highlight,q);
00515               q+=GetPixelChannels(frame_image);
00516             }
00517             for (x=0; x < (ssize_t) (frame_info->x-bevel_width); x++)
00518             {
00519               SetPixelInfoPixel(frame_image,&matte,q);
00520               q+=GetPixelChannels(frame_image);
00521             }
00522             for (x=0; x < y; x++)
00523             {
00524               SetPixelInfoPixel(frame_image,&shadow,q);
00525               q+=GetPixelChannels(frame_image);
00526             }
00527             for ( ; x < (ssize_t) (image->columns+2*frame_info->inner_bevel); x++)
00528             {
00529               if (x >= (ssize_t) (image->columns+2*frame_info->inner_bevel-y))
00530                 SetPixelInfoPixel(frame_image,&highlight,q);
00531               else
00532                 SetPixelInfoPixel(frame_image,&accentuate,q);
00533               q+=GetPixelChannels(frame_image);
00534             }
00535             width=frame_info->width-frame_info->x-image->columns-bevel_width;
00536             for (x=0; x < (ssize_t) width; x++)
00537             {
00538               SetPixelInfoPixel(frame_image,&matte,q);
00539               q+=GetPixelChannels(frame_image);
00540             }
00541             for (x=0; x < (ssize_t) frame_info->outer_bevel; x++)
00542             {
00543               SetPixelInfoPixel(frame_image,&shadow,q);
00544               q+=GetPixelChannels(frame_image);
00545             }
00546           }
00547           height=frame_info->height-frame_info->y-image->rows-bevel_width;
00548           for (y=0; y < (ssize_t) height; y++)
00549           {
00550             for (x=0; x < (ssize_t) frame_info->outer_bevel; x++)
00551             {
00552               SetPixelInfoPixel(frame_image,&highlight,q);
00553               q+=GetPixelChannels(frame_image);
00554             }
00555             width=frame_image->columns-2*frame_info->outer_bevel;
00556             for (x=0; x < (ssize_t) width; x++)
00557             {
00558               SetPixelInfoPixel(frame_image,&matte,q);
00559               q+=GetPixelChannels(frame_image);
00560             }
00561             for (x=0; x < (ssize_t) frame_info->outer_bevel; x++)
00562             {
00563               SetPixelInfoPixel(frame_image,&shadow,q);
00564               q+=GetPixelChannels(frame_image);
00565             }
00566           }
00567           for (y=frame_info->outer_bevel-1; y >= 0; y--)
00568           {
00569             for (x=0; x < y; x++)
00570             {
00571               SetPixelInfoPixel(frame_image,&highlight,q);
00572               q+=GetPixelChannels(frame_image);
00573             }
00574             for ( ; x < (ssize_t) frame_image->columns; x++)
00575             {
00576               if (x >= (ssize_t) (frame_image->columns-y))
00577                 SetPixelInfoPixel(frame_image,&shadow,q);
00578               else
00579                 SetPixelInfoPixel(frame_image,&trough,q);
00580               q+=GetPixelChannels(frame_image);
00581             }
00582           }
00583           (void) SyncCacheViewAuthenticPixels(frame_view,exception);
00584         }
00585     }
00586   frame_view=DestroyCacheView(frame_view);
00587   image_view=DestroyCacheView(image_view);
00588   if ((compose != CopyCompositeOp) && ((compose != OverCompositeOp) ||
00589       (image->matte != MagickFalse)))
00590     {
00591       x=(ssize_t) (frame_info->outer_bevel+(frame_info->x-bevel_width)+
00592         frame_info->inner_bevel);
00593       y=(ssize_t) (frame_info->outer_bevel+(frame_info->y-bevel_width)+
00594         frame_info->inner_bevel);
00595       (void) CompositeImage(frame_image,compose,image,x,y,exception);
00596     }
00597   return(frame_image);
00598 }
00599 
00600 /*
00601 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
00602 %                                                                             %
00603 %                                                                             %
00604 %                                                                             %
00605 %   R a i s e I m a g e                                                       %
00606 %                                                                             %
00607 %                                                                             %
00608 %                                                                             %
00609 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
00610 %
00611 %  RaiseImage() creates a simulated three-dimensional button-like effect
00612 %  by lightening and darkening the edges of the image.  Members width and
00613 %  height of raise_info define the width of the vertical and horizontal
00614 %  edge of the effect.
00615 %
00616 %  The format of the RaiseImage method is:
00617 %
00618 %      MagickBooleanType RaiseImage(const Image *image,
00619 %        const RectangleInfo *raise_info,const MagickBooleanType raise,
00620 %        ExceptionInfo *exception)
00621 %
00622 %  A description of each parameter follows:
00623 %
00624 %    o image: the image.
00625 %
00626 %    o raise_info: Define the width and height of the raise area.
00627 %
00628 %    o raise: A value other than zero creates a 3-D raise effect,
00629 %      otherwise it has a lowered effect.
00630 %
00631 %    o exception: return any errors or warnings in this structure.
00632 %
00633 */
00634 MagickExport MagickBooleanType RaiseImage(Image *image,
00635   const RectangleInfo *raise_info,const MagickBooleanType raise,
00636   ExceptionInfo *exception)
00637 {
00638 #define AccentuateFactor  ScaleCharToQuantum(135)
00639 #define HighlightFactor  ScaleCharToQuantum(190)
00640 #define ShadowFactor  ScaleCharToQuantum(190)
00641 #define RaiseImageTag  "Raise/Image"
00642 #define TroughFactor  ScaleCharToQuantum(135)
00643 
00644   CacheView
00645     *image_view;
00646 
00647   MagickBooleanType
00648     status;
00649 
00650   MagickOffsetType
00651     progress;
00652 
00653   Quantum
00654     foreground,
00655     background;
00656 
00657   ssize_t
00658     y;
00659 
00660   assert(image != (Image *) NULL);
00661   assert(image->signature == MagickSignature);
00662   if (image->debug != MagickFalse)
00663     (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
00664   assert(raise_info != (RectangleInfo *) NULL);
00665   if ((image->columns <= (raise_info->width << 1)) ||
00666       (image->rows <= (raise_info->height << 1)))
00667     ThrowBinaryException(OptionError,"ImageSizeMustExceedBevelWidth",
00668       image->filename);
00669   foreground=(Quantum) QuantumRange;
00670   background=(Quantum) 0;
00671   if (raise == MagickFalse)
00672     {
00673       foreground=(Quantum) 0;
00674       background=(Quantum) QuantumRange;
00675     }
00676   if (SetImageStorageClass(image,DirectClass,exception) == MagickFalse)
00677     return(MagickFalse);
00678   /*
00679     Raise image.
00680   */
00681   status=MagickTrue;
00682   progress=0;
00683   image_view=AcquireCacheView(image);
00684 #if defined(MAGICKCORE_OPENMP_SUPPORT) 
00685   #pragma omp parallel for schedule(static) shared(progress,status)
00686 #endif
00687   for (y=0; y < (ssize_t) raise_info->height; y++)
00688   {
00689     register ssize_t
00690       i,
00691       x;
00692 
00693     register Quantum
00694       *restrict q;
00695 
00696     if (status == MagickFalse)
00697       continue;
00698     q=GetCacheViewAuthenticPixels(image_view,0,y,image->columns,1,exception);
00699     if (q == (Quantum *) NULL)
00700       {
00701         status=MagickFalse;
00702         continue;
00703       }
00704     for (x=0; x < y; x++)
00705     {
00706       if (GetPixelMask(image,q) != 0)
00707         {
00708           q+=GetPixelChannels(image);
00709           continue;
00710         }
00711       for (i=0; i < (ssize_t) GetPixelChannels(image); i++)
00712       {
00713         PixelChannel
00714           channel;
00715 
00716         PixelTrait
00717           traits;
00718 
00719         channel=GetPixelChannelMapChannel(image,i);
00720         traits=GetPixelChannelMapTraits(image,channel);
00721         if ((traits & UpdatePixelTrait) == 0)
00722           continue;
00723         q[i]=ClampToQuantum(QuantumScale*((MagickRealType) q[i]*HighlightFactor+
00724           (MagickRealType) foreground*(QuantumRange-HighlightFactor)));
00725       }
00726       q+=GetPixelChannels(image);
00727     }
00728     for ( ; x < (ssize_t) (image->columns-y); x++)
00729     {
00730       if (GetPixelMask(image,q) != 0)
00731         {
00732           q+=GetPixelChannels(image);
00733           continue;
00734         }
00735       for (i=0; i < (ssize_t) GetPixelChannels(image); i++)
00736       {
00737         PixelChannel
00738           channel;
00739 
00740         PixelTrait
00741           traits;
00742 
00743         channel=GetPixelChannelMapChannel(image,i);
00744         traits=GetPixelChannelMapTraits(image,channel);
00745         if ((traits & UpdatePixelTrait) == 0)
00746           continue;
00747         q[i]=ClampToQuantum(QuantumScale*((MagickRealType) q[i]*
00748           AccentuateFactor+(MagickRealType) foreground*(QuantumRange-
00749           AccentuateFactor)));
00750       }
00751       q+=GetPixelChannels(image);
00752     }
00753     for ( ; x < (ssize_t) image->columns; x++)
00754     {
00755       if (GetPixelMask(image,q) != 0)
00756         {
00757           q+=GetPixelChannels(image);
00758           continue;
00759         }
00760       for (i=0; i < (ssize_t) GetPixelChannels(image); i++)
00761       {
00762         PixelChannel
00763           channel;
00764 
00765         PixelTrait
00766           traits;
00767 
00768         channel=GetPixelChannelMapChannel(image,i);
00769         traits=GetPixelChannelMapTraits(image,channel);
00770         if ((traits & UpdatePixelTrait) == 0)
00771           continue;
00772         q[i]=ClampToQuantum(QuantumScale*((MagickRealType) q[i]*ShadowFactor+
00773           (MagickRealType) background*(QuantumRange-ShadowFactor)));
00774       }
00775       q+=GetPixelChannels(image);
00776     }
00777     if (SyncCacheViewAuthenticPixels(image_view,exception) == MagickFalse)
00778       status=MagickFalse;
00779     if (image->progress_monitor != (MagickProgressMonitor) NULL)
00780       {
00781         MagickBooleanType
00782           proceed;
00783 
00784         proceed=SetImageProgress(image,RaiseImageTag,progress++,image->rows);
00785         if (proceed == MagickFalse)
00786           status=MagickFalse;
00787       }
00788   }
00789 #if defined(MAGICKCORE_OPENMP_SUPPORT)
00790   #pragma omp parallel for schedule(static) shared(progress,status)
00791 #endif
00792   for (y=(ssize_t) raise_info->height; y < (ssize_t) (image->rows-raise_info->height); y++)
00793   {
00794     register ssize_t
00795       i,
00796       x;
00797 
00798     register Quantum
00799       *restrict q;
00800 
00801     if (status == MagickFalse)
00802       continue;
00803     q=GetCacheViewAuthenticPixels(image_view,0,y,image->columns,1,exception);
00804     if (q == (Quantum *) NULL)
00805       {
00806         status=MagickFalse;
00807         continue;
00808       }
00809     for (x=0; x < (ssize_t) raise_info->width; x++)
00810     {
00811       if (GetPixelMask(image,q) != 0)
00812         {
00813           q+=GetPixelChannels(image);
00814           continue;
00815         }
00816       for (i=0; i < (ssize_t) GetPixelChannels(image); i++)
00817       {
00818         PixelChannel
00819           channel;
00820 
00821         PixelTrait
00822           traits;
00823 
00824         channel=GetPixelChannelMapChannel(image,i);
00825         traits=GetPixelChannelMapTraits(image,channel);
00826         if ((traits & UpdatePixelTrait) == 0)
00827           continue;
00828         q[i]=ClampToQuantum(QuantumScale*((MagickRealType) q[i]*HighlightFactor+
00829           (MagickRealType) foreground*(QuantumRange-HighlightFactor)));
00830       }
00831       q+=GetPixelChannels(image);
00832     }
00833     for ( ; x < (ssize_t) (image->columns-raise_info->width); x++)
00834       q+=GetPixelChannels(image);
00835     for ( ; x < (ssize_t) image->columns; x++)
00836     {
00837       if (GetPixelMask(image,q) != 0)
00838         {
00839           q+=GetPixelChannels(image);
00840           continue;
00841         }
00842       for (i=0; i < (ssize_t) GetPixelChannels(image); i++)
00843       {
00844         PixelChannel
00845           channel;
00846 
00847         PixelTrait
00848           traits;
00849 
00850         channel=GetPixelChannelMapChannel(image,i);
00851         traits=GetPixelChannelMapTraits(image,channel);
00852         if ((traits & UpdatePixelTrait) == 0)
00853           continue;
00854         q[i]=ClampToQuantum(QuantumScale*((MagickRealType) q[i]*ShadowFactor+
00855           (MagickRealType) background*(QuantumRange-ShadowFactor)));
00856       }
00857       q+=GetPixelChannels(image);
00858     }
00859     if (SyncCacheViewAuthenticPixels(image_view,exception) == MagickFalse)
00860       status=MagickFalse;
00861     if (image->progress_monitor != (MagickProgressMonitor) NULL)
00862       {
00863         MagickBooleanType
00864           proceed;
00865 
00866         proceed=SetImageProgress(image,RaiseImageTag,progress++,image->rows);
00867         if (proceed == MagickFalse)
00868           status=MagickFalse;
00869       }
00870   }
00871 #if defined(MAGICKCORE_OPENMP_SUPPORT) 
00872   #pragma omp parallel for schedule(static) shared(progress,status)
00873 #endif
00874   for (y=(ssize_t) (image->rows-raise_info->height); y < (ssize_t) image->rows; y++)
00875   {
00876     register ssize_t
00877       i,
00878       x;
00879 
00880     register Quantum
00881       *restrict q;
00882 
00883     if (status == MagickFalse)
00884       continue;
00885     q=GetCacheViewAuthenticPixels(image_view,0,y,image->columns,1,exception);
00886     if (q == (Quantum *) NULL)
00887       {
00888         status=MagickFalse;
00889         continue;
00890       }
00891     for (x=0; x < (ssize_t) (image->rows-y); x++)
00892     {
00893       if (GetPixelMask(image,q) != 0)
00894         {
00895           q+=GetPixelChannels(image);
00896           continue;
00897         }
00898       for (i=0; i < (ssize_t) GetPixelChannels(image); i++)
00899       {
00900         PixelChannel
00901           channel;
00902 
00903         PixelTrait
00904           traits;
00905 
00906         channel=GetPixelChannelMapChannel(image,i);
00907         traits=GetPixelChannelMapTraits(image,channel);
00908         if ((traits & UpdatePixelTrait) == 0)
00909           continue;
00910         q[i]=ClampToQuantum(QuantumScale*((MagickRealType) q[i]*HighlightFactor+
00911           (MagickRealType) foreground*(QuantumRange-HighlightFactor)));
00912       }
00913       q+=GetPixelChannels(image);
00914     }
00915     for ( ; x < (ssize_t) (image->columns-(image->rows-y)); x++)
00916     {
00917       for (i=0; i < (ssize_t) GetPixelChannels(image); i++)
00918       {
00919         PixelChannel
00920           channel;
00921 
00922         PixelTrait
00923           traits;
00924 
00925         channel=GetPixelChannelMapChannel(image,i);
00926         traits=GetPixelChannelMapTraits(image,channel);
00927         if ((traits & UpdatePixelTrait) == 0)
00928           continue;
00929         q[i]=ClampToQuantum(QuantumScale*((MagickRealType) q[i]*TroughFactor+
00930           (MagickRealType) background*(QuantumRange-TroughFactor)));
00931       }
00932       q+=GetPixelChannels(image);
00933     }
00934     for ( ; x < (ssize_t) image->columns; x++)
00935     {
00936       if (GetPixelMask(image,q) != 0)
00937         {
00938           q+=GetPixelChannels(image);
00939           continue;
00940         }
00941       for (i=0; i < (ssize_t) GetPixelChannels(image); i++)
00942       {
00943         PixelChannel
00944           channel;
00945 
00946         PixelTrait
00947           traits;
00948 
00949         channel=GetPixelChannelMapChannel(image,i);
00950         traits=GetPixelChannelMapTraits(image,channel);
00951         if ((traits & UpdatePixelTrait) == 0)
00952           continue;
00953         q[i]=ClampToQuantum(QuantumScale*((MagickRealType) q[i]*ShadowFactor+
00954           (MagickRealType) background*(QuantumRange-ShadowFactor)));
00955       }
00956       q+=GetPixelChannels(image);
00957     }
00958     if (SyncCacheViewAuthenticPixels(image_view,exception) == MagickFalse)
00959       status=MagickFalse;
00960     if (image->progress_monitor != (MagickProgressMonitor) NULL)
00961       {
00962         MagickBooleanType
00963           proceed;
00964 
00965 #if defined(MAGICKCORE_OPENMP_SUPPORT)
00966         #pragma omp critical (MagickCore_RaiseImage)
00967 #endif
00968         proceed=SetImageProgress(image,RaiseImageTag,progress++,image->rows);
00969         if (proceed == MagickFalse)
00970           status=MagickFalse;
00971       }
00972   }
00973   image_view=DestroyCacheView(image_view);
00974   return(status);
00975 }