decorate.c revision de984cdc3631106b1cbbb8d3972b76a0fc27e8e8
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-2014 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->border_color) == MagickFalse) && 234 (IsGrayColorspace(frame_image->colorspace) != MagickFalse)) 235 (void) SetImageColorspace(frame_image,sRGBColorspace,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 (GetPixelReadMask(image,q) == 0) 455 { 456 SetPixelBackgoundColor(frame_image,q); 457 p+=GetPixelChannels(image); 458 q+=GetPixelChannels(frame_image); 459 continue; 460 } 461 for (i=0; i < (ssize_t) GetPixelChannels(image); i++) 462 { 463 PixelChannel channel=GetPixelChannelChannel(image,i); 464 PixelTrait traits=GetPixelChannelTraits(image,channel); 465 if ((traits & (CopyPixelTrait | UpdatePixelTrait)) == 0) 466 continue; 467 q[i]=p[i]; 468 } 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 SetPixelInfoPixel(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 SetPixelInfoPixel(frame_image,&matte,q); 482 q+=GetPixelChannels(frame_image); 483 } 484 for (x=0; x < (ssize_t) frame_info->outer_bevel; x++) 485 { 486 SetPixelInfoPixel(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 *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 SetPixelInfoPixel(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 SetPixelInfoPixel(frame_image,&matte,q); 534 q+=GetPixelChannels(frame_image); 535 } 536 for (x=0; x < y; x++) 537 { 538 SetPixelInfoPixel(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 SetPixelInfoPixel(frame_image,&highlight,q); 545 else 546 SetPixelInfoPixel(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 SetPixelInfoPixel(frame_image,&matte,q); 553 q+=GetPixelChannels(frame_image); 554 } 555 for (x=0; x < (ssize_t) frame_info->outer_bevel; x++) 556 { 557 SetPixelInfoPixel(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 SetPixelInfoPixel(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 SetPixelInfoPixel(frame_image,&matte,q); 573 q+=GetPixelChannels(frame_image); 574 } 575 for (x=0; x < (ssize_t) frame_info->outer_bevel; x++) 576 { 577 SetPixelInfoPixel(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 SetPixelInfoPixel(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 SetPixelInfoPixel(frame_image,&shadow,q); 592 else 593 SetPixelInfoPixel(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 if ((compose != CopyCompositeOp) && ((compose != OverCompositeOp) || 603 (image->alpha_trait == BlendPixelTrait))) 604 { 605 x=(ssize_t) (frame_info->outer_bevel+(frame_info->x-bevel_width)+ 606 frame_info->inner_bevel); 607 y=(ssize_t) (frame_info->outer_bevel+(frame_info->y-bevel_width)+ 608 frame_info->inner_bevel); 609 (void) CompositeImage(frame_image,image,compose,MagickTrue,x,y, 610 exception); 611 } 612 if (status == MagickFalse) 613 frame_image=DestroyImage(frame_image); 614 return(frame_image); 615} 616 617/* 618%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 619% % 620% % 621% % 622% R a i s e I m a g e % 623% % 624% % 625% % 626%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 627% 628% RaiseImage() creates a simulated three-dimensional button-like effect 629% by lightening and darkening the edges of the image. Members width and 630% height of raise_info define the width of the vertical and horizontal 631% edge of the effect. 632% 633% The format of the RaiseImage method is: 634% 635% MagickBooleanType RaiseImage(const Image *image, 636% const RectangleInfo *raise_info,const MagickBooleanType raise, 637% ExceptionInfo *exception) 638% 639% A description of each parameter follows: 640% 641% o image: the image. 642% 643% o raise_info: Define the width and height of the raise area. 644% 645% o raise: A value other than zero creates a 3-D raise effect, 646% otherwise it has a lowered effect. 647% 648% o exception: return any errors or warnings in this structure. 649% 650*/ 651MagickExport MagickBooleanType RaiseImage(Image *image, 652 const RectangleInfo *raise_info,const MagickBooleanType raise, 653 ExceptionInfo *exception) 654{ 655#define AccentuateFactor ScaleCharToQuantum(135) 656#define HighlightFactor ScaleCharToQuantum(190) 657#define ShadowFactor ScaleCharToQuantum(190) 658#define RaiseImageTag "Raise/Image" 659#define TroughFactor ScaleCharToQuantum(135) 660 661 CacheView 662 *image_view; 663 664 MagickBooleanType 665 status; 666 667 MagickOffsetType 668 progress; 669 670 Quantum 671 foreground, 672 background; 673 674 ssize_t 675 y; 676 677 assert(image != (Image *) NULL); 678 assert(image->signature == MagickSignature); 679 if (image->debug != MagickFalse) 680 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename); 681 assert(raise_info != (RectangleInfo *) NULL); 682 if ((image->columns <= (raise_info->width << 1)) || 683 (image->rows <= (raise_info->height << 1))) 684 ThrowBinaryException(OptionError,"ImageSizeMustExceedBevelWidth", 685 image->filename); 686 foreground=QuantumRange; 687 background=(Quantum) 0; 688 if (raise == MagickFalse) 689 { 690 foreground=(Quantum) 0; 691 background=QuantumRange; 692 } 693 if (SetImageStorageClass(image,DirectClass,exception) == MagickFalse) 694 return(MagickFalse); 695 /* 696 Raise image. 697 */ 698 status=MagickTrue; 699 progress=0; 700 image_view=AcquireAuthenticCacheView(image,exception); 701#if defined(MAGICKCORE_OPENMP_SUPPORT) 702 #pragma omp parallel for schedule(static,4) shared(progress,status) \ 703 magick_threads(image,image,1,1) 704#endif 705 for (y=0; y < (ssize_t) raise_info->height; y++) 706 { 707 register ssize_t 708 i, 709 x; 710 711 register Quantum 712 *restrict q; 713 714 if (status == MagickFalse) 715 continue; 716 q=GetCacheViewAuthenticPixels(image_view,0,y,image->columns,1,exception); 717 if (q == (Quantum *) NULL) 718 { 719 status=MagickFalse; 720 continue; 721 } 722 for (x=0; x < y; x++) 723 { 724 if (GetPixelReadMask(image,q) == 0) 725 { 726 q+=GetPixelChannels(image); 727 continue; 728 } 729 for (i=0; i < (ssize_t) GetPixelChannels(image); i++) 730 { 731 PixelChannel channel=GetPixelChannelChannel(image,i); 732 PixelTrait traits=GetPixelChannelTraits(image,channel); 733 if ((traits & UpdatePixelTrait) == 0) 734 continue; 735 q[i]=ClampToQuantum(QuantumScale*((double) q[i]*HighlightFactor+(double) 736 foreground*(QuantumRange-HighlightFactor))); 737 } 738 q+=GetPixelChannels(image); 739 } 740 for ( ; x < (ssize_t) (image->columns-y); x++) 741 { 742 if (GetPixelReadMask(image,q) == 0) 743 { 744 q+=GetPixelChannels(image); 745 continue; 746 } 747 for (i=0; i < (ssize_t) GetPixelChannels(image); i++) 748 { 749 PixelChannel channel=GetPixelChannelChannel(image,i); 750 PixelTrait traits=GetPixelChannelTraits(image,channel); 751 if ((traits & UpdatePixelTrait) == 0) 752 continue; 753 q[i]=ClampToQuantum(QuantumScale*((double) q[i]*AccentuateFactor+ 754 (double) foreground*(QuantumRange-AccentuateFactor))); 755 } 756 q+=GetPixelChannels(image); 757 } 758 for ( ; x < (ssize_t) image->columns; x++) 759 { 760 if (GetPixelReadMask(image,q) == 0) 761 { 762 q+=GetPixelChannels(image); 763 continue; 764 } 765 for (i=0; i < (ssize_t) GetPixelChannels(image); i++) 766 { 767 PixelChannel channel=GetPixelChannelChannel(image,i); 768 PixelTrait traits=GetPixelChannelTraits(image,channel); 769 if ((traits & UpdatePixelTrait) == 0) 770 continue; 771 q[i]=ClampToQuantum(QuantumScale*((double) q[i]*ShadowFactor+(double) 772 background*(QuantumRange-ShadowFactor))); 773 } 774 q+=GetPixelChannels(image); 775 } 776 if (SyncCacheViewAuthenticPixels(image_view,exception) == MagickFalse) 777 status=MagickFalse; 778 if (image->progress_monitor != (MagickProgressMonitor) NULL) 779 { 780 MagickBooleanType 781 proceed; 782 783#if defined(MAGICKCORE_OPENMP_SUPPORT) 784 #pragma omp critical (MagickCore_RaiseImage) 785#endif 786 proceed=SetImageProgress(image,RaiseImageTag,progress++,image->rows); 787 if (proceed == MagickFalse) 788 status=MagickFalse; 789 } 790 } 791#if defined(MAGICKCORE_OPENMP_SUPPORT) 792 #pragma omp parallel for schedule(static,4) shared(progress,status) \ 793 magick_threads(image,image,1,1) 794#endif 795 for (y=(ssize_t) raise_info->height; y < (ssize_t) (image->rows-raise_info->height); y++) 796 { 797 register ssize_t 798 i, 799 x; 800 801 register Quantum 802 *restrict q; 803 804 if (status == MagickFalse) 805 continue; 806 q=GetCacheViewAuthenticPixels(image_view,0,y,image->columns,1,exception); 807 if (q == (Quantum *) NULL) 808 { 809 status=MagickFalse; 810 continue; 811 } 812 for (x=0; x < (ssize_t) raise_info->width; x++) 813 { 814 if (GetPixelReadMask(image,q) == 0) 815 { 816 q+=GetPixelChannels(image); 817 continue; 818 } 819 for (i=0; i < (ssize_t) GetPixelChannels(image); i++) 820 { 821 PixelChannel channel=GetPixelChannelChannel(image,i); 822 PixelTrait traits=GetPixelChannelTraits(image,channel); 823 if ((traits & UpdatePixelTrait) == 0) 824 continue; 825 q[i]=ClampToQuantum(QuantumScale*((double) q[i]*HighlightFactor+(double) 826 foreground*(QuantumRange-HighlightFactor))); 827 } 828 q+=GetPixelChannels(image); 829 } 830 for ( ; x < (ssize_t) (image->columns-raise_info->width); x++) 831 q+=GetPixelChannels(image); 832 for ( ; x < (ssize_t) image->columns; x++) 833 { 834 if (GetPixelReadMask(image,q) == 0) 835 { 836 q+=GetPixelChannels(image); 837 continue; 838 } 839 for (i=0; i < (ssize_t) GetPixelChannels(image); i++) 840 { 841 PixelChannel channel=GetPixelChannelChannel(image,i); 842 PixelTrait traits=GetPixelChannelTraits(image,channel); 843 if ((traits & UpdatePixelTrait) == 0) 844 continue; 845 q[i]=ClampToQuantum(QuantumScale*((double) q[i]*ShadowFactor+(double) 846 background*(QuantumRange-ShadowFactor))); 847 } 848 q+=GetPixelChannels(image); 849 } 850 if (SyncCacheViewAuthenticPixels(image_view,exception) == MagickFalse) 851 status=MagickFalse; 852 if (image->progress_monitor != (MagickProgressMonitor) NULL) 853 { 854 MagickBooleanType 855 proceed; 856 857#if defined(MAGICKCORE_OPENMP_SUPPORT) 858 #pragma omp critical (MagickCore_RaiseImage) 859#endif 860 proceed=SetImageProgress(image,RaiseImageTag,progress++,image->rows); 861 if (proceed == MagickFalse) 862 status=MagickFalse; 863 } 864 } 865#if defined(MAGICKCORE_OPENMP_SUPPORT) 866 #pragma omp parallel for schedule(static,4) shared(progress,status) \ 867 magick_threads(image,image,1,1) 868#endif 869 for (y=(ssize_t) (image->rows-raise_info->height); y < (ssize_t) image->rows; y++) 870 { 871 register ssize_t 872 i, 873 x; 874 875 register Quantum 876 *restrict q; 877 878 if (status == MagickFalse) 879 continue; 880 q=GetCacheViewAuthenticPixels(image_view,0,y,image->columns,1,exception); 881 if (q == (Quantum *) NULL) 882 { 883 status=MagickFalse; 884 continue; 885 } 886 for (x=0; x < (ssize_t) (image->rows-y); x++) 887 { 888 if (GetPixelReadMask(image,q) == 0) 889 { 890 q+=GetPixelChannels(image); 891 continue; 892 } 893 for (i=0; i < (ssize_t) GetPixelChannels(image); i++) 894 { 895 PixelChannel channel=GetPixelChannelChannel(image,i); 896 PixelTrait traits=GetPixelChannelTraits(image,channel); 897 if ((traits & UpdatePixelTrait) == 0) 898 continue; 899 q[i]=ClampToQuantum(QuantumScale*((double) q[i]*HighlightFactor+(double) 900 foreground*(QuantumRange-HighlightFactor))); 901 } 902 q+=GetPixelChannels(image); 903 } 904 for ( ; x < (ssize_t) (image->columns-(image->rows-y)); x++) 905 { 906 for (i=0; i < (ssize_t) GetPixelChannels(image); i++) 907 { 908 PixelChannel channel=GetPixelChannelChannel(image,i); 909 PixelTrait traits=GetPixelChannelTraits(image,channel); 910 if ((traits & UpdatePixelTrait) == 0) 911 continue; 912 q[i]=ClampToQuantum(QuantumScale*((double) q[i]*TroughFactor+ 913 (double) background*(QuantumRange-TroughFactor))); 914 } 915 q+=GetPixelChannels(image); 916 } 917 for ( ; x < (ssize_t) image->columns; x++) 918 { 919 if (GetPixelReadMask(image,q) == 0) 920 { 921 q+=GetPixelChannels(image); 922 continue; 923 } 924 for (i=0; i < (ssize_t) GetPixelChannels(image); i++) 925 { 926 PixelChannel channel=GetPixelChannelChannel(image,i); 927 PixelTrait traits=GetPixelChannelTraits(image,channel); 928 if ((traits & UpdatePixelTrait) == 0) 929 continue; 930 q[i]=ClampToQuantum(QuantumScale*((double) q[i]*ShadowFactor+(double) 931 background*(QuantumRange-ShadowFactor))); 932 } 933 q+=GetPixelChannels(image); 934 } 935 if (SyncCacheViewAuthenticPixels(image_view,exception) == MagickFalse) 936 status=MagickFalse; 937 if (image->progress_monitor != (MagickProgressMonitor) NULL) 938 { 939 MagickBooleanType 940 proceed; 941 942#if defined(MAGICKCORE_OPENMP_SUPPORT) 943 #pragma omp critical (MagickCore_RaiseImage) 944#endif 945 proceed=SetImageProgress(image,RaiseImageTag,progress++,image->rows); 946 if (proceed == MagickFalse) 947 status=MagickFalse; 948 } 949 } 950 image_view=DestroyCacheView(image_view); 951 return(status); 952} 953