1 /* 2 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 3 % % 4 % % 5 % % 6 % DDDD EEEEE CCCC OOO RRRR AAA TTTTT EEEEE % 7 % D D E C O O R R A A T E % 8 % D D EEE C O O RRRR AAAAA T EEE % 9 % D D E C O O R R A A T E % 10 % DDDD EEEEE CCCC OOO R R A A T EEEEE % 11 % % 12 % % 13 % MagickCore Image Decoration Methods % 14 % % 15 % Software Design % 16 % Cristy % 17 % July 1992 % 18 % % 19 % % 20 % Copyright 1999-2016 ImageMagick Studio LLC, a non-profit organization % 21 % dedicated to making software imaging solutions freely available. % 22 % % 23 % You may not use this file except in compliance with the License. You may % 24 % obtain a copy of the License at % 25 % % 26 % http://www.imagemagick.org/script/license.php % 27 % % 28 % Unless required by applicable law or agreed to in writing, software % 29 % distributed under the License is distributed on an "AS IS" BASIS, % 30 % WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. % 31 % See the License for the specific language governing permissions and % 32 % limitations under the License. % 33 % % 34 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 35 % 36 % 37 % 38 */ 39 40 /* 42 Include declarations. 43 */ 44 #include "MagickCore/studio.h" 45 #include "MagickCore/cache-view.h" 46 #include "MagickCore/color-private.h" 47 #include "MagickCore/colorspace-private.h" 48 #include "MagickCore/composite.h" 49 #include "MagickCore/decorate.h" 50 #include "MagickCore/exception.h" 51 #include "MagickCore/exception-private.h" 52 #include "MagickCore/image.h" 53 #include "MagickCore/memory_.h" 54 #include "MagickCore/monitor.h" 55 #include "MagickCore/monitor-private.h" 56 #include "MagickCore/pixel-accessor.h" 57 #include "MagickCore/quantum.h" 58 #include "MagickCore/quantum-private.h" 59 #include "MagickCore/resource_.h" 60 #include "MagickCore/thread-private.h" 61 #include "MagickCore/transform.h" 62 63 /* 65 Define declarations. 66 */ 67 #define AccentuateModulate ScaleCharToQuantum(80) 68 #define HighlightModulate ScaleCharToQuantum(125) 69 #define ShadowModulate ScaleCharToQuantum(135) 70 #define DepthModulate ScaleCharToQuantum(185) 71 #define TroughModulate ScaleCharToQuantum(110) 72 73 /* 75 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 76 % % 77 % % 78 % % 79 % B o r d e r I m a g e % 80 % % 81 % % 82 % % 83 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 84 % 85 % BorderImage() surrounds the image with a border of the color defined by 86 % the bordercolor member of the image structure. The width and height 87 % of the border are defined by the corresponding members of the border_info 88 % structure. 89 % 90 % The format of the BorderImage method is: 91 % 92 % Image *BorderImage(const Image *image,const RectangleInfo *border_info, 93 % const CompositeOperator compose,ExceptionInfo *exception) 94 % 95 % A description of each parameter follows: 96 % 97 % o image: the image. 98 % 99 % o border_info: define the width and height of the border. 100 % 101 % o compose: the composite operator. 102 % 103 % o exception: return any errors or warnings in this structure. 104 % 105 */ 106 MagickExport Image *BorderImage(const Image *image, 107 const RectangleInfo *border_info,const CompositeOperator compose, 108 ExceptionInfo *exception) 109 { 110 Image 111 *border_image, 112 *clone_image; 113 114 FrameInfo 115 frame_info; 116 117 assert(image != (const Image *) NULL); 118 assert(image->signature == MagickCoreSignature); 119 if (image->debug != MagickFalse) 120 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename); 121 assert(border_info != (RectangleInfo *) NULL); 122 frame_info.width=image->columns+(border_info->width << 1); 123 frame_info.height=image->rows+(border_info->height << 1); 124 frame_info.x=(ssize_t) border_info->width; 125 frame_info.y=(ssize_t) border_info->height; 126 frame_info.inner_bevel=0; 127 frame_info.outer_bevel=0; 128 clone_image=CloneImage(image,0,0,MagickTrue,exception); 129 if (clone_image == (Image *) NULL) 130 return((Image *) NULL); 131 clone_image->alpha_color=image->border_color; 132 border_image=FrameImage(clone_image,&frame_info,compose,exception); 133 clone_image=DestroyImage(clone_image); 134 if (border_image != (Image *) NULL) 135 border_image->alpha_color=image->alpha_color; 136 return(border_image); 137 } 138 139 /* 141 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 142 % % 143 % % 144 % % 145 % F r a m e I m a g e % 146 % % 147 % % 148 % % 149 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 150 % 151 % FrameImage() adds a simulated three-dimensional border around the image. 152 % The color of the border is defined by the alpha_color member of image. 153 % Members width and height of frame_info specify the border width of the 154 % vertical and horizontal sides of the frame. Members inner and outer 155 % indicate the width of the inner and outer shadows of the frame. 156 % 157 % The format of the FrameImage method is: 158 % 159 % Image *FrameImage(const Image *image,const FrameInfo *frame_info, 160 % const CompositeOperator compose,ExceptionInfo *exception) 161 % 162 % A description of each parameter follows: 163 % 164 % o image: the image. 165 % 166 % o frame_info: Define the width and height of the frame and its bevels. 167 % 168 % o compose: the composite operator. 169 % 170 % o exception: return any errors or warnings in this structure. 171 % 172 */ 173 MagickExport Image *FrameImage(const Image *image,const FrameInfo *frame_info, 174 const CompositeOperator compose,ExceptionInfo *exception) 175 { 176 #define FrameImageTag "Frame/Image" 177 178 CacheView 179 *image_view, 180 *frame_view; 181 182 Image 183 *frame_image; 184 185 MagickBooleanType 186 status; 187 188 MagickOffsetType 189 progress; 190 191 PixelInfo 192 accentuate, 193 highlight, 194 matte, 195 shadow, 196 trough; 197 198 register ssize_t 199 x; 200 201 size_t 202 bevel_width, 203 height, 204 width; 205 206 ssize_t 207 y; 208 209 /* 210 Check frame geometry. 211 */ 212 assert(image != (Image *) NULL); 213 assert(image->signature == MagickCoreSignature); 214 if (image->debug != MagickFalse) 215 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename); 216 assert(frame_info != (FrameInfo *) NULL); 217 if ((frame_info->outer_bevel < 0) || (frame_info->inner_bevel < 0)) 218 ThrowImageException(OptionError,"FrameIsLessThanImageSize"); 219 bevel_width=(size_t) (frame_info->outer_bevel+frame_info->inner_bevel); 220 x=(ssize_t) frame_info->width-frame_info->x-bevel_width; 221 y=(ssize_t) frame_info->height-frame_info->y-bevel_width; 222 if ((x < (ssize_t) image->columns) | (y < (ssize_t) image->rows)) 223 ThrowImageException(OptionError,"FrameIsLessThanImageSize"); 224 /* 225 Initialize framed image attributes. 226 */ 227 frame_image=CloneImage(image,frame_info->width,frame_info->height,MagickTrue, 228 exception); 229 if (frame_image == (Image *) NULL) 230 return((Image *) NULL); 231 if (SetImageStorageClass(frame_image,DirectClass,exception) == MagickFalse) 232 { 233 frame_image=DestroyImage(frame_image); 234 return((Image *) NULL); 235 } 236 if ((IsPixelInfoGray(&frame_image->border_color) == MagickFalse) && 237 (IsGrayColorspace(frame_image->colorspace) != MagickFalse)) 238 (void) SetImageColorspace(frame_image,sRGBColorspace,exception); 239 if ((frame_image->alpha_color.alpha_trait != UndefinedPixelTrait) && 240 (frame_image->alpha_trait == UndefinedPixelTrait)) 241 (void) SetImageAlpha(frame_image,OpaqueAlpha,exception); 242 frame_image->page=image->page; 243 if ((image->page.width != 0) && (image->page.height != 0)) 244 { 245 frame_image->page.width+=frame_image->columns-image->columns; 246 frame_image->page.height+=frame_image->rows-image->rows; 247 } 248 /* 249 Initialize 3D effects color. 250 */ 251 matte=image->alpha_color; 252 accentuate=matte; 253 accentuate.red=(double) (QuantumScale*((QuantumRange- 254 AccentuateModulate)*matte.red+(QuantumRange*AccentuateModulate))); 255 accentuate.green=(double) (QuantumScale*((QuantumRange- 256 AccentuateModulate)*matte.green+(QuantumRange*AccentuateModulate))); 257 accentuate.blue=(double) (QuantumScale*((QuantumRange- 258 AccentuateModulate)*matte.blue+(QuantumRange*AccentuateModulate))); 259 accentuate.black=(double) (QuantumScale*((QuantumRange- 260 AccentuateModulate)*matte.black+(QuantumRange*AccentuateModulate))); 261 accentuate.alpha=matte.alpha; 262 highlight=matte; 263 highlight.red=(double) (QuantumScale*((QuantumRange- 264 HighlightModulate)*matte.red+(QuantumRange*HighlightModulate))); 265 highlight.green=(double) (QuantumScale*((QuantumRange- 266 HighlightModulate)*matte.green+(QuantumRange*HighlightModulate))); 267 highlight.blue=(double) (QuantumScale*((QuantumRange- 268 HighlightModulate)*matte.blue+(QuantumRange*HighlightModulate))); 269 highlight.black=(double) (QuantumScale*((QuantumRange- 270 HighlightModulate)*matte.black+(QuantumRange*HighlightModulate))); 271 highlight.alpha=matte.alpha; 272 shadow=matte; 273 shadow.red=QuantumScale*matte.red*ShadowModulate; 274 shadow.green=QuantumScale*matte.green*ShadowModulate; 275 shadow.blue=QuantumScale*matte.blue*ShadowModulate; 276 shadow.black=QuantumScale*matte.black*ShadowModulate; 277 shadow.alpha=matte.alpha; 278 trough=matte; 279 trough.red=QuantumScale*matte.red*TroughModulate; 280 trough.green=QuantumScale*matte.green*TroughModulate; 281 trough.blue=QuantumScale*matte.blue*TroughModulate; 282 trough.black=QuantumScale*matte.black*TroughModulate; 283 trough.alpha=matte.alpha; 284 status=MagickTrue; 285 progress=0; 286 image_view=AcquireVirtualCacheView(image,exception); 287 frame_view=AcquireAuthenticCacheView(frame_image,exception); 288 height=(size_t) (frame_info->outer_bevel+(frame_info->y-bevel_width)+ 289 frame_info->inner_bevel); 290 if (height != 0) 291 { 292 register ssize_t 293 x; 294 295 register Quantum 296 *magick_restrict q; 297 298 /* 299 Draw top of ornamental border. 300 */ 301 q=QueueCacheViewAuthenticPixels(frame_view,0,0,frame_image->columns, 302 height,exception); 303 if (q != (Quantum *) NULL) 304 { 305 /* 306 Draw top of ornamental border. 307 */ 308 for (y=0; y < (ssize_t) frame_info->outer_bevel; y++) 309 { 310 for (x=0; x < (ssize_t) (frame_image->columns-y); x++) 311 { 312 if (x < y) 313 SetPixelViaPixelInfo(frame_image,&highlight,q); 314 else 315 SetPixelViaPixelInfo(frame_image,&accentuate,q); 316 q+=GetPixelChannels(frame_image); 317 } 318 for ( ; x < (ssize_t) frame_image->columns; x++) 319 { 320 SetPixelViaPixelInfo(frame_image,&shadow,q); 321 q+=GetPixelChannels(frame_image); 322 } 323 } 324 for (y=0; y < (ssize_t) (frame_info->y-bevel_width); y++) 325 { 326 for (x=0; x < (ssize_t) frame_info->outer_bevel; x++) 327 { 328 SetPixelViaPixelInfo(frame_image,&highlight,q); 329 q+=GetPixelChannels(frame_image); 330 } 331 width=frame_image->columns-2*frame_info->outer_bevel; 332 for (x=0; x < (ssize_t) width; x++) 333 { 334 SetPixelViaPixelInfo(frame_image,&matte,q); 335 q+=GetPixelChannels(frame_image); 336 } 337 for (x=0; x < (ssize_t) frame_info->outer_bevel; x++) 338 { 339 SetPixelViaPixelInfo(frame_image,&shadow,q); 340 q+=GetPixelChannels(frame_image); 341 } 342 } 343 for (y=0; y < (ssize_t) frame_info->inner_bevel; y++) 344 { 345 for (x=0; x < (ssize_t) frame_info->outer_bevel; x++) 346 { 347 SetPixelViaPixelInfo(frame_image,&highlight,q); 348 q+=GetPixelChannels(frame_image); 349 } 350 for (x=0; x < (ssize_t) (frame_info->x-bevel_width); x++) 351 { 352 SetPixelViaPixelInfo(frame_image,&matte,q); 353 q+=GetPixelChannels(frame_image); 354 } 355 width=image->columns+((size_t) frame_info->inner_bevel << 1)- 356 y; 357 for (x=0; x < (ssize_t) width; x++) 358 { 359 if (x < y) 360 SetPixelViaPixelInfo(frame_image,&shadow,q); 361 else 362 SetPixelViaPixelInfo(frame_image,&trough,q); 363 q+=GetPixelChannels(frame_image); 364 } 365 for ( ; x < (ssize_t) (image->columns+2*frame_info->inner_bevel); x++) 366 { 367 SetPixelViaPixelInfo(frame_image,&highlight,q); 368 q+=GetPixelChannels(frame_image); 369 } 370 width=frame_info->width-frame_info->x-image->columns-bevel_width; 371 for (x=0; x < (ssize_t) width; x++) 372 { 373 SetPixelViaPixelInfo(frame_image,&matte,q); 374 q+=GetPixelChannels(frame_image); 375 } 376 for (x=0; x < (ssize_t) frame_info->outer_bevel; x++) 377 { 378 SetPixelViaPixelInfo(frame_image,&shadow,q); 379 q+=GetPixelChannels(frame_image); 380 } 381 } 382 (void) SyncCacheViewAuthenticPixels(frame_view,exception); 383 } 384 } 385 /* 386 Draw sides of ornamental border. 387 */ 388 #if defined(MAGICKCORE_OPENMP_SUPPORT) 389 #pragma omp parallel for schedule(static,4) shared(progress,status) \ 390 magick_threads(image,frame_image,1,1) 391 #endif 392 for (y=0; y < (ssize_t) image->rows; y++) 393 { 394 register ssize_t 395 x; 396 397 register Quantum 398 *magick_restrict q; 399 400 size_t 401 width; 402 403 /* 404 Initialize scanline with matte color. 405 */ 406 if (status == MagickFalse) 407 continue; 408 q=QueueCacheViewAuthenticPixels(frame_view,0,frame_info->y+y, 409 frame_image->columns,1,exception); 410 if (q == (Quantum *) NULL) 411 { 412 status=MagickFalse; 413 continue; 414 } 415 for (x=0; x < (ssize_t) frame_info->outer_bevel; x++) 416 { 417 SetPixelViaPixelInfo(frame_image,&highlight,q); 418 q+=GetPixelChannels(frame_image); 419 } 420 for (x=0; x < (ssize_t) (frame_info->x-bevel_width); x++) 421 { 422 SetPixelViaPixelInfo(frame_image,&matte,q); 423 q+=GetPixelChannels(frame_image); 424 } 425 for (x=0; x < (ssize_t) frame_info->inner_bevel; x++) 426 { 427 SetPixelViaPixelInfo(frame_image,&shadow,q); 428 q+=GetPixelChannels(frame_image); 429 } 430 /* 431 Set frame interior pixels. 432 */ 433 { 434 register const Quantum 435 *p; 436 437 p=GetCacheViewVirtualPixels(image_view,0,y,image->columns,1,exception); 438 if (p == (const Quantum *) NULL) 439 { 440 status=MagickFalse; 441 continue; 442 } 443 for (x=0; x < (ssize_t) image->columns; x++) 444 { 445 register ssize_t 446 i; 447 448 if (GetPixelReadMask(image,q) == 0) 449 { 450 SetPixelBackgoundColor(frame_image,q); 451 p+=GetPixelChannels(image); 452 q+=GetPixelChannels(frame_image); 453 continue; 454 } 455 for (i=0; i < (ssize_t) GetPixelChannels(image); i++) 456 { 457 PixelChannel channel=GetPixelChannelChannel(image,i); 458 PixelTrait traits=GetPixelChannelTraits(image,channel); 459 PixelTrait frame_traits=GetPixelChannelTraits(frame_image,channel); 460 if ((traits == UndefinedPixelTrait) || 461 (frame_traits == UndefinedPixelTrait)) 462 continue; 463 SetPixelChannel(frame_image,channel,p[i],q); 464 } 465 SetPixelRed(frame_image,GetPixelRed(image,p),q); 466 SetPixelGreen(frame_image,GetPixelGreen(image,p),q); 467 SetPixelBlue(frame_image,GetPixelBlue(image,p),q); 468 SetPixelAlpha(frame_image,GetPixelAlpha(image,p),q); 469 p+=GetPixelChannels(image); 470 q+=GetPixelChannels(frame_image); 471 } 472 } 473 for (x=0; x < (ssize_t) frame_info->inner_bevel; x++) 474 { 475 SetPixelViaPixelInfo(frame_image,&highlight,q); 476 q+=GetPixelChannels(frame_image); 477 } 478 width=frame_info->width-frame_info->x-image->columns-bevel_width; 479 for (x=0; x < (ssize_t) width; x++) 480 { 481 SetPixelViaPixelInfo(frame_image,&matte,q); 482 q+=GetPixelChannels(frame_image); 483 } 484 for (x=0; x < (ssize_t) frame_info->outer_bevel; x++) 485 { 486 SetPixelViaPixelInfo(frame_image,&shadow,q); 487 q+=GetPixelChannels(frame_image); 488 } 489 if (SyncCacheViewAuthenticPixels(frame_view,exception) == MagickFalse) 490 status=MagickFalse; 491 if (image->progress_monitor != (MagickProgressMonitor) NULL) 492 { 493 MagickBooleanType 494 proceed; 495 496 #if defined(MAGICKCORE_OPENMP_SUPPORT) 497 #pragma omp critical (MagickCore_FrameImage) 498 #endif 499 proceed=SetImageProgress(image,FrameImageTag,progress++,image->rows); 500 if (proceed == MagickFalse) 501 status=MagickFalse; 502 } 503 } 504 height=(size_t) (frame_info->inner_bevel+frame_info->height- 505 frame_info->y-image->rows-bevel_width+frame_info->outer_bevel); 506 if (height != 0) 507 { 508 register ssize_t 509 x; 510 511 register Quantum 512 *magick_restrict q; 513 514 /* 515 Draw bottom of ornamental border. 516 */ 517 q=QueueCacheViewAuthenticPixels(frame_view,0,(ssize_t) (frame_image->rows- 518 height),frame_image->columns,height,exception); 519 if (q != (Quantum *) NULL) 520 { 521 /* 522 Draw bottom of ornamental border. 523 */ 524 for (y=frame_info->inner_bevel-1; y >= 0; y--) 525 { 526 for (x=0; x < (ssize_t) frame_info->outer_bevel; x++) 527 { 528 SetPixelViaPixelInfo(frame_image,&highlight,q); 529 q+=GetPixelChannels(frame_image); 530 } 531 for (x=0; x < (ssize_t) (frame_info->x-bevel_width); x++) 532 { 533 SetPixelViaPixelInfo(frame_image,&matte,q); 534 q+=GetPixelChannels(frame_image); 535 } 536 for (x=0; x < y; x++) 537 { 538 SetPixelViaPixelInfo(frame_image,&shadow,q); 539 q+=GetPixelChannels(frame_image); 540 } 541 for ( ; x < (ssize_t) (image->columns+2*frame_info->inner_bevel); x++) 542 { 543 if (x >= (ssize_t) (image->columns+2*frame_info->inner_bevel-y)) 544 SetPixelViaPixelInfo(frame_image,&highlight,q); 545 else 546 SetPixelViaPixelInfo(frame_image,&accentuate,q); 547 q+=GetPixelChannels(frame_image); 548 } 549 width=frame_info->width-frame_info->x-image->columns-bevel_width; 550 for (x=0; x < (ssize_t) width; x++) 551 { 552 SetPixelViaPixelInfo(frame_image,&matte,q); 553 q+=GetPixelChannels(frame_image); 554 } 555 for (x=0; x < (ssize_t) frame_info->outer_bevel; x++) 556 { 557 SetPixelViaPixelInfo(frame_image,&shadow,q); 558 q+=GetPixelChannels(frame_image); 559 } 560 } 561 height=frame_info->height-frame_info->y-image->rows-bevel_width; 562 for (y=0; y < (ssize_t) height; y++) 563 { 564 for (x=0; x < (ssize_t) frame_info->outer_bevel; x++) 565 { 566 SetPixelViaPixelInfo(frame_image,&highlight,q); 567 q+=GetPixelChannels(frame_image); 568 } 569 width=frame_image->columns-2*frame_info->outer_bevel; 570 for (x=0; x < (ssize_t) width; x++) 571 { 572 SetPixelViaPixelInfo(frame_image,&matte,q); 573 q+=GetPixelChannels(frame_image); 574 } 575 for (x=0; x < (ssize_t) frame_info->outer_bevel; x++) 576 { 577 SetPixelViaPixelInfo(frame_image,&shadow,q); 578 q+=GetPixelChannels(frame_image); 579 } 580 } 581 for (y=frame_info->outer_bevel-1; y >= 0; y--) 582 { 583 for (x=0; x < y; x++) 584 { 585 SetPixelViaPixelInfo(frame_image,&highlight,q); 586 q+=GetPixelChannels(frame_image); 587 } 588 for ( ; x < (ssize_t) frame_image->columns; x++) 589 { 590 if (x >= (ssize_t) (frame_image->columns-y)) 591 SetPixelViaPixelInfo(frame_image,&shadow,q); 592 else 593 SetPixelViaPixelInfo(frame_image,&trough,q); 594 q+=GetPixelChannels(frame_image); 595 } 596 } 597 (void) SyncCacheViewAuthenticPixels(frame_view,exception); 598 } 599 } 600 frame_view=DestroyCacheView(frame_view); 601 image_view=DestroyCacheView(image_view); 602 x=(ssize_t) (frame_info->outer_bevel+(frame_info->x-bevel_width)+ 603 frame_info->inner_bevel); 604 y=(ssize_t) (frame_info->outer_bevel+(frame_info->y-bevel_width)+ 605 frame_info->inner_bevel); 606 if (status != MagickFalse) 607 status=CompositeImage(frame_image,image,compose,MagickTrue,x,y, 608 exception); 609 if (status == MagickFalse) 610 frame_image=DestroyImage(frame_image); 611 return(frame_image); 612 } 613 614 /* 616 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 617 % % 618 % % 619 % % 620 % R a i s e I m a g e % 621 % % 622 % % 623 % % 624 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 625 % 626 % RaiseImage() creates a simulated three-dimensional button-like effect 627 % by lightening and darkening the edges of the image. Members width and 628 % height of raise_info define the width of the vertical and horizontal 629 % edge of the effect. 630 % 631 % The format of the RaiseImage method is: 632 % 633 % MagickBooleanType RaiseImage(const Image *image, 634 % const RectangleInfo *raise_info,const MagickBooleanType raise, 635 % ExceptionInfo *exception) 636 % 637 % A description of each parameter follows: 638 % 639 % o image: the image. 640 % 641 % o raise_info: Define the width and height of the raise area. 642 % 643 % o raise: A value other than zero creates a 3-D raise effect, 644 % otherwise it has a lowered effect. 645 % 646 % o exception: return any errors or warnings in this structure. 647 % 648 */ 649 MagickExport MagickBooleanType RaiseImage(Image *image, 650 const RectangleInfo *raise_info,const MagickBooleanType raise, 651 ExceptionInfo *exception) 652 { 653 #define AccentuateFactor ScaleCharToQuantum(135) 654 #define HighlightFactor ScaleCharToQuantum(190) 655 #define ShadowFactor ScaleCharToQuantum(190) 656 #define RaiseImageTag "Raise/Image" 657 #define TroughFactor ScaleCharToQuantum(135) 658 659 CacheView 660 *image_view; 661 662 MagickBooleanType 663 status; 664 665 MagickOffsetType 666 progress; 667 668 Quantum 669 foreground, 670 background; 671 672 ssize_t 673 y; 674 675 assert(image != (Image *) NULL); 676 assert(image->signature == MagickCoreSignature); 677 if (image->debug != MagickFalse) 678 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename); 679 assert(raise_info != (RectangleInfo *) NULL); 680 if ((image->columns <= (raise_info->width << 1)) || 681 (image->rows <= (raise_info->height << 1))) 682 ThrowBinaryException(OptionError,"ImageSizeMustExceedBevelWidth", 683 image->filename); 684 foreground=QuantumRange; 685 background=(Quantum) 0; 686 if (raise == MagickFalse) 687 { 688 foreground=(Quantum) 0; 689 background=QuantumRange; 690 } 691 if (SetImageStorageClass(image,DirectClass,exception) == MagickFalse) 692 return(MagickFalse); 693 /* 694 Raise image. 695 */ 696 status=MagickTrue; 697 progress=0; 698 image_view=AcquireAuthenticCacheView(image,exception); 699 #if defined(MAGICKCORE_OPENMP_SUPPORT) 700 #pragma omp parallel for schedule(static,4) shared(progress,status) \ 701 magick_threads(image,image,1,1) 702 #endif 703 for (y=0; y < (ssize_t) raise_info->height; y++) 704 { 705 register ssize_t 706 i, 707 x; 708 709 register Quantum 710 *magick_restrict q; 711 712 if (status == MagickFalse) 713 continue; 714 q=GetCacheViewAuthenticPixels(image_view,0,y,image->columns,1,exception); 715 if (q == (Quantum *) NULL) 716 { 717 status=MagickFalse; 718 continue; 719 } 720 for (x=0; x < y; x++) 721 { 722 if (GetPixelReadMask(image,q) == 0) 723 { 724 q+=GetPixelChannels(image); 725 continue; 726 } 727 for (i=0; i < (ssize_t) GetPixelChannels(image); i++) 728 { 729 PixelChannel channel=GetPixelChannelChannel(image,i); 730 PixelTrait traits=GetPixelChannelTraits(image,channel); 731 if ((traits & UpdatePixelTrait) == 0) 732 continue; 733 q[i]=ClampToQuantum(QuantumScale*((double) q[i]*HighlightFactor+(double) 734 foreground*(QuantumRange-HighlightFactor))); 735 } 736 q+=GetPixelChannels(image); 737 } 738 for ( ; x < (ssize_t) (image->columns-y); x++) 739 { 740 if (GetPixelReadMask(image,q) == 0) 741 { 742 q+=GetPixelChannels(image); 743 continue; 744 } 745 for (i=0; i < (ssize_t) GetPixelChannels(image); i++) 746 { 747 PixelChannel channel=GetPixelChannelChannel(image,i); 748 PixelTrait traits=GetPixelChannelTraits(image,channel); 749 if ((traits & UpdatePixelTrait) == 0) 750 continue; 751 q[i]=ClampToQuantum(QuantumScale*((double) q[i]*AccentuateFactor+ 752 (double) foreground*(QuantumRange-AccentuateFactor))); 753 } 754 q+=GetPixelChannels(image); 755 } 756 for ( ; x < (ssize_t) image->columns; x++) 757 { 758 if (GetPixelReadMask(image,q) == 0) 759 { 760 q+=GetPixelChannels(image); 761 continue; 762 } 763 for (i=0; i < (ssize_t) GetPixelChannels(image); i++) 764 { 765 PixelChannel channel=GetPixelChannelChannel(image,i); 766 PixelTrait traits=GetPixelChannelTraits(image,channel); 767 if ((traits & UpdatePixelTrait) == 0) 768 continue; 769 q[i]=ClampToQuantum(QuantumScale*((double) q[i]*ShadowFactor+(double) 770 background*(QuantumRange-ShadowFactor))); 771 } 772 q+=GetPixelChannels(image); 773 } 774 if (SyncCacheViewAuthenticPixels(image_view,exception) == MagickFalse) 775 status=MagickFalse; 776 if (image->progress_monitor != (MagickProgressMonitor) NULL) 777 { 778 MagickBooleanType 779 proceed; 780 781 #if defined(MAGICKCORE_OPENMP_SUPPORT) 782 #pragma omp critical (MagickCore_RaiseImage) 783 #endif 784 proceed=SetImageProgress(image,RaiseImageTag,progress++,image->rows); 785 if (proceed == MagickFalse) 786 status=MagickFalse; 787 } 788 } 789 #if defined(MAGICKCORE_OPENMP_SUPPORT) 790 #pragma omp parallel for schedule(static,4) shared(progress,status) \ 791 magick_threads(image,image,1,1) 792 #endif 793 for (y=(ssize_t) raise_info->height; y < (ssize_t) (image->rows-raise_info->height); y++) 794 { 795 register ssize_t 796 i, 797 x; 798 799 register Quantum 800 *magick_restrict q; 801 802 if (status == MagickFalse) 803 continue; 804 q=GetCacheViewAuthenticPixels(image_view,0,y,image->columns,1,exception); 805 if (q == (Quantum *) NULL) 806 { 807 status=MagickFalse; 808 continue; 809 } 810 for (x=0; x < (ssize_t) raise_info->width; x++) 811 { 812 if (GetPixelReadMask(image,q) == 0) 813 { 814 q+=GetPixelChannels(image); 815 continue; 816 } 817 for (i=0; i < (ssize_t) GetPixelChannels(image); i++) 818 { 819 PixelChannel channel=GetPixelChannelChannel(image,i); 820 PixelTrait traits=GetPixelChannelTraits(image,channel); 821 if ((traits & UpdatePixelTrait) == 0) 822 continue; 823 q[i]=ClampToQuantum(QuantumScale*((double) q[i]*HighlightFactor+(double) 824 foreground*(QuantumRange-HighlightFactor))); 825 } 826 q+=GetPixelChannels(image); 827 } 828 for ( ; x < (ssize_t) (image->columns-raise_info->width); x++) 829 q+=GetPixelChannels(image); 830 for ( ; x < (ssize_t) image->columns; x++) 831 { 832 if (GetPixelReadMask(image,q) == 0) 833 { 834 q+=GetPixelChannels(image); 835 continue; 836 } 837 for (i=0; i < (ssize_t) GetPixelChannels(image); i++) 838 { 839 PixelChannel channel=GetPixelChannelChannel(image,i); 840 PixelTrait traits=GetPixelChannelTraits(image,channel); 841 if ((traits & UpdatePixelTrait) == 0) 842 continue; 843 q[i]=ClampToQuantum(QuantumScale*((double) q[i]*ShadowFactor+(double) 844 background*(QuantumRange-ShadowFactor))); 845 } 846 q+=GetPixelChannels(image); 847 } 848 if (SyncCacheViewAuthenticPixels(image_view,exception) == MagickFalse) 849 status=MagickFalse; 850 if (image->progress_monitor != (MagickProgressMonitor) NULL) 851 { 852 MagickBooleanType 853 proceed; 854 855 #if defined(MAGICKCORE_OPENMP_SUPPORT) 856 #pragma omp critical (MagickCore_RaiseImage) 857 #endif 858 proceed=SetImageProgress(image,RaiseImageTag,progress++,image->rows); 859 if (proceed == MagickFalse) 860 status=MagickFalse; 861 } 862 } 863 #if defined(MAGICKCORE_OPENMP_SUPPORT) 864 #pragma omp parallel for schedule(static,4) shared(progress,status) \ 865 magick_threads(image,image,1,1) 866 #endif 867 for (y=(ssize_t) (image->rows-raise_info->height); y < (ssize_t) image->rows; y++) 868 { 869 register ssize_t 870 i, 871 x; 872 873 register Quantum 874 *magick_restrict q; 875 876 if (status == MagickFalse) 877 continue; 878 q=GetCacheViewAuthenticPixels(image_view,0,y,image->columns,1,exception); 879 if (q == (Quantum *) NULL) 880 { 881 status=MagickFalse; 882 continue; 883 } 884 for (x=0; x < (ssize_t) (image->rows-y); x++) 885 { 886 if (GetPixelReadMask(image,q) == 0) 887 { 888 q+=GetPixelChannels(image); 889 continue; 890 } 891 for (i=0; i < (ssize_t) GetPixelChannels(image); i++) 892 { 893 PixelChannel channel=GetPixelChannelChannel(image,i); 894 PixelTrait traits=GetPixelChannelTraits(image,channel); 895 if ((traits & UpdatePixelTrait) == 0) 896 continue; 897 q[i]=ClampToQuantum(QuantumScale*((double) q[i]*HighlightFactor+(double) 898 foreground*(QuantumRange-HighlightFactor))); 899 } 900 q+=GetPixelChannels(image); 901 } 902 for ( ; x < (ssize_t) (image->columns-(image->rows-y)); x++) 903 { 904 for (i=0; i < (ssize_t) GetPixelChannels(image); i++) 905 { 906 PixelChannel channel=GetPixelChannelChannel(image,i); 907 PixelTrait traits=GetPixelChannelTraits(image,channel); 908 if ((traits & UpdatePixelTrait) == 0) 909 continue; 910 q[i]=ClampToQuantum(QuantumScale*((double) q[i]*TroughFactor+ 911 (double) background*(QuantumRange-TroughFactor))); 912 } 913 q+=GetPixelChannels(image); 914 } 915 for ( ; x < (ssize_t) image->columns; x++) 916 { 917 if (GetPixelReadMask(image,q) == 0) 918 { 919 q+=GetPixelChannels(image); 920 continue; 921 } 922 for (i=0; i < (ssize_t) GetPixelChannels(image); i++) 923 { 924 PixelChannel channel=GetPixelChannelChannel(image,i); 925 PixelTrait traits=GetPixelChannelTraits(image,channel); 926 if ((traits & UpdatePixelTrait) == 0) 927 continue; 928 q[i]=ClampToQuantum(QuantumScale*((double) q[i]*ShadowFactor+(double) 929 background*(QuantumRange-ShadowFactor))); 930 } 931 q+=GetPixelChannels(image); 932 } 933 if (SyncCacheViewAuthenticPixels(image_view,exception) == MagickFalse) 934 status=MagickFalse; 935 if (image->progress_monitor != (MagickProgressMonitor) NULL) 936 { 937 MagickBooleanType 938 proceed; 939 940 #if defined(MAGICKCORE_OPENMP_SUPPORT) 941 #pragma omp critical (MagickCore_RaiseImage) 942 #endif 943 proceed=SetImageProgress(image,RaiseImageTag,progress++,image->rows); 944 if (proceed == MagickFalse) 945 status=MagickFalse; 946 } 947 } 948 image_view=DestroyCacheView(image_view); 949 return(status); 950 } 951