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