caption.c revision b712c6e549e8dbd76a125beb14182d41cc8027ee
13ed852eea50f9d4cd633efb8c2b054b8e33c253cristy/*
23ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
33ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%                                                                             %
43ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%                                                                             %
53ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%                                                                             %
63ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%               CCCC   AAA   PPPP   TTTTT  IIIII   OOO   N   N                %
73ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%              C      A   A  P   P    T      I    O   O  NN  N                %
83ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%              C      AAAAA  PPPP     T      I    O   O  N N N                %
93ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%              C      A   A  P        T      I    O   O  N  NN                %
103ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%               CCCC  A   A  P        T    IIIII   OOO   N   N                %
113ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%                                                                             %
123ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%                                                                             %
133ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%                             Read Text Caption.                              %
143ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%                                                                             %
153ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%                              Software Design                                %
163ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%                                John Cristy                                  %
173ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%                               February 2002                                 %
183ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%                                                                             %
193ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%                                                                             %
2045ef08fd6a09813e4a8f5ddadf85ba9e0ec2cdc7cristy%  Copyright 1999-2013 ImageMagick Studio LLC, a non-profit organization      %
213ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%  dedicated to making software imaging solutions freely available.           %
223ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%                                                                             %
233ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%  You may not use this file except in compliance with the License.  You may  %
243ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%  obtain a copy of the License at                                            %
253ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%                                                                             %
263ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%    http://www.imagemagick.org/script/license.php                            %
273ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%                                                                             %
283ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%  Unless required by applicable law or agreed to in writing, software        %
293ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%  distributed under the License is distributed on an "AS IS" BASIS,          %
303ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.   %
313ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%  See the License for the specific language governing permissions and        %
323ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%  limitations under the License.                                             %
333ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%                                                                             %
343ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
353ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%
363ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%
373ed852eea50f9d4cd633efb8c2b054b8e33c253cristy*/
383ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
393ed852eea50f9d4cd633efb8c2b054b8e33c253cristy/*
403ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  Include declarations.
413ed852eea50f9d4cd633efb8c2b054b8e33c253cristy*/
424c08aed51c5899665ade97263692328eea4af106cristy#include "MagickCore/studio.h"
434c08aed51c5899665ade97263692328eea4af106cristy#include "MagickCore/annotate.h"
4476ce6e193e5a305875173a744bbd59d27ddb3148cristy#include "MagickCore/artifact.h"
454c08aed51c5899665ade97263692328eea4af106cristy#include "MagickCore/blob.h"
464c08aed51c5899665ade97263692328eea4af106cristy#include "MagickCore/blob-private.h"
478a3ce7f37eeb9deabe9134cb75cd69e7dae75301cristy#include "MagickCore/composite-private.h"
484c08aed51c5899665ade97263692328eea4af106cristy#include "MagickCore/draw.h"
498a3ce7f37eeb9deabe9134cb75cd69e7dae75301cristy#include "MagickCore/draw-private.h"
504c08aed51c5899665ade97263692328eea4af106cristy#include "MagickCore/exception.h"
514c08aed51c5899665ade97263692328eea4af106cristy#include "MagickCore/exception-private.h"
524c08aed51c5899665ade97263692328eea4af106cristy#include "MagickCore/image.h"
534c08aed51c5899665ade97263692328eea4af106cristy#include "MagickCore/image-private.h"
544c08aed51c5899665ade97263692328eea4af106cristy#include "MagickCore/list.h"
554c08aed51c5899665ade97263692328eea4af106cristy#include "MagickCore/magick.h"
564c08aed51c5899665ade97263692328eea4af106cristy#include "MagickCore/memory_.h"
578a3ce7f37eeb9deabe9134cb75cd69e7dae75301cristy#include "MagickCore/module.h"
584c08aed51c5899665ade97263692328eea4af106cristy#include "MagickCore/option.h"
594c08aed51c5899665ade97263692328eea4af106cristy#include "MagickCore/property.h"
604c08aed51c5899665ade97263692328eea4af106cristy#include "MagickCore/quantum-private.h"
614c08aed51c5899665ade97263692328eea4af106cristy#include "MagickCore/static.h"
624c08aed51c5899665ade97263692328eea4af106cristy#include "MagickCore/string_.h"
638a3ce7f37eeb9deabe9134cb75cd69e7dae75301cristy#include "MagickCore/string-private.h"
648a3ce7f37eeb9deabe9134cb75cd69e7dae75301cristy#include "MagickCore/utility.h"
653ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
663ed852eea50f9d4cd633efb8c2b054b8e33c253cristy/*
673ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
683ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%                                                                             %
693ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%                                                                             %
703ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%                                                                             %
713ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%   R e a d C A P T I O N I m a g e                                           %
723ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%                                                                             %
733ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%                                                                             %
743ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%                                                                             %
753ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
763ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%
773ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%  ReadCAPTIONImage() reads a CAPTION image file and returns it.  It
783ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%  allocates the memory necessary for the new Image structure and returns a
793ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%  pointer to the new image.
803ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%
813ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%  The format of the ReadCAPTIONImage method is:
823ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%
833ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%      Image *ReadCAPTIONImage(const ImageInfo *image_info,
843ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%        ExceptionInfo *exception)
853ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%
863ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%  A description of each parameter follows:
873ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%
883ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%    o image_info: the image info.
893ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%
903ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%    o exception: return any errors or warnings in this structure.
913ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%
923ed852eea50f9d4cd633efb8c2b054b8e33c253cristy*/
933ed852eea50f9d4cd633efb8c2b054b8e33c253cristystatic Image *ReadCAPTIONImage(const ImageInfo *image_info,
943ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  ExceptionInfo *exception)
953ed852eea50f9d4cd633efb8c2b054b8e33c253cristy{
963ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  char
973ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    *caption,
983ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    geometry[MaxTextExtent],
9954ec42737fdec7527afa06ca95be82c8ca0bd866cristy    *property,
10054ec42737fdec7527afa06ca95be82c8ca0bd866cristy    *text;
1013ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
1023ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  const char
103ab272ac4f115daf25c032de9dbb49a399eebe49bcristy    *gravity,
104ab272ac4f115daf25c032de9dbb49a399eebe49bcristy    *option;
1053ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
1063ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  DrawInfo
1073ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    *draw_info;
1083ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
1093ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  Image
1103ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    *image;
1113ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
1123ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  MagickBooleanType
1133ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    status;
1143ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
115bb50337b2a8a16ca7e903cc04ab195ff0fd47ae6cristy  register ssize_t
1163ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    i;
1173ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
118bb50337b2a8a16ca7e903cc04ab195ff0fd47ae6cristy  size_t
1193ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    height,
1203ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    width;
1213ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
1224e82e51d7ebce7b4ef0f808d906124dd6f812248cristy  TypeMetric
1234e82e51d7ebce7b4ef0f808d906124dd6f812248cristy    metrics;
1244e82e51d7ebce7b4ef0f808d906124dd6f812248cristy
1253ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  /*
1263ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    Initialize Image structure.
1273ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  */
1283ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  assert(image_info != (const ImageInfo *) NULL);
1293ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  assert(image_info->signature == MagickSignature);
1303ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  if (image_info->debug != MagickFalse)
1313ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",
1323ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      image_info->filename);
1333ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  assert(exception != (ExceptionInfo *) NULL);
1343ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  assert(exception->signature == MagickSignature);
1359950d57e1124b73f684fb5946e206994cefda628cristy  image=AcquireImage(image_info,exception);
1363ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  (void) ResetImagePage(image,"0x0+0+0");
1373ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  /*
1383ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    Format caption.
1393ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  */
1408b206bac411969018dc3a6d395f525f1664af412cristy  option=GetImageArtifact(image,"filename");
141ab272ac4f115daf25c032de9dbb49a399eebe49bcristy  if (option == (const char *) NULL)
142ab272ac4f115daf25c032de9dbb49a399eebe49bcristy    property=InterpretImageProperties(image_info,image,image_info->filename,
143ab272ac4f115daf25c032de9dbb49a399eebe49bcristy      exception);
144ab272ac4f115daf25c032de9dbb49a399eebe49bcristy  else
145ab272ac4f115daf25c032de9dbb49a399eebe49bcristy    if (LocaleNCompare(option,"caption:",8) == 0)
146ab272ac4f115daf25c032de9dbb49a399eebe49bcristy      property=InterpretImageProperties(image_info,image,option+8,exception);
147ab272ac4f115daf25c032de9dbb49a399eebe49bcristy    else
148ab272ac4f115daf25c032de9dbb49a399eebe49bcristy      property=InterpretImageProperties(image_info,image,option,exception);
149d15e65928aec551b7388c2863de3e3e628e2e0ddcristy  (void) SetImageProperty(image,"caption",property,exception);
1503ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  property=DestroyString(property);
151d15e65928aec551b7388c2863de3e3e628e2e0ddcristy  caption=ConstantString(GetImageProperty(image,"caption",exception));
1523ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  draw_info=CloneDrawInfo(image_info,(DrawInfo *) NULL);
1536fc392931fb03ddff4853716af6d51e329f59696cristy  (void) CloneString(&draw_info->text,caption);
1548b206bac411969018dc3a6d395f525f1664af412cristy  gravity=GetImageArtifact(image,"gravity");
1553ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  if (gravity != (char *) NULL)
156042ee78fa9004bf1ac6a95f09d9d1faca631dda1cristy    draw_info->gravity=(GravityType) ParseCommandOption(MagickGravityOptions,
1573ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      MagickFalse,gravity);
1588db9ca45d3b9861f5b18cdc760c8e8f0f157b270cristy  if (image->columns == 0)
1598db9ca45d3b9861f5b18cdc760c8e8f0f157b270cristy    {
1608db9ca45d3b9861f5b18cdc760c8e8f0f157b270cristy      for ( ; ; draw_info->pointsize*=2.0)
1618db9ca45d3b9861f5b18cdc760c8e8f0f157b270cristy      {
16254ec42737fdec7527afa06ca95be82c8ca0bd866cristy        text=AcquireString(caption);
1639f92e3cee3ca2d153ccb77ee02fd27eed563021ecristy        i=FormatMagickCaption(image,draw_info,MagickFalse,&metrics,&text,
16454ec42737fdec7527afa06ca95be82c8ca0bd866cristy          exception);
16554ec42737fdec7527afa06ca95be82c8ca0bd866cristy        (void) CloneString(&draw_info->text,text);
16654ec42737fdec7527afa06ca95be82c8ca0bd866cristy        text=DestroyString(text);
1678db9ca45d3b9861f5b18cdc760c8e8f0f157b270cristy        (void) FormatLocaleString(geometry,MaxTextExtent,"%+g%+g",
1688db9ca45d3b9861f5b18cdc760c8e8f0f157b270cristy          -metrics.bounds.x1,metrics.ascent);
1698db9ca45d3b9861f5b18cdc760c8e8f0f157b270cristy        if (draw_info->gravity == UndefinedGravity)
1708db9ca45d3b9861f5b18cdc760c8e8f0f157b270cristy          (void) CloneString(&draw_info->geometry,geometry);
1718db9ca45d3b9861f5b18cdc760c8e8f0f157b270cristy        status=GetMultilineTypeMetrics(image,draw_info,&metrics,exception);
1728db9ca45d3b9861f5b18cdc760c8e8f0f157b270cristy        height=(size_t) floor(metrics.height+draw_info->stroke_width+0.5);
173a492593efccb08b72392d64966b5c7728e56f16acristy        if ((height >= image->rows) || (image_info->pointsize != 0.0))
1748db9ca45d3b9861f5b18cdc760c8e8f0f157b270cristy          break;
1758db9ca45d3b9861f5b18cdc760c8e8f0f157b270cristy      }
176a492593efccb08b72392d64966b5c7728e56f16acristy      draw_info->pointsize/=2.0;
177b712c6e549e8dbd76a125beb14182d41cc8027eecristy      status=GetMultilineTypeMetrics(image,draw_info,&metrics,exception);
178a492593efccb08b72392d64966b5c7728e56f16acristy      width=(size_t) floor(metrics.width+draw_info->stroke_width+0.5);
1798db9ca45d3b9861f5b18cdc760c8e8f0f157b270cristy      image->columns=width;
1808db9ca45d3b9861f5b18cdc760c8e8f0f157b270cristy    }
1818db9ca45d3b9861f5b18cdc760c8e8f0f157b270cristy  if (image->rows == 0)
1828db9ca45d3b9861f5b18cdc760c8e8f0f157b270cristy    {
1838db9ca45d3b9861f5b18cdc760c8e8f0f157b270cristy      for ( ; ; draw_info->pointsize*=2.0)
1848db9ca45d3b9861f5b18cdc760c8e8f0f157b270cristy      {
18554ec42737fdec7527afa06ca95be82c8ca0bd866cristy        text=AcquireString(caption);
1869f92e3cee3ca2d153ccb77ee02fd27eed563021ecristy        i=FormatMagickCaption(image,draw_info,MagickFalse,&metrics,&text,
18754ec42737fdec7527afa06ca95be82c8ca0bd866cristy          exception);
18854ec42737fdec7527afa06ca95be82c8ca0bd866cristy        (void) CloneString(&draw_info->text,text);
18954ec42737fdec7527afa06ca95be82c8ca0bd866cristy        text=DestroyString(text);
1908db9ca45d3b9861f5b18cdc760c8e8f0f157b270cristy        (void) FormatLocaleString(geometry,MaxTextExtent,"%+g%+g",
1918db9ca45d3b9861f5b18cdc760c8e8f0f157b270cristy          -metrics.bounds.x1,metrics.ascent);
1928db9ca45d3b9861f5b18cdc760c8e8f0f157b270cristy        if (draw_info->gravity == UndefinedGravity)
1938db9ca45d3b9861f5b18cdc760c8e8f0f157b270cristy          (void) CloneString(&draw_info->geometry,geometry);
1948db9ca45d3b9861f5b18cdc760c8e8f0f157b270cristy        status=GetMultilineTypeMetrics(image,draw_info,&metrics,exception);
1958db9ca45d3b9861f5b18cdc760c8e8f0f157b270cristy        width=(size_t) floor(metrics.width+draw_info->stroke_width+0.5);
1968db9ca45d3b9861f5b18cdc760c8e8f0f157b270cristy        height=(size_t) floor(metrics.height+draw_info->stroke_width+0.5);
19754ec42737fdec7527afa06ca95be82c8ca0bd866cristy        if ((width >= image->columns) || (image_info->pointsize != 0.0))
1988db9ca45d3b9861f5b18cdc760c8e8f0f157b270cristy          break;
1998db9ca45d3b9861f5b18cdc760c8e8f0f157b270cristy      }
200a492593efccb08b72392d64966b5c7728e56f16acristy      draw_info->pointsize/=2.0;
201a492593efccb08b72392d64966b5c7728e56f16acristy      status=GetMultilineTypeMetrics(image,draw_info,&metrics,exception);
20254ec42737fdec7527afa06ca95be82c8ca0bd866cristy      image->rows=(size_t) ((i+1)*(metrics.ascent-metrics.descent+
20354ec42737fdec7527afa06ca95be82c8ca0bd866cristy        draw_info->interline_spacing+draw_info->stroke_width)+0.5);
2048db9ca45d3b9861f5b18cdc760c8e8f0f157b270cristy    }
205a492593efccb08b72392d64966b5c7728e56f16acristy  if (fabs(image_info->pointsize) < MagickEpsilon)
2063ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    {
207bdf24b20c5b02c773580a7b8cbf4ae8bb11ef994cristy      double
208bdf24b20c5b02c773580a7b8cbf4ae8bb11ef994cristy        high,
209bdf24b20c5b02c773580a7b8cbf4ae8bb11ef994cristy        low;
210bdf24b20c5b02c773580a7b8cbf4ae8bb11ef994cristy
2113ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      /*
212bdf24b20c5b02c773580a7b8cbf4ae8bb11ef994cristy        Auto fit text into bounding box.
2133ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      */
2148592b059b2b4f03c0280b0e1146b225207e624f8cristy      for ( ; ; draw_info->pointsize*=2.0)
2153ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      {
2163ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        text=AcquireString(caption);
2179f92e3cee3ca2d153ccb77ee02fd27eed563021ecristy        i=FormatMagickCaption(image,draw_info,MagickFalse,&metrics,&text,
2185cbc016effaa2d7ee617f46ca0a2371533d4ae17cristy          exception);
2193ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        (void) CloneString(&draw_info->text,text);
2203ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        text=DestroyString(text);
221b51dff5c0d16a4c1b69ff683e786cb3b4c467694cristy        (void) FormatLocaleString(geometry,MaxTextExtent,"%+g%+g",
2223ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          -metrics.bounds.x1,metrics.ascent);
2233ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        if (draw_info->gravity == UndefinedGravity)
2243ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          (void) CloneString(&draw_info->geometry,geometry);
2255cbc016effaa2d7ee617f46ca0a2371533d4ae17cristy        status=GetMultilineTypeMetrics(image,draw_info,&metrics,exception);
226bb50337b2a8a16ca7e903cc04ab195ff0fd47ae6cristy        width=(size_t) floor(metrics.width+draw_info->stroke_width+0.5);
2274e82e51d7ebce7b4ef0f808d906124dd6f812248cristy        height=(size_t) floor(metrics.height+draw_info->stroke_width+0.5);
22854ec42737fdec7527afa06ca95be82c8ca0bd866cristy        if ((width >= image->columns) && (height >= image->rows))
2293ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          break;
23054ec42737fdec7527afa06ca95be82c8ca0bd866cristy        if ((width >= (image->columns << 1)) || (height >= (image->rows << 1)))
2318b235b2d0ea1bce8f9743d2d25bd6ddc9f72ff1dcristy          break;
2323ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      }
233bdf24b20c5b02c773580a7b8cbf4ae8bb11ef994cristy      high=draw_info->pointsize/2.0;
2348592b059b2b4f03c0280b0e1146b225207e624f8cristy      for (low=high/2.0; (high-low) > 1.0; )
2353ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      {
236bdf24b20c5b02c773580a7b8cbf4ae8bb11ef994cristy        draw_info->pointsize=(low+high)/2.0;
2373ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        text=AcquireString(caption);
2389f92e3cee3ca2d153ccb77ee02fd27eed563021ecristy        i=FormatMagickCaption(image,draw_info,MagickFalse,&metrics,&text,
2395cbc016effaa2d7ee617f46ca0a2371533d4ae17cristy          exception);
2403ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        (void) CloneString(&draw_info->text,text);
2413ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        text=DestroyString(text);
242b51dff5c0d16a4c1b69ff683e786cb3b4c467694cristy        (void) FormatLocaleString(geometry,MaxTextExtent,"%+g%+g",
2433ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          -metrics.bounds.x1,metrics.ascent);
2443ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        if (draw_info->gravity == UndefinedGravity)
2453ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          (void) CloneString(&draw_info->geometry,geometry);
2465cbc016effaa2d7ee617f46ca0a2371533d4ae17cristy        status=GetMultilineTypeMetrics(image,draw_info,&metrics,exception);
247bb50337b2a8a16ca7e903cc04ab195ff0fd47ae6cristy        width=(size_t) floor(metrics.width+draw_info->stroke_width+0.5);
2484e82e51d7ebce7b4ef0f808d906124dd6f812248cristy        height=(size_t) floor(metrics.height+draw_info->stroke_width+0.5);
24942f5a6a8af8b1e4fd5f341e709c4d06778b8d85fcristy        if ((width <= image->columns) && (height <= image->rows))
250bdf24b20c5b02c773580a7b8cbf4ae8bb11ef994cristy          low=draw_info->pointsize+1.0;
251bdf24b20c5b02c773580a7b8cbf4ae8bb11ef994cristy        else
252bdf24b20c5b02c773580a7b8cbf4ae8bb11ef994cristy          high=draw_info->pointsize-1.0;
2533ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      }
2546cd29479f50f920eb9e65e97ba682037204f7708cristy      for (draw_info->pointsize=(low+high)/2.0; (high-low) > 1.0; )
25517386ff059907b275aeb762297179b2d26d95a33cristy      {
25617386ff059907b275aeb762297179b2d26d95a33cristy        text=AcquireString(caption);
2579f92e3cee3ca2d153ccb77ee02fd27eed563021ecristy        i=FormatMagickCaption(image,draw_info,MagickFalse,&metrics,&text,
25817386ff059907b275aeb762297179b2d26d95a33cristy          exception);
25917386ff059907b275aeb762297179b2d26d95a33cristy        (void) CloneString(&draw_info->text,text);
26017386ff059907b275aeb762297179b2d26d95a33cristy        text=DestroyString(text);
26117386ff059907b275aeb762297179b2d26d95a33cristy        (void) FormatLocaleString(geometry,MaxTextExtent,"%+g%+g",
26217386ff059907b275aeb762297179b2d26d95a33cristy          -metrics.bounds.x1,metrics.ascent);
26317386ff059907b275aeb762297179b2d26d95a33cristy        if (draw_info->gravity == UndefinedGravity)
26417386ff059907b275aeb762297179b2d26d95a33cristy          (void) CloneString(&draw_info->geometry,geometry);
26517386ff059907b275aeb762297179b2d26d95a33cristy        status=GetMultilineTypeMetrics(image,draw_info,&metrics,exception);
26617386ff059907b275aeb762297179b2d26d95a33cristy        width=(size_t) floor(metrics.width+draw_info->stroke_width+0.5);
26717386ff059907b275aeb762297179b2d26d95a33cristy        height=(size_t) floor(metrics.height+draw_info->stroke_width+0.5);
26817386ff059907b275aeb762297179b2d26d95a33cristy        if ((width <= image->columns) && (height <= image->rows))
26917386ff059907b275aeb762297179b2d26d95a33cristy          break;
2706cd29479f50f920eb9e65e97ba682037204f7708cristy        draw_info->pointsize--;
27117386ff059907b275aeb762297179b2d26d95a33cristy      }
272ec0bf4bde1f4ae360eaad31b98fb9ffe06d3b35dcristy      draw_info->pointsize--;
2733ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    }
274a492593efccb08b72392d64966b5c7728e56f16acristy  (void) CloneString(&draw_info->text,caption);
275a492593efccb08b72392d64966b5c7728e56f16acristy  i=FormatMagickCaption(image,draw_info,MagickFalse,&metrics,&caption,
276a492593efccb08b72392d64966b5c7728e56f16acristy    exception);
277ea1a8aa04a9fe1500104284407c1cc06d20da699cristy  if (SetImageBackgroundColor(image,exception) == MagickFalse)
27895524f92fc346f548f202d36ffc6a17fdbd1b1cbcristy    {
27995524f92fc346f548f202d36ffc6a17fdbd1b1cbcristy      image=DestroyImageList(image);
28095524f92fc346f548f202d36ffc6a17fdbd1b1cbcristy      return((Image *) NULL);
28195524f92fc346f548f202d36ffc6a17fdbd1b1cbcristy    }
2823ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  /*
2833ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    Draw caption.
2843ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  */
2853ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  (void) CloneString(&draw_info->text,caption);
2865cbc016effaa2d7ee617f46ca0a2371533d4ae17cristy  status=GetMultilineTypeMetrics(image,draw_info,&metrics,exception);
287024843f38984cd26602f0b3b28a0768dfa056bb5cristy  if ((draw_info->gravity != UndefinedGravity) &&
288024843f38984cd26602f0b3b28a0768dfa056bb5cristy      (draw_info->direction != RightToLeftDirection))
289bb50337b2a8a16ca7e903cc04ab195ff0fd47ae6cristy    image->page.x=(ssize_t) (metrics.bounds.x1-draw_info->stroke_width/2.0);
2903ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  else
2913ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    {
292b51dff5c0d16a4c1b69ff683e786cb3b4c467694cristy      (void) FormatLocaleString(geometry,MaxTextExtent,"%+g%+g",
2933ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        -metrics.bounds.x1+draw_info->stroke_width/2.0,metrics.ascent+
2943ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        draw_info->stroke_width/2.0);
295024843f38984cd26602f0b3b28a0768dfa056bb5cristy      if (draw_info->direction == RightToLeftDirection)
296024843f38984cd26602f0b3b28a0768dfa056bb5cristy        (void) FormatLocaleString(geometry,MaxTextExtent,"%+g%+g",
297024843f38984cd26602f0b3b28a0768dfa056bb5cristy          image->columns-(metrics.bounds.x2+draw_info->stroke_width/2.0),
298024843f38984cd26602f0b3b28a0768dfa056bb5cristy          metrics.ascent+draw_info->stroke_width/2.0);
299024843f38984cd26602f0b3b28a0768dfa056bb5cristy      draw_info->geometry=AcquireString(geometry);
3003ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    }
301ab272ac4f115daf25c032de9dbb49a399eebe49bcristy  status=AnnotateImage(image,draw_info,exception);
3023ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  draw_info=DestroyDrawInfo(draw_info);
3033ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  caption=DestroyString(caption);
304ab272ac4f115daf25c032de9dbb49a399eebe49bcristy  if (status == MagickFalse)
305ab272ac4f115daf25c032de9dbb49a399eebe49bcristy    {
306ab272ac4f115daf25c032de9dbb49a399eebe49bcristy      image=DestroyImageList(image);
307ab272ac4f115daf25c032de9dbb49a399eebe49bcristy      return((Image *) NULL);
308ab272ac4f115daf25c032de9dbb49a399eebe49bcristy    }
3093ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  return(GetFirstImageInList(image));
3103ed852eea50f9d4cd633efb8c2b054b8e33c253cristy}
3113ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
3123ed852eea50f9d4cd633efb8c2b054b8e33c253cristy/*
3133ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3143ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%                                                                             %
3153ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%                                                                             %
3163ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%                                                                             %
3173ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%   R e g i s t e r C A P T I O N I m a g e                                   %
3183ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%                                                                             %
3193ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%                                                                             %
3203ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%                                                                             %
3213ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3223ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%
3233ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%  RegisterCAPTIONImage() adds attributes for the CAPTION image format to
3243ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%  the list of supported formats.  The attributes include the image format
3253ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%  tag, a method to read and/or write the format, whether the format
3263ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%  supports the saving of more than one frame to the same file or blob,
3273ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%  whether the format supports native in-memory I/O, and a brief
3283ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%  description of the format.
3293ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%
3303ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%  The format of the RegisterCAPTIONImage method is:
3313ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%
332bb50337b2a8a16ca7e903cc04ab195ff0fd47ae6cristy%      size_t RegisterCAPTIONImage(void)
3333ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%
3343ed852eea50f9d4cd633efb8c2b054b8e33c253cristy*/
335bb50337b2a8a16ca7e903cc04ab195ff0fd47ae6cristyModuleExport size_t RegisterCAPTIONImage(void)
3363ed852eea50f9d4cd633efb8c2b054b8e33c253cristy{
3373ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  MagickInfo
3383ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    *entry;
3393ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
3403ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  entry=SetMagickInfo("CAPTION");
3413ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  entry->decoder=(DecodeImageHandler *) ReadCAPTIONImage;
3428a3ce7f37eeb9deabe9134cb75cd69e7dae75301cristy  entry->description=ConstantString("Caption");
3433ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  entry->adjoin=MagickFalse;
3443ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  entry->module=ConstantString("CAPTION");
3453ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  (void) RegisterMagickInfo(entry);
3463ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  return(MagickImageCoderSignature);
3473ed852eea50f9d4cd633efb8c2b054b8e33c253cristy}
3483ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
3493ed852eea50f9d4cd633efb8c2b054b8e33c253cristy/*
3503ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3513ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%                                                                             %
3523ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%                                                                             %
3533ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%                                                                             %
3543ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%   U n r e g i s t e r C A P T I O N I m a g e                               %
3553ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%                                                                             %
3563ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%                                                                             %
3573ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%                                                                             %
3583ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3593ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%
3603ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%  UnregisterCAPTIONImage() removes format registrations made by the
3613ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%  CAPTION module from the list of supported formats.
3623ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%
3633ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%  The format of the UnregisterCAPTIONImage method is:
3643ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%
3653ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%      UnregisterCAPTIONImage(void)
3663ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%
3673ed852eea50f9d4cd633efb8c2b054b8e33c253cristy*/
3683ed852eea50f9d4cd633efb8c2b054b8e33c253cristyModuleExport void UnregisterCAPTIONImage(void)
3693ed852eea50f9d4cd633efb8c2b054b8e33c253cristy{
3703ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  (void) UnregisterMagickInfo("CAPTION");
3713ed852eea50f9d4cd633efb8c2b054b8e33c253cristy}
372