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