decorate.c revision b09db11cc8fa61710ac2bc9c46c06733c39d67b7
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-2012 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.matte != MagickFalse) && 237 (frame_image->matte == MagickFalse)) 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=(MagickRealType) (QuantumScale*((QuantumRange- 252 AccentuateModulate)*matte.red+(QuantumRange*AccentuateModulate))); 253 accentuate.green=(MagickRealType) (QuantumScale*((QuantumRange- 254 AccentuateModulate)*matte.green+(QuantumRange*AccentuateModulate))); 255 accentuate.blue=(MagickRealType) (QuantumScale*((QuantumRange- 256 AccentuateModulate)*matte.blue+(QuantumRange*AccentuateModulate))); 257 accentuate.black=(MagickRealType) (QuantumScale*((QuantumRange- 258 AccentuateModulate)*matte.black+(QuantumRange*AccentuateModulate))); 259 accentuate.alpha=matte.alpha; 260 highlight=matte; 261 highlight.red=(MagickRealType) (QuantumScale*((QuantumRange- 262 HighlightModulate)*matte.red+(QuantumRange*HighlightModulate))); 263 highlight.green=(MagickRealType) (QuantumScale*((QuantumRange- 264 HighlightModulate)*matte.green+(QuantumRange*HighlightModulate))); 265 highlight.blue=(MagickRealType) (QuantumScale*((QuantumRange- 266 HighlightModulate)*matte.blue+(QuantumRange*HighlightModulate))); 267 highlight.black=(MagickRealType) (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) shared(progress,status) \ 388 dynamic_number_threads(image,image->columns,image->rows,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->matte != MagickFalse))) 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 if ((GetPixelRedTraits(image) & UpdatePixelTrait) != 0) 452 SetPixelRed(frame_image,GetPixelRed(image,p),q); 453 if ((GetPixelGreenTraits(image) & UpdatePixelTrait) != 0) 454 SetPixelGreen(frame_image,GetPixelGreen(image,p),q); 455 if ((GetPixelBlueTraits(image) & UpdatePixelTrait) != 0) 456 SetPixelBlue(frame_image,GetPixelBlue(image,p),q); 457 if ((GetPixelBlackTraits(image) & UpdatePixelTrait) != 0) 458 SetPixelBlack(frame_image,GetPixelBlack(image,p),q); 459 if ((GetPixelAlphaTraits(image) & UpdatePixelTrait) != 0) 460 SetPixelAlpha(frame_image,GetPixelAlpha(image,p),q); 461 p+=GetPixelChannels(image); 462 q+=GetPixelChannels(frame_image); 463 } 464 } 465 for (x=0; x < (ssize_t) frame_info->inner_bevel; x++) 466 { 467 SetPixelInfoPixel(frame_image,&highlight,q); 468 q+=GetPixelChannels(frame_image); 469 } 470 width=frame_info->width-frame_info->x-image->columns-bevel_width; 471 for (x=0; x < (ssize_t) width; x++) 472 { 473 SetPixelInfoPixel(frame_image,&matte,q); 474 q+=GetPixelChannels(frame_image); 475 } 476 for (x=0; x < (ssize_t) frame_info->outer_bevel; x++) 477 { 478 SetPixelInfoPixel(frame_image,&shadow,q); 479 q+=GetPixelChannels(frame_image); 480 } 481 if (SyncCacheViewAuthenticPixels(frame_view,exception) == MagickFalse) 482 status=MagickFalse; 483 if (image->progress_monitor != (MagickProgressMonitor) NULL) 484 { 485 MagickBooleanType 486 proceed; 487 488#if defined(MAGICKCORE_OPENMP_SUPPORT) 489 #pragma omp critical (MagickCore_FrameImage) 490#endif 491 proceed=SetImageProgress(image,FrameImageTag,progress++,image->rows); 492 if (proceed == MagickFalse) 493 status=MagickFalse; 494 } 495 } 496 height=(size_t) (frame_info->inner_bevel+frame_info->height- 497 frame_info->y-image->rows-bevel_width+frame_info->outer_bevel); 498 if (height != 0) 499 { 500 register ssize_t 501 x; 502 503 register Quantum 504 *restrict q; 505 506 /* 507 Draw bottom of ornamental border. 508 */ 509 q=QueueCacheViewAuthenticPixels(frame_view,0,(ssize_t) (frame_image->rows- 510 height),frame_image->columns,height,exception); 511 if (q != (Quantum *) NULL) 512 { 513 /* 514 Draw bottom of ornamental border. 515 */ 516 for (y=frame_info->inner_bevel-1; y >= 0; y--) 517 { 518 for (x=0; x < (ssize_t) frame_info->outer_bevel; x++) 519 { 520 SetPixelInfoPixel(frame_image,&highlight,q); 521 q+=GetPixelChannels(frame_image); 522 } 523 for (x=0; x < (ssize_t) (frame_info->x-bevel_width); x++) 524 { 525 SetPixelInfoPixel(frame_image,&matte,q); 526 q+=GetPixelChannels(frame_image); 527 } 528 for (x=0; x < y; x++) 529 { 530 SetPixelInfoPixel(frame_image,&shadow,q); 531 q+=GetPixelChannels(frame_image); 532 } 533 for ( ; x < (ssize_t) (image->columns+2*frame_info->inner_bevel); x++) 534 { 535 if (x >= (ssize_t) (image->columns+2*frame_info->inner_bevel-y)) 536 SetPixelInfoPixel(frame_image,&highlight,q); 537 else 538 SetPixelInfoPixel(frame_image,&accentuate,q); 539 q+=GetPixelChannels(frame_image); 540 } 541 width=frame_info->width-frame_info->x-image->columns-bevel_width; 542 for (x=0; x < (ssize_t) width; x++) 543 { 544 SetPixelInfoPixel(frame_image,&matte,q); 545 q+=GetPixelChannels(frame_image); 546 } 547 for (x=0; x < (ssize_t) frame_info->outer_bevel; x++) 548 { 549 SetPixelInfoPixel(frame_image,&shadow,q); 550 q+=GetPixelChannels(frame_image); 551 } 552 } 553 height=frame_info->height-frame_info->y-image->rows-bevel_width; 554 for (y=0; y < (ssize_t) height; y++) 555 { 556 for (x=0; x < (ssize_t) frame_info->outer_bevel; x++) 557 { 558 SetPixelInfoPixel(frame_image,&highlight,q); 559 q+=GetPixelChannels(frame_image); 560 } 561 width=frame_image->columns-2*frame_info->outer_bevel; 562 for (x=0; x < (ssize_t) width; x++) 563 { 564 SetPixelInfoPixel(frame_image,&matte,q); 565 q+=GetPixelChannels(frame_image); 566 } 567 for (x=0; x < (ssize_t) frame_info->outer_bevel; x++) 568 { 569 SetPixelInfoPixel(frame_image,&shadow,q); 570 q+=GetPixelChannels(frame_image); 571 } 572 } 573 for (y=frame_info->outer_bevel-1; y >= 0; y--) 574 { 575 for (x=0; x < y; x++) 576 { 577 SetPixelInfoPixel(frame_image,&highlight,q); 578 q+=GetPixelChannels(frame_image); 579 } 580 for ( ; x < (ssize_t) frame_image->columns; x++) 581 { 582 if (x >= (ssize_t) (frame_image->columns-y)) 583 SetPixelInfoPixel(frame_image,&shadow,q); 584 else 585 SetPixelInfoPixel(frame_image,&trough,q); 586 q+=GetPixelChannels(frame_image); 587 } 588 } 589 (void) SyncCacheViewAuthenticPixels(frame_view,exception); 590 } 591 } 592 frame_view=DestroyCacheView(frame_view); 593 image_view=DestroyCacheView(image_view); 594 if ((compose != CopyCompositeOp) && ((compose != OverCompositeOp) || 595 (image->matte != MagickFalse))) 596 { 597 x=(ssize_t) (frame_info->outer_bevel+(frame_info->x-bevel_width)+ 598 frame_info->inner_bevel); 599 y=(ssize_t) (frame_info->outer_bevel+(frame_info->y-bevel_width)+ 600 frame_info->inner_bevel); 601 (void) CompositeImage(frame_image,image,compose,MagickTrue,x,y, 602 exception); 603 } 604 return(frame_image); 605} 606 607/* 608%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 609% % 610% % 611% % 612% R a i s e I m a g e % 613% % 614% % 615% % 616%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 617% 618% RaiseImage() creates a simulated three-dimensional button-like effect 619% by lightening and darkening the edges of the image. Members width and 620% height of raise_info define the width of the vertical and horizontal 621% edge of the effect. 622% 623% The format of the RaiseImage method is: 624% 625% MagickBooleanType RaiseImage(const Image *image, 626% const RectangleInfo *raise_info,const MagickBooleanType raise, 627% ExceptionInfo *exception) 628% 629% A description of each parameter follows: 630% 631% o image: the image. 632% 633% o raise_info: Define the width and height of the raise area. 634% 635% o raise: A value other than zero creates a 3-D raise effect, 636% otherwise it has a lowered effect. 637% 638% o exception: return any errors or warnings in this structure. 639% 640*/ 641MagickExport MagickBooleanType RaiseImage(Image *image, 642 const RectangleInfo *raise_info,const MagickBooleanType raise, 643 ExceptionInfo *exception) 644{ 645#define AccentuateFactor ScaleCharToQuantum(135) 646#define HighlightFactor ScaleCharToQuantum(190) 647#define ShadowFactor ScaleCharToQuantum(190) 648#define RaiseImageTag "Raise/Image" 649#define TroughFactor ScaleCharToQuantum(135) 650 651 CacheView 652 *image_view; 653 654 MagickBooleanType 655 status; 656 657 MagickOffsetType 658 progress; 659 660 Quantum 661 foreground, 662 background; 663 664 ssize_t 665 y; 666 667 assert(image != (Image *) NULL); 668 assert(image->signature == MagickSignature); 669 if (image->debug != MagickFalse) 670 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename); 671 assert(raise_info != (RectangleInfo *) NULL); 672 if ((image->columns <= (raise_info->width << 1)) || 673 (image->rows <= (raise_info->height << 1))) 674 ThrowBinaryException(OptionError,"ImageSizeMustExceedBevelWidth", 675 image->filename); 676 foreground=QuantumRange; 677 background=(Quantum) 0; 678 if (raise == MagickFalse) 679 { 680 foreground=(Quantum) 0; 681 background=QuantumRange; 682 } 683 if (SetImageStorageClass(image,DirectClass,exception) == MagickFalse) 684 return(MagickFalse); 685 /* 686 Raise image. 687 */ 688 status=MagickTrue; 689 progress=0; 690 image_view=AcquireAuthenticCacheView(image,exception); 691#if defined(MAGICKCORE_OPENMP_SUPPORT) 692 #pragma omp parallel for schedule(static) shared(progress,status) \ 693 dynamic_number_threads(image,image->columns,image->rows,1) 694#endif 695 for (y=0; y < (ssize_t) raise_info->height; y++) 696 { 697 register ssize_t 698 i, 699 x; 700 701 register Quantum 702 *restrict q; 703 704 if (status == MagickFalse) 705 continue; 706 q=GetCacheViewAuthenticPixels(image_view,0,y,image->columns,1,exception); 707 if (q == (Quantum *) NULL) 708 { 709 status=MagickFalse; 710 continue; 711 } 712 for (x=0; x < y; x++) 713 { 714 if (GetPixelMask(image,q) != 0) 715 { 716 q+=GetPixelChannels(image); 717 continue; 718 } 719 for (i=0; i < (ssize_t) GetPixelChannels(image); i++) 720 { 721 PixelChannel 722 channel; 723 724 PixelTrait 725 traits; 726 727 channel=GetPixelChannelMapChannel(image,i); 728 traits=GetPixelChannelMapTraits(image,channel); 729 if ((traits & UpdatePixelTrait) == 0) 730 continue; 731 q[i]=ClampToQuantum(QuantumScale*((MagickRealType) q[i]*HighlightFactor+ 732 (MagickRealType) foreground*(QuantumRange-HighlightFactor))); 733 } 734 q+=GetPixelChannels(image); 735 } 736 for ( ; x < (ssize_t) (image->columns-y); x++) 737 { 738 if (GetPixelMask(image,q) != 0) 739 { 740 q+=GetPixelChannels(image); 741 continue; 742 } 743 for (i=0; i < (ssize_t) GetPixelChannels(image); i++) 744 { 745 PixelChannel 746 channel; 747 748 PixelTrait 749 traits; 750 751 channel=GetPixelChannelMapChannel(image,i); 752 traits=GetPixelChannelMapTraits(image,channel); 753 if ((traits & UpdatePixelTrait) == 0) 754 continue; 755 q[i]=ClampToQuantum(QuantumScale*((MagickRealType) q[i]* 756 AccentuateFactor+(MagickRealType) foreground*(QuantumRange- 757 AccentuateFactor))); 758 } 759 q+=GetPixelChannels(image); 760 } 761 for ( ; x < (ssize_t) image->columns; x++) 762 { 763 if (GetPixelMask(image,q) != 0) 764 { 765 q+=GetPixelChannels(image); 766 continue; 767 } 768 for (i=0; i < (ssize_t) GetPixelChannels(image); i++) 769 { 770 PixelChannel 771 channel; 772 773 PixelTrait 774 traits; 775 776 channel=GetPixelChannelMapChannel(image,i); 777 traits=GetPixelChannelMapTraits(image,channel); 778 if ((traits & UpdatePixelTrait) == 0) 779 continue; 780 q[i]=ClampToQuantum(QuantumScale*((MagickRealType) q[i]*ShadowFactor+ 781 (MagickRealType) background*(QuantumRange-ShadowFactor))); 782 } 783 q+=GetPixelChannels(image); 784 } 785 if (SyncCacheViewAuthenticPixels(image_view,exception) == MagickFalse) 786 status=MagickFalse; 787 if (image->progress_monitor != (MagickProgressMonitor) NULL) 788 { 789 MagickBooleanType 790 proceed; 791 792 proceed=SetImageProgress(image,RaiseImageTag,progress++,image->rows); 793 if (proceed == MagickFalse) 794 status=MagickFalse; 795 } 796 } 797#if defined(MAGICKCORE_OPENMP_SUPPORT) 798 #pragma omp parallel for schedule(static) shared(progress,status) \ 799 dynamic_number_threads(image,image->columns,image->rows,1) 800#endif 801 for (y=(ssize_t) raise_info->height; y < (ssize_t) (image->rows-raise_info->height); y++) 802 { 803 register ssize_t 804 i, 805 x; 806 807 register Quantum 808 *restrict q; 809 810 if (status == MagickFalse) 811 continue; 812 q=GetCacheViewAuthenticPixels(image_view,0,y,image->columns,1,exception); 813 if (q == (Quantum *) NULL) 814 { 815 status=MagickFalse; 816 continue; 817 } 818 for (x=0; x < (ssize_t) raise_info->width; x++) 819 { 820 if (GetPixelMask(image,q) != 0) 821 { 822 q+=GetPixelChannels(image); 823 continue; 824 } 825 for (i=0; i < (ssize_t) GetPixelChannels(image); i++) 826 { 827 PixelChannel 828 channel; 829 830 PixelTrait 831 traits; 832 833 channel=GetPixelChannelMapChannel(image,i); 834 traits=GetPixelChannelMapTraits(image,channel); 835 if ((traits & UpdatePixelTrait) == 0) 836 continue; 837 q[i]=ClampToQuantum(QuantumScale*((MagickRealType) q[i]*HighlightFactor+ 838 (MagickRealType) foreground*(QuantumRange-HighlightFactor))); 839 } 840 q+=GetPixelChannels(image); 841 } 842 for ( ; x < (ssize_t) (image->columns-raise_info->width); x++) 843 q+=GetPixelChannels(image); 844 for ( ; x < (ssize_t) image->columns; x++) 845 { 846 if (GetPixelMask(image,q) != 0) 847 { 848 q+=GetPixelChannels(image); 849 continue; 850 } 851 for (i=0; i < (ssize_t) GetPixelChannels(image); i++) 852 { 853 PixelChannel 854 channel; 855 856 PixelTrait 857 traits; 858 859 channel=GetPixelChannelMapChannel(image,i); 860 traits=GetPixelChannelMapTraits(image,channel); 861 if ((traits & UpdatePixelTrait) == 0) 862 continue; 863 q[i]=ClampToQuantum(QuantumScale*((MagickRealType) q[i]*ShadowFactor+ 864 (MagickRealType) background*(QuantumRange-ShadowFactor))); 865 } 866 q+=GetPixelChannels(image); 867 } 868 if (SyncCacheViewAuthenticPixels(image_view,exception) == MagickFalse) 869 status=MagickFalse; 870 if (image->progress_monitor != (MagickProgressMonitor) NULL) 871 { 872 MagickBooleanType 873 proceed; 874 875 proceed=SetImageProgress(image,RaiseImageTag,progress++,image->rows); 876 if (proceed == MagickFalse) 877 status=MagickFalse; 878 } 879 } 880#if defined(MAGICKCORE_OPENMP_SUPPORT) 881 #pragma omp parallel for schedule(static) shared(progress,status) \ 882 dynamic_number_threads(image,image->columns,image->rows,1) 883#endif 884 for (y=(ssize_t) (image->rows-raise_info->height); y < (ssize_t) image->rows; y++) 885 { 886 register ssize_t 887 i, 888 x; 889 890 register Quantum 891 *restrict q; 892 893 if (status == MagickFalse) 894 continue; 895 q=GetCacheViewAuthenticPixels(image_view,0,y,image->columns,1,exception); 896 if (q == (Quantum *) NULL) 897 { 898 status=MagickFalse; 899 continue; 900 } 901 for (x=0; x < (ssize_t) (image->rows-y); x++) 902 { 903 if (GetPixelMask(image,q) != 0) 904 { 905 q+=GetPixelChannels(image); 906 continue; 907 } 908 for (i=0; i < (ssize_t) GetPixelChannels(image); i++) 909 { 910 PixelChannel 911 channel; 912 913 PixelTrait 914 traits; 915 916 channel=GetPixelChannelMapChannel(image,i); 917 traits=GetPixelChannelMapTraits(image,channel); 918 if ((traits & UpdatePixelTrait) == 0) 919 continue; 920 q[i]=ClampToQuantum(QuantumScale*((MagickRealType) q[i]*HighlightFactor+ 921 (MagickRealType) foreground*(QuantumRange-HighlightFactor))); 922 } 923 q+=GetPixelChannels(image); 924 } 925 for ( ; x < (ssize_t) (image->columns-(image->rows-y)); x++) 926 { 927 for (i=0; i < (ssize_t) GetPixelChannels(image); i++) 928 { 929 PixelChannel 930 channel; 931 932 PixelTrait 933 traits; 934 935 channel=GetPixelChannelMapChannel(image,i); 936 traits=GetPixelChannelMapTraits(image,channel); 937 if ((traits & UpdatePixelTrait) == 0) 938 continue; 939 q[i]=ClampToQuantum(QuantumScale*((MagickRealType) q[i]*TroughFactor+ 940 (MagickRealType) background*(QuantumRange-TroughFactor))); 941 } 942 q+=GetPixelChannels(image); 943 } 944 for ( ; x < (ssize_t) image->columns; x++) 945 { 946 if (GetPixelMask(image,q) != 0) 947 { 948 q+=GetPixelChannels(image); 949 continue; 950 } 951 for (i=0; i < (ssize_t) GetPixelChannels(image); i++) 952 { 953 PixelChannel 954 channel; 955 956 PixelTrait 957 traits; 958 959 channel=GetPixelChannelMapChannel(image,i); 960 traits=GetPixelChannelMapTraits(image,channel); 961 if ((traits & UpdatePixelTrait) == 0) 962 continue; 963 q[i]=ClampToQuantum(QuantumScale*((MagickRealType) q[i]*ShadowFactor+ 964 (MagickRealType) background*(QuantumRange-ShadowFactor))); 965 } 966 q+=GetPixelChannels(image); 967 } 968 if (SyncCacheViewAuthenticPixels(image_view,exception) == MagickFalse) 969 status=MagickFalse; 970 if (image->progress_monitor != (MagickProgressMonitor) NULL) 971 { 972 MagickBooleanType 973 proceed; 974 975#if defined(MAGICKCORE_OPENMP_SUPPORT) 976 #pragma omp critical (MagickCore_RaiseImage) 977#endif 978 proceed=SetImageProgress(image,RaiseImageTag,progress++,image->rows); 979 if (proceed == MagickFalse) 980 status=MagickFalse; 981 } 982 } 983 image_view=DestroyCacheView(image_view); 984 return(status); 985} 986