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