/* %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % % % % % % % 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); }