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