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