|
|
/*
|
|
|
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
|
|
% %
|
|
|
% %
|
|
|
% %
|
|
|
% DDDD EEEEE CCCC OOO RRRR AAA TTTTT EEEEE %
|
|
|
% D D E C O O R R A A T E %
|
|
|
% D D EEE C O O RRRR AAAAA T EEE %
|
|
|
% D D E C O O R R A A T E %
|
|
|
% DDDD EEEEE CCCC OOO R R A A T EEEEE %
|
|
|
% %
|
|
|
% %
|
|
|
% MagickCore Image Decoration Methods %
|
|
|
% %
|
|
|
% Software Design %
|
|
|
% Cristy %
|
|
|
% July 1992 %
|
|
|
% %
|
|
|
% %
|
|
|
% Copyright 1999-2021 ImageMagick Studio LLC, a non-profit organization %
|
|
|
% dedicated to making software imaging solutions freely available. %
|
|
|
% %
|
|
|
% You may not use this file except in compliance with the License. You may %
|
|
|
% obtain a copy of the License at %
|
|
|
% %
|
|
|
% https://imagemagick.org/script/license.php %
|
|
|
% %
|
|
|
% Unless required by applicable law or agreed to in writing, software %
|
|
|
% distributed under the License is distributed on an "AS IS" BASIS, %
|
|
|
% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. %
|
|
|
% See the License for the specific language governing permissions and %
|
|
|
% limitations under the License. %
|
|
|
% %
|
|
|
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
|
|
%
|
|
|
%
|
|
|
%
|
|
|
*/
|
|
|
|
|
|
/*
|
|
|
Include declarations.
|
|
|
*/
|
|
|
#include "MagickCore/studio.h"
|
|
|
#include "MagickCore/cache-view.h"
|
|
|
#include "MagickCore/color-private.h"
|
|
|
#include "MagickCore/colorspace-private.h"
|
|
|
#include "MagickCore/composite.h"
|
|
|
#include "MagickCore/decorate.h"
|
|
|
#include "MagickCore/exception.h"
|
|
|
#include "MagickCore/exception-private.h"
|
|
|
#include "MagickCore/image.h"
|
|
|
#include "MagickCore/memory_.h"
|
|
|
#include "MagickCore/monitor.h"
|
|
|
#include "MagickCore/monitor-private.h"
|
|
|
#include "MagickCore/pixel-accessor.h"
|
|
|
#include "MagickCore/quantum.h"
|
|
|
#include "MagickCore/quantum-private.h"
|
|
|
#include "MagickCore/resource_.h"
|
|
|
#include "MagickCore/thread-private.h"
|
|
|
#include "MagickCore/transform.h"
|
|
|
|
|
|
/*
|
|
|
Define declarations.
|
|
|
*/
|
|
|
#define AccentuateModulate ScaleCharToQuantum(80)
|
|
|
#define HighlightModulate ScaleCharToQuantum(125)
|
|
|
#define ShadowModulate ScaleCharToQuantum(135)
|
|
|
#define DepthModulate ScaleCharToQuantum(185)
|
|
|
#define TroughModulate ScaleCharToQuantum(110)
|
|
|
|
|
|
/*
|
|
|
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
|
|
% %
|
|
|
% %
|
|
|
% %
|
|
|
% B o r d e r I m a g e %
|
|
|
% %
|
|
|
% %
|
|
|
% %
|
|
|
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
|
|
%
|
|
|
% BorderImage() surrounds the image with a border of the color defined by
|
|
|
% the bordercolor member of the image structure. The width and height
|
|
|
% of the border are defined by the corresponding members of the border_info
|
|
|
% structure.
|
|
|
%
|
|
|
% The format of the BorderImage method is:
|
|
|
%
|
|
|
% Image *BorderImage(const Image *image,const RectangleInfo *border_info,
|
|
|
% const CompositeOperator compose,ExceptionInfo *exception)
|
|
|
%
|
|
|
% A description of each parameter follows:
|
|
|
%
|
|
|
% o image: the image.
|
|
|
%
|
|
|
% o border_info: define the width and height of the border.
|
|
|
%
|
|
|
% o compose: the composite operator.
|
|
|
%
|
|
|
% o exception: return any errors or warnings in this structure.
|
|
|
%
|
|
|
*/
|
|
|
MagickExport Image *BorderImage(const Image *image,
|
|
|
const RectangleInfo *border_info,const CompositeOperator compose,
|
|
|
ExceptionInfo *exception)
|
|
|
{
|
|
|
Image
|
|
|
*border_image,
|
|
|
*clone_image;
|
|
|
|
|
|
FrameInfo
|
|
|
frame_info;
|
|
|
|
|
|
assert(image != (const Image *) NULL);
|
|
|
assert(image->signature == MagickCoreSignature);
|
|
|
if (image->debug != MagickFalse)
|
|
|
(void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
|
|
|
assert(border_info != (RectangleInfo *) NULL);
|
|
|
frame_info.width=image->columns+(border_info->width << 1);
|
|
|
frame_info.height=image->rows+(border_info->height << 1);
|
|
|
frame_info.x=(ssize_t) border_info->width;
|
|
|
frame_info.y=(ssize_t) border_info->height;
|
|
|
frame_info.inner_bevel=0;
|
|
|
frame_info.outer_bevel=0;
|
|
|
clone_image=CloneImage(image,0,0,MagickTrue,exception);
|
|
|
if (clone_image == (Image *) NULL)
|
|
|
return((Image *) NULL);
|
|
|
clone_image->matte_color=image->border_color;
|
|
|
border_image=FrameImage(clone_image,&frame_info,compose,exception);
|
|
|
clone_image=DestroyImage(clone_image);
|
|
|
if (border_image != (Image *) NULL)
|
|
|
border_image->matte_color=image->matte_color;
|
|
|
return(border_image);
|
|
|
}
|
|
|
|
|
|
/*
|
|
|
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
|
|
% %
|
|
|
% %
|
|
|
% %
|
|
|
% F r a m e I m a g e %
|
|
|
% %
|
|
|
% %
|
|
|
% %
|
|
|
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
|
|
%
|
|
|
% FrameImage() adds a simulated three-dimensional border around the image.
|
|
|
% The color of the border is defined by the matte_color member of image.
|
|
|
% Members width and height of frame_info specify the border width of the
|
|
|
% vertical and horizontal sides of the frame. Members inner and outer
|
|
|
% indicate the width of the inner and outer shadows of the frame.
|
|
|
%
|
|
|
% The format of the FrameImage method is:
|
|
|
%
|
|
|
% Image *FrameImage(const Image *image,const FrameInfo *frame_info,
|
|
|
% const CompositeOperator compose,ExceptionInfo *exception)
|
|
|
%
|
|
|
% A description of each parameter follows:
|
|
|
%
|
|
|
% o image: the image.
|
|
|
%
|
|
|
% o frame_info: Define the width and height of the frame and its bevels.
|
|
|
%
|
|
|
% o compose: the composite operator.
|
|
|
%
|
|
|
% o exception: return any errors or warnings in this structure.
|
|
|
%
|
|
|
*/
|
|
|
MagickExport Image *FrameImage(const Image *image,const FrameInfo *frame_info,
|
|
|
const CompositeOperator compose,ExceptionInfo *exception)
|
|
|
{
|
|
|
#define FrameImageTag "Frame/Image"
|
|
|
|
|
|
CacheView
|
|
|
*image_view,
|
|
|
*frame_view;
|
|
|
|
|
|
Image
|
|
|
*frame_image;
|
|
|
|
|
|
MagickBooleanType
|
|
|
status;
|
|
|
|
|
|
MagickOffsetType
|
|
|
progress;
|
|
|
|
|
|
PixelInfo
|
|
|
accentuate,
|
|
|
highlight,
|
|
|
matte,
|
|
|
shadow,
|
|
|
trough;
|
|
|
|
|
|
ssize_t
|
|
|
x;
|
|
|
|
|
|
size_t
|
|
|
bevel_width,
|
|
|
height,
|
|
|
width;
|
|
|
|
|
|
ssize_t
|
|
|
y;
|
|
|
|
|
|
/*
|
|
|
Check frame geometry.
|
|
|
*/
|
|
|
assert(image != (Image *) NULL);
|
|
|
assert(image->signature == MagickCoreSignature);
|
|
|
if (image->debug != MagickFalse)
|
|
|
(void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
|
|
|
assert(frame_info != (FrameInfo *) NULL);
|
|
|
if ((frame_info->outer_bevel < 0) || (frame_info->inner_bevel < 0))
|
|
|
ThrowImageException(OptionError,"FrameIsLessThanImageSize");
|
|
|
bevel_width=(size_t) (frame_info->outer_bevel+frame_info->inner_bevel);
|
|
|
x=(ssize_t) frame_info->width-frame_info->x-bevel_width;
|
|
|
y=(ssize_t) frame_info->height-frame_info->y-bevel_width;
|
|
|
if ((x < (ssize_t) image->columns) || (y < (ssize_t) image->rows))
|
|
|
ThrowImageException(OptionError,"FrameIsLessThanImageSize");
|
|
|
/*
|
|
|
Initialize framed image attributes.
|
|
|
*/
|
|
|
frame_image=CloneImage(image,frame_info->width,frame_info->height,MagickTrue,
|
|
|
exception);
|
|
|
if (frame_image == (Image *) NULL)
|
|
|
return((Image *) NULL);
|
|
|
if (SetImageStorageClass(frame_image,DirectClass,exception) == MagickFalse)
|
|
|
{
|
|
|
frame_image=DestroyImage(frame_image);
|
|
|
return((Image *) NULL);
|
|
|
}
|
|
|
if ((IsPixelInfoGray(&frame_image->border_color) == MagickFalse) &&
|
|
|
(IsGrayColorspace(frame_image->colorspace) != MagickFalse))
|
|
|
(void) SetImageColorspace(frame_image,sRGBColorspace,exception);
|
|
|
if ((frame_image->matte_color.alpha_trait != UndefinedPixelTrait) &&
|
|
|
(frame_image->alpha_trait == UndefinedPixelTrait))
|
|
|
(void) SetImageAlpha(frame_image,OpaqueAlpha,exception);
|
|
|
frame_image->page=image->page;
|
|
|
if ((image->page.width != 0) && (image->page.height != 0))
|
|
|
{
|
|
|
frame_image->page.width+=frame_image->columns-image->columns;
|
|
|
frame_image->page.height+=frame_image->rows-image->rows;
|
|
|
}
|
|
|
/*
|
|
|
Initialize 3D effects color.
|
|
|
*/
|
|
|
matte=image->matte_color;
|
|
|
accentuate=matte;
|
|
|
accentuate.red=(double) (QuantumScale*((QuantumRange-
|
|
|
AccentuateModulate)*matte.red+(QuantumRange*AccentuateModulate)));
|
|
|
accentuate.green=(double) (QuantumScale*((QuantumRange-
|
|
|
AccentuateModulate)*matte.green+(QuantumRange*AccentuateModulate)));
|
|
|
accentuate.blue=(double) (QuantumScale*((QuantumRange-
|
|
|
AccentuateModulate)*matte.blue+(QuantumRange*AccentuateModulate)));
|
|
|
accentuate.black=(double) (QuantumScale*((QuantumRange-
|
|
|
AccentuateModulate)*matte.black+(QuantumRange*AccentuateModulate)));
|
|
|
accentuate.alpha=matte.alpha;
|
|
|
highlight=matte;
|
|
|
highlight.red=(double) (QuantumScale*((QuantumRange-
|
|
|
HighlightModulate)*matte.red+(QuantumRange*HighlightModulate)));
|
|
|
highlight.green=(double) (QuantumScale*((QuantumRange-
|
|
|
HighlightModulate)*matte.green+(QuantumRange*HighlightModulate)));
|
|
|
highlight.blue=(double) (QuantumScale*((QuantumRange-
|
|
|
HighlightModulate)*matte.blue+(QuantumRange*HighlightModulate)));
|
|
|
highlight.black=(double) (QuantumScale*((QuantumRange-
|
|
|
HighlightModulate)*matte.black+(QuantumRange*HighlightModulate)));
|
|
|
highlight.alpha=matte.alpha;
|
|
|
shadow=matte;
|
|
|
shadow.red=QuantumScale*matte.red*ShadowModulate;
|
|
|
shadow.green=QuantumScale*matte.green*ShadowModulate;
|
|
|
shadow.blue=QuantumScale*matte.blue*ShadowModulate;
|
|
|
shadow.black=QuantumScale*matte.black*ShadowModulate;
|
|
|
shadow.alpha=matte.alpha;
|
|
|
trough=matte;
|
|
|
trough.red=QuantumScale*matte.red*TroughModulate;
|
|
|
trough.green=QuantumScale*matte.green*TroughModulate;
|
|
|
trough.blue=QuantumScale*matte.blue*TroughModulate;
|
|
|
trough.black=QuantumScale*matte.black*TroughModulate;
|
|
|
trough.alpha=matte.alpha;
|
|
|
status=MagickTrue;
|
|
|
progress=0;
|
|
|
image_view=AcquireVirtualCacheView(image,exception);
|
|
|
frame_view=AcquireAuthenticCacheView(frame_image,exception);
|
|
|
height=(size_t) (frame_info->outer_bevel+(frame_info->y-bevel_width)+
|
|
|
frame_info->inner_bevel);
|
|
|
if (height != 0)
|
|
|
{
|
|
|
ssize_t
|
|
|
x;
|
|
|
|
|
|
Quantum
|
|
|
*magick_restrict q;
|
|
|
|
|
|
/*
|
|
|
Draw top of ornamental border.
|
|
|
*/
|
|
|
q=QueueCacheViewAuthenticPixels(frame_view,0,0,frame_image->columns,
|
|
|
height,exception);
|
|
|
if (q != (Quantum *) NULL)
|
|
|
{
|
|
|
/*
|
|
|
Draw top of ornamental border.
|
|
|
*/
|
|
|
for (y=0; y < (ssize_t) frame_info->outer_bevel; y++)
|
|
|
{
|
|
|
for (x=0; x < (ssize_t) (frame_image->columns-y); x++)
|
|
|
{
|
|
|
if (x < y)
|
|
|
SetPixelViaPixelInfo(frame_image,&highlight,q);
|
|
|
else
|
|
|
SetPixelViaPixelInfo(frame_image,&accentuate,q);
|
|
|
q+=GetPixelChannels(frame_image);
|
|
|
}
|
|
|
for ( ; x < (ssize_t) frame_image->columns; x++)
|
|
|
{
|
|
|
SetPixelViaPixelInfo(frame_image,&shadow,q);
|
|
|
q+=GetPixelChannels(frame_image);
|
|
|
}
|
|
|
}
|
|
|
for (y=0; y < (ssize_t) (frame_info->y-bevel_width); y++)
|
|
|
{
|
|
|
for (x=0; x < (ssize_t) frame_info->outer_bevel; x++)
|
|
|
{
|
|
|
SetPixelViaPixelInfo(frame_image,&highlight,q);
|
|
|
q+=GetPixelChannels(frame_image);
|
|
|
}
|
|
|
width=frame_image->columns-2*frame_info->outer_bevel;
|
|
|
for (x=0; x < (ssize_t) width; x++)
|
|
|
{
|
|
|
SetPixelViaPixelInfo(frame_image,&matte,q);
|
|
|
q+=GetPixelChannels(frame_image);
|
|
|
}
|
|
|
for (x=0; x < (ssize_t) frame_info->outer_bevel; x++)
|
|
|
{
|
|
|
SetPixelViaPixelInfo(frame_image,&shadow,q);
|
|
|
q+=GetPixelChannels(frame_image);
|
|
|
}
|
|
|
}
|
|
|
for (y=0; y < (ssize_t) frame_info->inner_bevel; y++)
|
|
|
{
|
|
|
for (x=0; x < (ssize_t) frame_info->outer_bevel; x++)
|
|
|
{
|
|
|
SetPixelViaPixelInfo(frame_image,&highlight,q);
|
|
|
q+=GetPixelChannels(frame_image);
|
|
|
}
|
|
|
for (x=0; x < (ssize_t) (frame_info->x-bevel_width); x++)
|
|
|
{
|
|
|
SetPixelViaPixelInfo(frame_image,&matte,q);
|
|
|
q+=GetPixelChannels(frame_image);
|
|
|
}
|
|
|
width=image->columns+((size_t) frame_info->inner_bevel << 1)-
|
|
|
y;
|
|
|
for (x=0; x < (ssize_t) width; x++)
|
|
|
{
|
|
|
if (x < y)
|
|
|
SetPixelViaPixelInfo(frame_image,&shadow,q);
|
|
|
else
|
|
|
SetPixelViaPixelInfo(frame_image,&trough,q);
|
|
|
q+=GetPixelChannels(frame_image);
|
|
|
}
|
|
|
for ( ; x < (ssize_t) (image->columns+2*frame_info->inner_bevel); x++)
|
|
|
{
|
|
|
SetPixelViaPixelInfo(frame_image,&highlight,q);
|
|
|
q+=GetPixelChannels(frame_image);
|
|
|
}
|
|
|
width=frame_info->width-frame_info->x-image->columns-bevel_width;
|
|
|
for (x=0; x < (ssize_t) width; x++)
|
|
|
{
|
|
|
SetPixelViaPixelInfo(frame_image,&matte,q);
|
|
|
q+=GetPixelChannels(frame_image);
|
|
|
}
|
|
|
for (x=0; x < (ssize_t) frame_info->outer_bevel; x++)
|
|
|
{
|
|
|
SetPixelViaPixelInfo(frame_image,&shadow,q);
|
|
|
q+=GetPixelChannels(frame_image);
|
|
|
}
|
|
|
}
|
|
|
(void) SyncCacheViewAuthenticPixels(frame_view,exception);
|
|
|
}
|
|
|
}
|
|
|
/*
|
|
|
Draw sides of ornamental border.
|
|
|
*/
|
|
|
#if defined(MAGICKCORE_OPENMP_SUPPORT)
|
|
|
#pragma omp parallel for schedule(static) shared(progress,status) \
|
|
|
magick_number_threads(image,frame_image,image->rows,1)
|
|
|
#endif
|
|
|
for (y=0; y < (ssize_t) image->rows; y++)
|
|
|
{
|
|
|
ssize_t
|
|
|
x;
|
|
|
|
|
|
Quantum
|
|
|
*magick_restrict q;
|
|
|
|
|
|
size_t
|
|
|
width;
|
|
|
|
|
|
/*
|
|
|
Initialize scanline with matte color.
|
|
|
*/
|
|
|
if (status == MagickFalse)
|
|
|
continue;
|
|
|
q=QueueCacheViewAuthenticPixels(frame_view,0,frame_info->y+y,
|
|
|
frame_image->columns,1,exception);
|
|
|
if (q == (Quantum *) NULL)
|
|
|
{
|
|
|
status=MagickFalse;
|
|
|
continue;
|
|
|
}
|
|
|
for (x=0; x < (ssize_t) frame_info->outer_bevel; x++)
|
|
|
{
|
|
|
SetPixelViaPixelInfo(frame_image,&highlight,q);
|
|
|
q+=GetPixelChannels(frame_image);
|
|
|
}
|
|
|
for (x=0; x < (ssize_t) (frame_info->x-bevel_width); x++)
|
|
|
{
|
|
|
SetPixelViaPixelInfo(frame_image,&matte,q);
|
|
|
q+=GetPixelChannels(frame_image);
|
|
|
}
|
|
|
for (x=0; x < (ssize_t) frame_info->inner_bevel; x++)
|
|
|
{
|
|
|
SetPixelViaPixelInfo(frame_image,&shadow,q);
|
|
|
q+=GetPixelChannels(frame_image);
|
|
|
}
|
|
|
/*
|
|
|
Set frame interior pixels.
|
|
|
*/
|
|
|
for (x=0; x < (ssize_t) image->columns; x++)
|
|
|
{
|
|
|
SetPixelViaPixelInfo(frame_image,&frame_image->border_color,q);
|
|
|
q+=GetPixelChannels(frame_image);
|
|
|
}
|
|
|
for (x=0; x < (ssize_t) frame_info->inner_bevel; x++)
|
|
|
{
|
|
|
SetPixelViaPixelInfo(frame_image,&highlight,q);
|
|
|
q+=GetPixelChannels(frame_image);
|
|
|
}
|
|
|
width=frame_info->width-frame_info->x-image->columns-bevel_width;
|
|
|
for (x=0; x < (ssize_t) width; x++)
|
|
|
{
|
|
|
SetPixelViaPixelInfo(frame_image,&matte,q);
|
|
|
q+=GetPixelChannels(frame_image);
|
|
|
}
|
|
|
for (x=0; x < (ssize_t) frame_info->outer_bevel; x++)
|
|
|
{
|
|
|
SetPixelViaPixelInfo(frame_image,&shadow,q);
|
|
|
q+=GetPixelChannels(frame_image);
|
|
|
}
|
|
|
if (SyncCacheViewAuthenticPixels(frame_view,exception) == MagickFalse)
|
|
|
status=MagickFalse;
|
|
|
if (image->progress_monitor != (MagickProgressMonitor) NULL)
|
|
|
{
|
|
|
MagickBooleanType
|
|
|
proceed;
|
|
|
|
|
|
#if defined(MAGICKCORE_OPENMP_SUPPORT)
|
|
|
#pragma omp atomic
|
|
|
#endif
|
|
|
progress++;
|
|
|
proceed=SetImageProgress(image,FrameImageTag,progress,image->rows);
|
|
|
if (proceed == MagickFalse)
|
|
|
status=MagickFalse;
|
|
|
}
|
|
|
}
|
|
|
height=(size_t) (frame_info->inner_bevel+frame_info->height-
|
|
|
frame_info->y-image->rows-bevel_width+frame_info->outer_bevel);
|
|
|
if (height != 0)
|
|
|
{
|
|
|
ssize_t
|
|
|
x;
|
|
|
|
|
|
Quantum
|
|
|
*magick_restrict q;
|
|
|
|
|
|
/*
|
|
|
Draw bottom of ornamental border.
|
|
|
*/
|
|
|
q=QueueCacheViewAuthenticPixels(frame_view,0,(ssize_t) (frame_image->rows-
|
|
|
height),frame_image->columns,height,exception);
|
|
|
if (q != (Quantum *) NULL)
|
|
|
{
|
|
|
/*
|
|
|
Draw bottom of ornamental border.
|
|
|
*/
|
|
|
for (y=frame_info->inner_bevel-1; y >= 0; y--)
|
|
|
{
|
|
|
for (x=0; x < (ssize_t) frame_info->outer_bevel; x++)
|
|
|
{
|
|
|
SetPixelViaPixelInfo(frame_image,&highlight,q);
|
|
|
q+=GetPixelChannels(frame_image);
|
|
|
}
|
|
|
for (x=0; x < (ssize_t) (frame_info->x-bevel_width); x++)
|
|
|
{
|
|
|
SetPixelViaPixelInfo(frame_image,&matte,q);
|
|
|
q+=GetPixelChannels(frame_image);
|
|
|
}
|
|
|
for (x=0; x < y; x++)
|
|
|
{
|
|
|
SetPixelViaPixelInfo(frame_image,&shadow,q);
|
|
|
q+=GetPixelChannels(frame_image);
|
|
|
}
|
|
|
for ( ; x < (ssize_t) (image->columns+2*frame_info->inner_bevel); x++)
|
|
|
{
|
|
|
if (x >= (ssize_t) (image->columns+2*frame_info->inner_bevel-y))
|
|
|
SetPixelViaPixelInfo(frame_image,&highlight,q);
|
|
|
else
|
|
|
SetPixelViaPixelInfo(frame_image,&accentuate,q);
|
|
|
q+=GetPixelChannels(frame_image);
|
|
|
}
|
|
|
width=frame_info->width-frame_info->x-image->columns-bevel_width;
|
|
|
for (x=0; x < (ssize_t) width; x++)
|
|
|
{
|
|
|
SetPixelViaPixelInfo(frame_image,&matte,q);
|
|
|
q+=GetPixelChannels(frame_image);
|
|
|
}
|
|
|
for (x=0; x < (ssize_t) frame_info->outer_bevel; x++)
|
|
|
{
|
|
|
SetPixelViaPixelInfo(frame_image,&shadow,q);
|
|
|
q+=GetPixelChannels(frame_image);
|
|
|
}
|
|
|
}
|
|
|
height=frame_info->height-frame_info->y-image->rows-bevel_width;
|
|
|
for (y=0; y < (ssize_t) height; y++)
|
|
|
{
|
|
|
for (x=0; x < (ssize_t) frame_info->outer_bevel; x++)
|
|
|
{
|
|
|
SetPixelViaPixelInfo(frame_image,&highlight,q);
|
|
|
q+=GetPixelChannels(frame_image);
|
|
|
}
|
|
|
width=frame_image->columns-2*frame_info->outer_bevel;
|
|
|
for (x=0; x < (ssize_t) width; x++)
|
|
|
{
|
|
|
SetPixelViaPixelInfo(frame_image,&matte,q);
|
|
|
q+=GetPixelChannels(frame_image);
|
|
|
}
|
|
|
for (x=0; x < (ssize_t) frame_info->outer_bevel; x++)
|
|
|
{
|
|
|
SetPixelViaPixelInfo(frame_image,&shadow,q);
|
|
|
q+=GetPixelChannels(frame_image);
|
|
|
}
|
|
|
}
|
|
|
for (y=frame_info->outer_bevel-1; y >= 0; y--)
|
|
|
{
|
|
|
for (x=0; x < y; x++)
|
|
|
{
|
|
|
SetPixelViaPixelInfo(frame_image,&highlight,q);
|
|
|
q+=GetPixelChannels(frame_image);
|
|
|
}
|
|
|
for ( ; x < (ssize_t) frame_image->columns; x++)
|
|
|
{
|
|
|
if (x >= (ssize_t) (frame_image->columns-y))
|
|
|
SetPixelViaPixelInfo(frame_image,&shadow,q);
|
|
|
else
|
|
|
SetPixelViaPixelInfo(frame_image,&trough,q);
|
|
|
q+=GetPixelChannels(frame_image);
|
|
|
}
|
|
|
}
|
|
|
(void) SyncCacheViewAuthenticPixels(frame_view,exception);
|
|
|
}
|
|
|
}
|
|
|
frame_view=DestroyCacheView(frame_view);
|
|
|
image_view=DestroyCacheView(image_view);
|
|
|
x=(ssize_t) (frame_info->outer_bevel+(frame_info->x-bevel_width)+
|
|
|
frame_info->inner_bevel);
|
|
|
y=(ssize_t) (frame_info->outer_bevel+(frame_info->y-bevel_width)+
|
|
|
frame_info->inner_bevel);
|
|
|
if (status != MagickFalse)
|
|
|
status=CompositeImage(frame_image,image,compose,MagickTrue,x,y,
|
|
|
exception);
|
|
|
if (status == MagickFalse)
|
|
|
frame_image=DestroyImage(frame_image);
|
|
|
return(frame_image);
|
|
|
}
|
|
|
|
|
|
/*
|
|
|
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
|
|
% %
|
|
|
% %
|
|
|
% %
|
|
|
% R a i s e I m a g e %
|
|
|
% %
|
|
|
% %
|
|
|
% %
|
|
|
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
|
|
%
|
|
|
% RaiseImage() creates a simulated three-dimensional button-like effect
|
|
|
% by lightening and darkening the edges of the image. Members width and
|
|
|
% height of raise_info define the width of the vertical and horizontal
|
|
|
% edge of the effect.
|
|
|
%
|
|
|
% The format of the RaiseImage method is:
|
|
|
%
|
|
|
% MagickBooleanType RaiseImage(const Image *image,
|
|
|
% const RectangleInfo *raise_info,const MagickBooleanType raise,
|
|
|
% ExceptionInfo *exception)
|
|
|
%
|
|
|
% A description of each parameter follows:
|
|
|
%
|
|
|
% o image: the image.
|
|
|
%
|
|
|
% o raise_info: Define the width and height of the raise area.
|
|
|
%
|
|
|
% o raise: A value other than zero creates a 3-D raise effect,
|
|
|
% otherwise it has a lowered effect.
|
|
|
%
|
|
|
% o exception: return any errors or warnings in this structure.
|
|
|
%
|
|
|
*/
|
|
|
MagickExport MagickBooleanType RaiseImage(Image *image,
|
|
|
const RectangleInfo *raise_info,const MagickBooleanType raise,
|
|
|
ExceptionInfo *exception)
|
|
|
{
|
|
|
#define AccentuateFactor ScaleCharToQuantum(135)
|
|
|
#define HighlightFactor ScaleCharToQuantum(190)
|
|
|
#define ShadowFactor ScaleCharToQuantum(190)
|
|
|
#define RaiseImageTag "Raise/Image"
|
|
|
#define TroughFactor ScaleCharToQuantum(135)
|
|
|
|
|
|
CacheView
|
|
|
*image_view;
|
|
|
|
|
|
MagickBooleanType
|
|
|
status;
|
|
|
|
|
|
MagickOffsetType
|
|
|
progress;
|
|
|
|
|
|
Quantum
|
|
|
foreground,
|
|
|
background;
|
|
|
|
|
|
ssize_t
|
|
|
y;
|
|
|
|
|
|
assert(image != (Image *) NULL);
|
|
|
assert(image->signature == MagickCoreSignature);
|
|
|
if (image->debug != MagickFalse)
|
|
|
(void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
|
|
|
assert(raise_info != (RectangleInfo *) NULL);
|
|
|
if ((image->columns <= (raise_info->width << 1)) ||
|
|
|
(image->rows <= (raise_info->height << 1)))
|
|
|
ThrowBinaryException(OptionError,"ImageSizeMustExceedBevelWidth",
|
|
|
image->filename);
|
|
|
foreground=QuantumRange;
|
|
|
background=(Quantum) 0;
|
|
|
if (raise == MagickFalse)
|
|
|
{
|
|
|
foreground=(Quantum) 0;
|
|
|
background=QuantumRange;
|
|
|
}
|
|
|
if (SetImageStorageClass(image,DirectClass,exception) == MagickFalse)
|
|
|
return(MagickFalse);
|
|
|
/*
|
|
|
Raise image.
|
|
|
*/
|
|
|
status=MagickTrue;
|
|
|
progress=0;
|
|
|
image_view=AcquireAuthenticCacheView(image,exception);
|
|
|
#if defined(MAGICKCORE_OPENMP_SUPPORT)
|
|
|
#pragma omp parallel for schedule(static) shared(progress,status) \
|
|
|
magick_number_threads(image,image,raise_info->height,1)
|
|
|
#endif
|
|
|
for (y=0; y < (ssize_t) raise_info->height; y++)
|
|
|
{
|
|
|
ssize_t
|
|
|
i,
|
|
|
x;
|
|
|
|
|
|
Quantum
|
|
|
*magick_restrict q;
|
|
|
|
|
|
if (status == MagickFalse)
|
|
|
continue;
|
|
|
q=GetCacheViewAuthenticPixels(image_view,0,y,image->columns,1,exception);
|
|
|
if (q == (Quantum *) NULL)
|
|
|
{
|
|
|
status=MagickFalse;
|
|
|
continue;
|
|
|
}
|
|
|
for (x=0; x < y; x++)
|
|
|
{
|
|
|
for (i=0; i < (ssize_t) GetPixelChannels(image); i++)
|
|
|
{
|
|
|
PixelChannel channel = GetPixelChannelChannel(image,i);
|
|
|
PixelTrait traits = GetPixelChannelTraits(image,channel);
|
|
|
if ((traits & UpdatePixelTrait) == 0)
|
|
|
continue;
|
|
|
q[i]=ClampToQuantum(QuantumScale*((double) q[i]*HighlightFactor+(double)
|
|
|
foreground*(QuantumRange-HighlightFactor)));
|
|
|
}
|
|
|
q+=GetPixelChannels(image);
|
|
|
}
|
|
|
for ( ; x < (ssize_t) (image->columns-y); x++)
|
|
|
{
|
|
|
for (i=0; i < (ssize_t) GetPixelChannels(image); i++)
|
|
|
{
|
|
|
PixelChannel channel = GetPixelChannelChannel(image,i);
|
|
|
PixelTrait traits = GetPixelChannelTraits(image,channel);
|
|
|
if ((traits & UpdatePixelTrait) == 0)
|
|
|
continue;
|
|
|
q[i]=ClampToQuantum(QuantumScale*((double) q[i]*AccentuateFactor+
|
|
|
(double) foreground*(QuantumRange-AccentuateFactor)));
|
|
|
}
|
|
|
q+=GetPixelChannels(image);
|
|
|
}
|
|
|
for ( ; x < (ssize_t) image->columns; x++)
|
|
|
{
|
|
|
for (i=0; i < (ssize_t) GetPixelChannels(image); i++)
|
|
|
{
|
|
|
PixelChannel channel = GetPixelChannelChannel(image,i);
|
|
|
PixelTrait traits = GetPixelChannelTraits(image,channel);
|
|
|
if ((traits & UpdatePixelTrait) == 0)
|
|
|
continue;
|
|
|
q[i]=ClampToQuantum(QuantumScale*((double) q[i]*ShadowFactor+(double)
|
|
|
background*(QuantumRange-ShadowFactor)));
|
|
|
}
|
|
|
q+=GetPixelChannels(image);
|
|
|
}
|
|
|
if (SyncCacheViewAuthenticPixels(image_view,exception) == MagickFalse)
|
|
|
status=MagickFalse;
|
|
|
if (image->progress_monitor != (MagickProgressMonitor) NULL)
|
|
|
{
|
|
|
MagickBooleanType
|
|
|
proceed;
|
|
|
|
|
|
#if defined(MAGICKCORE_OPENMP_SUPPORT)
|
|
|
#pragma omp atomic
|
|
|
#endif
|
|
|
progress++;
|
|
|
proceed=SetImageProgress(image,RaiseImageTag,progress,image->rows);
|
|
|
if (proceed == MagickFalse)
|
|
|
status=MagickFalse;
|
|
|
}
|
|
|
}
|
|
|
#if defined(MAGICKCORE_OPENMP_SUPPORT)
|
|
|
#pragma omp parallel for schedule(static) shared(progress,status) \
|
|
|
magick_number_threads(image,image,image->rows-2*raise_info->height,1)
|
|
|
#endif
|
|
|
for (y=(ssize_t) raise_info->height; y < (ssize_t) (image->rows-raise_info->height); y++)
|
|
|
{
|
|
|
ssize_t
|
|
|
i,
|
|
|
x;
|
|
|
|
|
|
Quantum
|
|
|
*magick_restrict q;
|
|
|
|
|
|
if (status == MagickFalse)
|
|
|
continue;
|
|
|
q=GetCacheViewAuthenticPixels(image_view,0,y,image->columns,1,exception);
|
|
|
if (q == (Quantum *) NULL)
|
|
|
{
|
|
|
status=MagickFalse;
|
|
|
continue;
|
|
|
}
|
|
|
for (x=0; x < (ssize_t) raise_info->width; x++)
|
|
|
{
|
|
|
for (i=0; i < (ssize_t) GetPixelChannels(image); i++)
|
|
|
{
|
|
|
PixelChannel channel = GetPixelChannelChannel(image,i);
|
|
|
PixelTrait traits = GetPixelChannelTraits(image,channel);
|
|
|
if ((traits & UpdatePixelTrait) == 0)
|
|
|
continue;
|
|
|
q[i]=ClampToQuantum(QuantumScale*((double) q[i]*HighlightFactor+(double)
|
|
|
foreground*(QuantumRange-HighlightFactor)));
|
|
|
}
|
|
|
q+=GetPixelChannels(image);
|
|
|
}
|
|
|
for ( ; x < (ssize_t) (image->columns-raise_info->width); x++)
|
|
|
q+=GetPixelChannels(image);
|
|
|
for ( ; x < (ssize_t) image->columns; x++)
|
|
|
{
|
|
|
for (i=0; i < (ssize_t) GetPixelChannels(image); i++)
|
|
|
{
|
|
|
PixelChannel channel = GetPixelChannelChannel(image,i);
|
|
|
PixelTrait traits = GetPixelChannelTraits(image,channel);
|
|
|
if ((traits & UpdatePixelTrait) == 0)
|
|
|
continue;
|
|
|
q[i]=ClampToQuantum(QuantumScale*((double) q[i]*ShadowFactor+(double)
|
|
|
background*(QuantumRange-ShadowFactor)));
|
|
|
}
|
|
|
q+=GetPixelChannels(image);
|
|
|
}
|
|
|
if (SyncCacheViewAuthenticPixels(image_view,exception) == MagickFalse)
|
|
|
status=MagickFalse;
|
|
|
if (image->progress_monitor != (MagickProgressMonitor) NULL)
|
|
|
{
|
|
|
MagickBooleanType
|
|
|
proceed;
|
|
|
|
|
|
#if defined(MAGICKCORE_OPENMP_SUPPORT)
|
|
|
#pragma omp atomic
|
|
|
#endif
|
|
|
progress++;
|
|
|
proceed=SetImageProgress(image,RaiseImageTag,progress,image->rows);
|
|
|
if (proceed == MagickFalse)
|
|
|
status=MagickFalse;
|
|
|
}
|
|
|
}
|
|
|
#if defined(MAGICKCORE_OPENMP_SUPPORT)
|
|
|
#pragma omp parallel for schedule(static) shared(progress,status) \
|
|
|
magick_number_threads(image,image,image->rows-raise_info->height,1)
|
|
|
#endif
|
|
|
for (y=(ssize_t) (image->rows-raise_info->height); y < (ssize_t) image->rows; y++)
|
|
|
{
|
|
|
ssize_t
|
|
|
i,
|
|
|
x;
|
|
|
|
|
|
Quantum
|
|
|
*magick_restrict q;
|
|
|
|
|
|
if (status == MagickFalse)
|
|
|
continue;
|
|
|
q=GetCacheViewAuthenticPixels(image_view,0,y,image->columns,1,exception);
|
|
|
if (q == (Quantum *) NULL)
|
|
|
{
|
|
|
status=MagickFalse;
|
|
|
continue;
|
|
|
}
|
|
|
for (x=0; x < (ssize_t) (image->rows-y); x++)
|
|
|
{
|
|
|
for (i=0; i < (ssize_t) GetPixelChannels(image); i++)
|
|
|
{
|
|
|
PixelChannel channel = GetPixelChannelChannel(image,i);
|
|
|
PixelTrait traits = GetPixelChannelTraits(image,channel);
|
|
|
if ((traits & UpdatePixelTrait) == 0)
|
|
|
continue;
|
|
|
q[i]=ClampToQuantum(QuantumScale*((double) q[i]*HighlightFactor+(double)
|
|
|
foreground*(QuantumRange-HighlightFactor)));
|
|
|
}
|
|
|
q+=GetPixelChannels(image);
|
|
|
}
|
|
|
for ( ; x < (ssize_t) (image->columns-(image->rows-y)); x++)
|
|
|
{
|
|
|
for (i=0; i < (ssize_t) GetPixelChannels(image); i++)
|
|
|
{
|
|
|
PixelChannel channel = GetPixelChannelChannel(image,i);
|
|
|
PixelTrait traits = GetPixelChannelTraits(image,channel);
|
|
|
if ((traits & UpdatePixelTrait) == 0)
|
|
|
continue;
|
|
|
q[i]=ClampToQuantum(QuantumScale*((double) q[i]*TroughFactor+
|
|
|
(double) background*(QuantumRange-TroughFactor)));
|
|
|
}
|
|
|
q+=GetPixelChannels(image);
|
|
|
}
|
|
|
for ( ; x < (ssize_t) image->columns; x++)
|
|
|
{
|
|
|
for (i=0; i < (ssize_t) GetPixelChannels(image); i++)
|
|
|
{
|
|
|
PixelChannel channel = GetPixelChannelChannel(image,i);
|
|
|
PixelTrait traits = GetPixelChannelTraits(image,channel);
|
|
|
if ((traits & UpdatePixelTrait) == 0)
|
|
|
continue;
|
|
|
q[i]=ClampToQuantum(QuantumScale*((double) q[i]*ShadowFactor+(double)
|
|
|
background*(QuantumRange-ShadowFactor)));
|
|
|
}
|
|
|
q+=GetPixelChannels(image);
|
|
|
}
|
|
|
if (SyncCacheViewAuthenticPixels(image_view,exception) == MagickFalse)
|
|
|
status=MagickFalse;
|
|
|
if (image->progress_monitor != (MagickProgressMonitor) NULL)
|
|
|
{
|
|
|
MagickBooleanType
|
|
|
proceed;
|
|
|
|
|
|
#if defined(MAGICKCORE_OPENMP_SUPPORT)
|
|
|
#pragma omp atomic
|
|
|
#endif
|
|
|
progress++;
|
|
|
proceed=SetImageProgress(image,RaiseImageTag,progress,image->rows);
|
|
|
if (proceed == MagickFalse)
|
|
|
status=MagickFalse;
|
|
|
}
|
|
|
}
|
|
|
image_view=DestroyCacheView(image_view);
|
|
|
return(status);
|
|
|
}
|