You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

476 lines
19 KiB

This file contains invisible Unicode characters!

This file contains invisible Unicode characters that may be processed differently from what appears below. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to reveal hidden characters.

/*
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% %
% %
% %
% AAA RRRR TTTTT IIIII FFFFF AAA CCCC TTTTT %
% A A R R T I F A A C T %
% AAAAA RRRRR T I FFF AAAAA C T %
% A A R R T I F A A C T %
% A A R R T IIIII F A A CCCCC T %
% %
% %
% MagickCore Artifact Methods %
% %
% Software Design %
% Cristy %
% March 2000 %
% %
% %
% 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/artifact.h"
#include "MagickCore/cache.h"
#include "MagickCore/color.h"
#include "MagickCore/compare.h"
#include "MagickCore/constitute.h"
#include "MagickCore/draw.h"
#include "MagickCore/effect.h"
#include "MagickCore/exception.h"
#include "MagickCore/exception-private.h"
#include "MagickCore/fx.h"
#include "MagickCore/fx-private.h"
#include "MagickCore/gem.h"
#include "MagickCore/geometry.h"
#include "MagickCore/image.h"
#include "MagickCore/layer.h"
#include "MagickCore/list.h"
#include "MagickCore/memory_.h"
#include "MagickCore/monitor.h"
#include "MagickCore/montage.h"
#include "MagickCore/option.h"
#include "MagickCore/profile.h"
#include "MagickCore/quantum.h"
#include "MagickCore/resource_.h"
#include "MagickCore/splay-tree.h"
#include "MagickCore/signature-private.h"
#include "MagickCore/statistic.h"
#include "MagickCore/string_.h"
#include "MagickCore/token.h"
#include "MagickCore/utility.h"
#include "MagickCore/xml-tree.h"
/*
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% %
% %
% %
% C l o n e I m a g e A r t i f a c t s %
% %
% %
% %
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%
% CloneImageArtifacts() clones all image artifacts to another image.
%
% This will not delete any existing artifacts that may be present!
%
% The format of the CloneImageArtifacts method is:
%
% MagickBooleanType CloneImageArtifacts(Image *image,
% const Image *clone_image)
%
% A description of each parameter follows:
%
% o image: the image, to recieve the cloned artifacts.
%
% o clone_image: the source image for artifacts to clone.
%
*/
MagickExport MagickBooleanType CloneImageArtifacts(Image *image,
const Image *clone_image)
{
assert(image != (Image *) NULL);
assert(image->signature == MagickCoreSignature);
if (image->debug != MagickFalse)
(void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
assert(clone_image != (const Image *) NULL);
assert(clone_image->signature == MagickCoreSignature);
if (clone_image->debug != MagickFalse)
(void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",
clone_image->filename);
if (clone_image->artifacts != (void *) NULL)
{
if (image->artifacts != (void *) NULL)
DestroyImageArtifacts(image);
image->artifacts=CloneSplayTree((SplayTreeInfo *) clone_image->artifacts,
(void *(*)(void *)) ConstantString,(void *(*)(void *)) ConstantString);
}
return(MagickTrue);
}
/*
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% %
% %
% %
% D e f i n e I m a g e A r t i f a c t %
% %
% %
% %
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%
% DefineImageArtifact() associates an assignment string of the form
% "key=value" with per-image artifact. It is equivelent to
% SetImageArtifact().
%
% The format of the DefineImageArtifact method is:
%
% MagickBooleanType DefineImageArtifact(Image *image,
% const char *artifact)
%
% A description of each parameter follows:
%
% o image: the image.
%
% o artifact: the image artifact.
%
*/
MagickExport MagickBooleanType DefineImageArtifact(Image *image,
const char *artifact)
{
char
key[MagickPathExtent],
value[MagickPathExtent];
char
*p;
assert(image != (Image *) NULL);
assert(artifact != (const char *) NULL);
(void) CopyMagickString(key,artifact,MagickPathExtent-1);
for (p=key; *p != '\0'; p++)
if (*p == '=')
break;
*value='\0';
if (*p == '=')
(void) CopyMagickString(value,p+1,MagickPathExtent);
*p='\0';
return(SetImageArtifact(image,key,value));
}
/*
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% %
% %
% %
% D e l e t e I m a g e A r t i f a c t %
% %
% %
% %
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%
% DeleteImageArtifact() deletes an image artifact.
%
% The format of the DeleteImageArtifact method is:
%
% MagickBooleanType DeleteImageArtifact(Image *image,const char *artifact)
%
% A description of each parameter follows:
%
% o image: the image.
%
% o artifact: the image artifact.
%
*/
MagickExport MagickBooleanType DeleteImageArtifact(Image *image,
const char *artifact)
{
assert(image != (Image *) NULL);
assert(image->signature == MagickCoreSignature);
if (image->debug != MagickFalse)
(void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
if (image->artifacts == (void *) NULL)
return(MagickFalse);
return(DeleteNodeFromSplayTree((SplayTreeInfo *) image->artifacts,artifact));
}
/*
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% %
% %
% %
% D e s t r o y I m a g e A r t i f a c t s %
% %
% %
% %
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%
% DestroyImageArtifacts() destroys all artifacts and associated memory
% attached to the given image.
%
% The format of the DestroyImageArtifacts method is:
%
% void DestroyImageArtifacts(Image *image)
%
% A description of each parameter follows:
%
% o image: the image.
%
*/
MagickExport void DestroyImageArtifacts(Image *image)
{
assert(image != (Image *) NULL);
assert(image->signature == MagickCoreSignature);
if (image->debug != MagickFalse)
(void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
if (image->artifacts != (void *) NULL)
image->artifacts=(void *) DestroySplayTree((SplayTreeInfo *)
image->artifacts);
}
/*
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% %
% %
% %
% G e t I m a g e A r t i f a c t %
% %
% %
% %
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%
% GetImageArtifact() gets a value associated with an image artifact.
% If the requested artifact is NULL return the first artifact, to
% prepare to iterate over all artifacts.
%
% The returned string is a constant string in the tree and should NOT be
% freed by the caller.
%
% The format of the GetImageArtifact method is:
%
% const char *GetImageArtifact(const Image *image,const char *key)
%
% A description of each parameter follows:
%
% o image: the image.
%
% o key: the key.
%
*/
MagickExport const char *GetImageArtifact(const Image *image,
const char *artifact)
{
const char
*p;
assert(image != (Image *) NULL);
assert(image->signature == MagickCoreSignature);
if (image->debug != MagickFalse)
(void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
p=(const char *) NULL;
if (image->artifacts != (void *) NULL)
{
if (artifact == (const char *) NULL)
return((const char *) GetRootValueFromSplayTree((SplayTreeInfo *)
image->artifacts));
p=(const char *) GetValueFromSplayTree((SplayTreeInfo *) image->artifacts,
artifact);
if (p != (const char *) NULL)
return(p);
}
if ((image->image_info != (ImageInfo *) NULL) &&
(image->image_info->options != (void *) NULL))
p=(const char *) GetValueFromSplayTree((SplayTreeInfo *)
image->image_info->options,artifact);
return(p);
}
/*
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% %
% %
% %
% G e t N e x t I m a g e A r t i f a c t %
% %
% %
% %
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%
% GetNextImageArtifact() gets the next image artifact value.
%
% The format of the GetNextImageArtifact method is:
%
% char *GetNextImageArtifact(const Image *image)
%
% A description of each parameter follows:
%
% o image: the image.
%
*/
MagickExport const char *GetNextImageArtifact(const Image *image)
{
assert(image != (Image *) NULL);
assert(image->signature == MagickCoreSignature);
if (image->debug != MagickFalse)
(void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
if (image->artifacts == (void *) NULL)
return((const char *) NULL);
return((const char *) GetNextKeyInSplayTree(
(SplayTreeInfo *) image->artifacts));
}
/*
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% %
% %
% %
% R e m o v e I m a g e A r t i f a c t %
% %
% %
% %
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%
% RemoveImageArtifact() removes an artifact from the image and returns its
% value.
%
% In this case the ConstantString() value returned should be freed by the
% caller when finished.
%
% The format of the RemoveImageArtifact method is:
%
% char *RemoveImageArtifact(Image *image,const char *artifact)
%
% A description of each parameter follows:
%
% o image: the image.
%
% o artifact: the image artifact.
%
*/
MagickExport char *RemoveImageArtifact(Image *image,const char *artifact)
{
char
*value;
assert(image != (Image *) NULL);
assert(image->signature == MagickCoreSignature);
if (image->debug != MagickFalse)
(void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
if (image->artifacts == (void *) NULL)
return((char *) NULL);
value=(char *) RemoveNodeFromSplayTree((SplayTreeInfo *) image->artifacts,
artifact);
return(value);
}
/*
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% %
% %
% %
% R e s e t I m a g e A r t i f a c t I t e r a t o r %
% %
% %
% %
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%
% ResetImageArtifactIterator() resets the image artifact iterator. Use it
% in conjunction with GetNextImageArtifact() to iterate over all the values
% associated with an image artifact.
%
% Alternatively you can use GetImageArtifact() with a NULL artifact field to
% reset the iterator and return the first artifact.
%
% The format of the ResetImageArtifactIterator method is:
%
% ResetImageArtifactIterator(Image *image)
%
% A description of each parameter follows:
%
% o image: the image.
%
*/
MagickExport void ResetImageArtifactIterator(const Image *image)
{
assert(image != (Image *) NULL);
assert(image->signature == MagickCoreSignature);
if (image->debug != MagickFalse)
(void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
if (image->artifacts == (void *) NULL)
return;
ResetSplayTreeIterator((SplayTreeInfo *) image->artifacts);
}
/*
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% %
% %
% %
% S e t I m a g e A r t i f a c t %
% %
% %
% %
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%
% SetImageArtifact() sets a key-value pair in the image artifact namespace.
% Artifacts differ from properties. Properties are public and are generally
% exported to an external image format if the format supports it. Artifacts
% are private and are utilized by the internal ImageMagick API to modify the
% behavior of certain algorithms.
%
% The format of the SetImageArtifact method is:
%
% MagickBooleanType SetImageArtifact(Image *image,const char *artifact,
% const char *value)
%
% A description of each parameter follows:
%
% o image: the image.
%
% o artifact: the image artifact key.
%
% o value: the image artifact value.
%
*/
MagickExport MagickBooleanType SetImageArtifact(Image *image,
const char *artifact,const char *value)
{
MagickBooleanType
status;
assert(image != (Image *) NULL);
assert(image->signature == MagickCoreSignature);
if (image->debug != MagickFalse)
(void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
/*
Create tree if needed - specify how key,values are to be freed.
*/
if (image->artifacts == (void *) NULL)
image->artifacts=NewSplayTree(CompareSplayTreeString,RelinquishMagickMemory,
RelinquishMagickMemory);
/*
Delete artifact if NULL -- empty string values are valid!,
*/
if (value == (const char *) NULL)
return(DeleteImageArtifact(image,artifact));
/*
Add artifact to splay-tree.
*/
status=AddValueToSplayTree((SplayTreeInfo *) image->artifacts,
ConstantString(artifact),ConstantString(value));
return(status);
}