]> granicus.if.org Git - imagemagick/blob - MagickCore/geometry.c
(no commit message)
[imagemagick] / MagickCore / geometry.c
1 /*
2 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3 %                                                                             %
4 %                                                                             %
5 %                                                                             %
6 %           GGGG   EEEEE   OOO   M   M  EEEEE  TTTTT  RRRR   Y   Y            %
7 %           G      E      O   O  MM MM  E        T    R   R   Y Y             %
8 %           G  GG  EEE    O   O  M M M  EEE      T    RRRR     Y              %
9 %           G   G  E      O   O  M   M  E        T    R R      Y              %
10 %            GGGG  EEEEE   OOO   M   M  EEEEE    T    R  R     Y              %
11 %                                                                             %
12 %                                                                             %
13 %                       MagickCore Geometry Methods                           %
14 %                                                                             %
15 %                             Software Design                                 %
16 %                               John Cristy                                   %
17 %                              January 2003                                   %
18 %                                                                             %
19 %                                                                             %
20 %  Copyright 1999-2012 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 %    http://www.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 \f
39 /*
40   Include declarations.
41 */
42 #include "MagickCore/studio.h"
43 #include "MagickCore/constitute.h"
44 #include "MagickCore/draw.h"
45 #include "MagickCore/exception.h"
46 #include "MagickCore/exception-private.h"
47 #include "MagickCore/geometry.h"
48 #include "MagickCore/memory_.h"
49 #include "MagickCore/string_.h"
50 #include "MagickCore/string-private.h"
51 #include "MagickCore/token.h"
52 \f
53 /*
54 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
55 %                                                                             %
56 %                                                                             %
57 %                                                                             %
58 %   G e t G e o m e t r y                                                     %
59 %                                                                             %
60 %                                                                             %
61 %                                                                             %
62 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
63 %
64 %  GetGeometry() parses a geometry specification and returns the width,
65 %  height, x, and y values.  It also returns flags that indicates which
66 %  of the four values (width, height, x, y) were located in the string, and
67 %  whether the x or y values are negative.  In addition, there are flags to
68 %  report any meta characters (%, !, <, or >).
69 %
70 %  The format of the GetGeometry method is:
71 %
72 %      MagickStatusType GetGeometry(const char *geometry,ssize_t *x,ssize_t *y,
73 %        size_t *width,size_t *height)
74 %
75 %  A description of each parameter follows:
76 %
77 %    o geometry:  The geometry.
78 %
79 %    o x,y:  The x and y offset as determined by the geometry specification.
80 %
81 %    o width,height:  The width and height as determined by the geometry
82 %      specification.
83 %
84 */
85 MagickExport MagickStatusType GetGeometry(const char *geometry,ssize_t *x,
86   ssize_t *y,size_t *width,size_t *height)
87 {
88   char
89     *p,
90     pedantic_geometry[MaxTextExtent],
91     *q;
92
93   double
94     value;
95
96   int
97     c;
98
99   MagickStatusType
100     flags;
101
102   /*
103     Remove whitespace and meta characters from geometry specification.
104   */
105   flags=NoValue;
106   if ((geometry == (char *) NULL) || (*geometry == '\0'))
107     return(flags);
108   if (strlen(geometry) >= (MaxTextExtent-1))
109     return(flags);
110   (void) CopyMagickString(pedantic_geometry,geometry,MaxTextExtent);
111   for (p=pedantic_geometry; *p != '\0'; )
112   {
113     if (isspace((int) ((unsigned char) *p)) != 0)
114       {
115         (void) CopyMagickString(p,p+1,MaxTextExtent);
116         continue;
117       }
118     c=(int) ((unsigned int) *p);
119     switch (c)
120     {
121       case '%':
122       {
123         flags|=PercentValue;
124         (void) CopyMagickString(p,p+1,MaxTextExtent);
125         break;
126       }
127       case '!':
128       {
129         flags|=AspectValue;
130         (void) CopyMagickString(p,p+1,MaxTextExtent);
131         break;
132       }
133       case '<':
134       {
135         flags|=LessValue;
136         (void) CopyMagickString(p,p+1,MaxTextExtent);
137         break;
138       }
139       case '>':
140       {
141         flags|=GreaterValue;
142         (void) CopyMagickString(p,p+1,MaxTextExtent);
143         break;
144       }
145       case '^':
146       {
147         flags|=MinimumValue;
148         (void) CopyMagickString(p,p+1,MaxTextExtent);
149         break;
150       }
151       case '@':
152       {
153         flags|=AreaValue;
154         (void) CopyMagickString(p,p+1,MaxTextExtent);
155         break;
156       }
157       case '(':
158       case ')':
159       {
160         (void) CopyMagickString(p,p+1,MaxTextExtent);
161         break;
162       }
163       case '-':
164       case '.':
165       case ',':
166       case '+':
167       case '0':
168       case '1':
169       case '2':
170       case '3':
171       case '4':
172       case '5':
173       case '6':
174       case '7':
175       case '8':
176       case '9':
177       case 'x':
178       case 'X':
179       case 215:
180       {
181         p++;
182         break;
183       }
184       default:
185         return(flags);
186     }
187   }
188   /*
189     Parse width, height, x, and y.
190   */
191   p=pedantic_geometry;
192   if (*p == '\0')
193     return(flags);
194   q=p;
195   value=StringToDouble(p,&q);
196   (void) value;
197   if (LocaleNCompare(p,"0x",2) == 0)
198     value=(double) strtol(p,&q,10);
199   c=(int) ((unsigned char) *q);
200   if ((c == 215) || (*q == 'x') || (*q == 'X') || (*q == '\0'))
201     {
202       /*
203         Parse width.
204       */
205       q=p;
206       if (LocaleNCompare(p,"0x",2) == 0)
207         *width=(size_t) strtol(p,&p,10);
208       else
209         *width=(size_t) floor(StringToDouble(p,&p)+0.5);
210       if (p != q)
211         flags|=WidthValue;
212     }
213   c=(*p);
214   c=(int) ((unsigned char) *p);
215   if ((c == 215) || (*p == 'x') || (*p == 'X'))
216     {
217       p++;
218       if ((*p != '+') && (*p != '-'))
219         {
220           /*
221             Parse height.
222           */
223           q=p;
224           *height=(size_t) floor(StringToDouble(p,&p)+0.5);
225           if (p != q)
226             flags|=HeightValue;
227         }
228     }
229   if ((*p == '+') || (*p == '-'))
230     {
231       /*
232         Parse x value.
233       */
234       if (*p == '-')
235         flags|=XNegative;
236       q=p;
237       *x=(ssize_t) ceil(StringToDouble(p,&p)-0.5);
238       if (p != q)
239         flags|=XValue;
240       if ((*p == '+') || (*p == '-'))
241         {
242           /*
243             Parse y value.
244           */
245           if (*p == '-')
246             flags|=YNegative;
247           q=p;
248           *y=(ssize_t) ceil(StringToDouble(p,&p)-0.5);
249           if (p != q)
250             flags|=YValue;
251         }
252     }
253   return(flags);
254 }
255 \f
256 /*
257 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
258 %                                                                             %
259 %                                                                             %
260 %                                                                             %
261 %  G e t P a g e G e o m e t r y                                              %
262 %                                                                             %
263 %                                                                             %
264 %                                                                             %
265 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
266 %
267 %  GetPageGeometry() replaces any page mneumonic with the equivalent size in
268 %  picas.
269 %
270 %  The format of the GetPageGeometry method is:
271 %
272 %      char *GetPageGeometry(const char *page_geometry)
273 %
274 %  A description of each parameter follows.
275 %
276 %   o  page_geometry:  Specifies a pointer to an array of characters.  The
277 %      string is either a Postscript page name (e.g. A4) or a postscript page
278 %      geometry (e.g. 612x792+36+36).
279 %
280 */
281 MagickExport char *GetPageGeometry(const char *page_geometry)
282 {
283   static const char
284     *PageSizes[][2]=
285     {
286       { "4x6",  "288x432" },
287       { "5x7",  "360x504" },
288       { "7x9",  "504x648" },
289       { "8x10", "576x720" },
290       { "9x11",  "648x792" },
291       { "9x12",  "648x864" },
292       { "10x13",  "720x936" },
293       { "10x14",  "720x1008" },
294       { "11x17",  "792x1224" },
295       { "a0",  "2384x3370" },
296       { "a1",  "1684x2384" },
297       { "a10", "73x105" },
298       { "a2",  "1191x1684" },
299       { "a3",  "842x1191" },
300       { "a4",  "595x842" },
301       { "a4smaLL", "595x842" },
302       { "a5",  "420x595" },
303       { "a6",  "297x420" },
304       { "a7",  "210x297" },
305       { "a8",  "148x210" },
306       { "a9",  "105x148" },
307       { "archa", "648x864" },
308       { "archb", "864x1296" },
309       { "archC", "1296x1728" },
310       { "archd", "1728x2592" },
311       { "arche", "2592x3456" },
312       { "b0",  "2920x4127" },
313       { "b1",  "2064x2920" },
314       { "b10", "91x127" },
315       { "b2",  "1460x2064" },
316       { "b3",  "1032x1460" },
317       { "b4",  "729x1032" },
318       { "b5",  "516x729" },
319       { "b6",  "363x516" },
320       { "b7",  "258x363" },
321       { "b8",  "181x258" },
322       { "b9",  "127x181" },
323       { "c0",  "2599x3676" },
324       { "c1",  "1837x2599" },
325       { "c2",  "1298x1837" },
326       { "c3",  "918x1296" },
327       { "c4",  "649x918" },
328       { "c5",  "459x649" },
329       { "c6",  "323x459" },
330       { "c7",  "230x323" },
331       { "executive", "540x720" },
332       { "flsa", "612x936" },
333       { "flse", "612x936" },
334       { "folio",  "612x936" },
335       { "halfletter", "396x612" },
336       { "isob0", "2835x4008" },
337       { "isob1", "2004x2835" },
338       { "isob10", "88x125" },
339       { "isob2", "1417x2004" },
340       { "isob3", "1001x1417" },
341       { "isob4", "709x1001" },
342       { "isob5", "499x709" },
343       { "isob6", "354x499" },
344       { "isob7", "249x354" },
345       { "isob8", "176x249" },
346       { "isob9", "125x176" },
347       { "jisb0", "1030x1456" },
348       { "jisb1", "728x1030" },
349       { "jisb2", "515x728" },
350       { "jisb3", "364x515" },
351       { "jisb4", "257x364" },
352       { "jisb5", "182x257" },
353       { "jisb6", "128x182" },
354       { "ledger",  "1224x792" },
355       { "legal",  "612x1008" },
356       { "letter", "612x792" },
357       { "lettersmaLL",  "612x792" },
358       { "quarto",  "610x780" },
359       { "statement",  "396x612" },
360       { "tabloid",  "792x1224" },
361       { (char *) NULL, (char *) NULL }
362     };
363
364   char
365     *page;
366
367   register ssize_t
368     i;
369
370   assert(page_geometry != (char *) NULL);
371   (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",page_geometry);
372   page=AcquireString(page_geometry);
373   for (i=0; *PageSizes[i] != (char *) NULL; i++)
374     if (LocaleNCompare(PageSizes[i][0],page,strlen(PageSizes[i][0])) == 0)
375       {
376         RectangleInfo
377           geometry;
378
379         MagickStatusType
380           flags;
381
382         /*
383           Replace mneumonic with the equivalent size in dots-per-inch.
384         */
385         (void) CopyMagickString(page,PageSizes[i][1],MaxTextExtent);
386         (void) ConcatenateMagickString(page,page_geometry+
387           strlen(PageSizes[i][0]),MaxTextExtent);
388         flags=GetGeometry(page,&geometry.x,&geometry.y,&geometry.width,
389           &geometry.height);
390         if ((flags & GreaterValue) == 0)
391           (void) ConcatenateMagickString(page,">",MaxTextExtent);
392         break;
393       }
394   return(page);
395 }
396 \f
397 /*
398 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
399 %                                                                             %
400 %                                                                             %
401 %                                                                             %
402 %   G r a v i t y A d j u s t G e o m e t r y                                 %
403 %                                                                             %
404 %                                                                             % %                                                                             %
405 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
406 %
407 %  GravityAdjustGeometry() adjusts the offset of a region with regard to the
408 %  given: width, height and gravity; against which it is positioned.
409 %
410 %  The region should also have an appropriate width and height to correctly
411 %  set the right offset of the top left corner of the region.
412 %
413 %  The format of the GravityAdjustGeometry method is:
414 %
415 %      void GravityAdjustGeometry(const size_t width, const size_t height,
416 %        const GravityType gravity,RectangleInfo *region);
417 %
418 %  A description of each parameter follows:
419 %
420 %    o width, height:  the larger area the region is relative to
421 %
422 %    o gravity: the edge/corner the current offset is relative to
423 %
424 %    o region:  The region requiring a offset adjustment relative to gravity
425 %
426 */
427 MagickExport void GravityAdjustGeometry(const size_t width,
428   const size_t height,const GravityType gravity,RectangleInfo *region)
429 {
430   if (region->height == 0)
431     region->height=height;
432   if (region->width == 0)
433     region->width=width;
434   switch (gravity)
435   {
436     case NorthEastGravity:
437     case EastGravity:
438     case SouthEastGravity:
439     {
440       region->x=(ssize_t) (width-region->width-region->x);
441       break;
442     }
443     case NorthGravity:
444     case SouthGravity:
445     case CenterGravity:
446     case StaticGravity:
447     {
448       region->x+=(ssize_t) (width/2-region->width/2);
449       break;
450     }
451     case ForgetGravity:
452     case NorthWestGravity:
453     case WestGravity:
454     case SouthWestGravity:
455     default:
456       break;
457   }
458   switch (gravity)
459   {
460     case SouthWestGravity:
461     case SouthGravity:
462     case SouthEastGravity:
463     {
464       region->y=(ssize_t) (height-region->height-region->y);
465       break;
466     }
467     case EastGravity:
468     case WestGravity:
469     case CenterGravity:
470     case StaticGravity:
471     {
472       region->y+=(ssize_t) (height/2-region->height/2);
473       break;
474     }
475     case ForgetGravity:
476     case NorthWestGravity:
477     case NorthGravity:
478     case NorthEastGravity:
479     default:
480       break;
481   }
482   return;
483 }
484 \f
485 /*
486 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
487 %                                                                             %
488 %                                                                             %
489 %                                                                             %
490 +     I s G e o m e t r y                                                     %
491 %                                                                             %
492 %                                                                             %
493 %                                                                             %
494 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
495 %
496 %  IsGeometry() returns MagickTrue if the geometry specification is valid.
497 %  Examples are 100, 100x200, x200, 100x200+10+20, +10+20, 200%, 200x200!, etc.
498 %
499 %  The format of the IsGeometry method is:
500 %
501 %      MagickBooleanType IsGeometry(const char *geometry)
502 %
503 %  A description of each parameter follows:
504 %
505 %    o geometry: This string is the geometry specification.
506 %
507 */
508 MagickExport MagickBooleanType IsGeometry(const char *geometry)
509 {
510   GeometryInfo
511     geometry_info;
512
513   MagickStatusType
514     flags;
515
516   if (geometry == (const char *) NULL)
517     return(MagickFalse);
518   flags=ParseGeometry(geometry,&geometry_info);
519   if (flags == NoValue)
520     flags=ParseGeometry(geometry+1,&geometry_info);  /* i.e. +-4+-4 */
521   return(flags != NoValue ? MagickTrue : MagickFalse);
522 }
523 \f
524 /*
525 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
526 %                                                                             %
527 %                                                                             %
528 %                                                                             %
529 +     I s S c e n e G e o m e t r y                                           %
530 %                                                                             %
531 %                                                                             %
532 %                                                                             %
533 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
534 %
535 %  IsSceneGeometry() returns MagickTrue if the geometry is a valid scene
536 %  specification (e.g. [1], [1-9], [1,7,4]).
537 %
538 %  The format of the IsSceneGeometry method is:
539 %
540 %      MagickBooleanType IsSceneGeometry(const char *geometry,
541 %        const MagickBooleanType pedantic)
542 %
543 %  A description of each parameter follows:
544 %
545 %    o geometry: This string is the geometry specification.
546 %
547 %    o pedantic: A value other than 0 invokes a more restrictive set of
548 %      conditions for a valid specification (e.g. [1], [1-4], [4-1]).
549 %
550 */
551 MagickExport MagickBooleanType IsSceneGeometry(const char *geometry,
552   const MagickBooleanType pedantic)
553 {
554   char
555     *p;
556
557   double
558     value;
559
560   if (geometry == (const char *) NULL)
561     return(MagickFalse);
562   p=(char *) geometry;
563   value=StringToDouble(geometry,&p);
564   (void) value;
565   if (p == geometry)
566     return(MagickFalse);
567   if (strspn(geometry,"0123456789-, ") != strlen(geometry))
568     return(MagickFalse);
569   if ((pedantic != MagickFalse) && (strchr(geometry,',') != (char *) NULL))
570     return(MagickFalse);
571   return(MagickTrue);
572 }
573 \f
574 /*
575 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
576 %                                                                             %
577 %                                                                             %
578 %                                                                             %
579 %   P a r s e A b s o l u t e G e o m e t r y                                 %
580 %                                                                             %
581 %                                                                             %
582 %                                                                             %
583 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
584 %
585 %  ParseAbsoluteGeometry() returns a region as defined by the geometry string,
586 %  without any modification by percentages or gravity.
587 %
588 %  It currently just a wrapper around GetGeometry(), but may be expanded in
589 %  the future to handle other positioning information.
590 %
591 %  The format of the ParseAbsoluteGeometry method is:
592 %
593 %      MagickStatusType ParseAbsoluteGeometry(const char *geometry,
594 %        RectangleInfo *region_info)
595 %
596 %  A description of each parameter follows:
597 %
598 %    o geometry:  The geometry string (e.g. "100x100+10+10").
599 %
600 %    o region_info: the region as defined by the geometry string.
601 %
602 */
603 MagickExport MagickStatusType ParseAbsoluteGeometry(const char *geometry,
604   RectangleInfo *region_info)
605 {
606   MagickStatusType
607     flags;
608
609   flags=GetGeometry(geometry,&region_info->x,&region_info->y,
610     &region_info->width,&region_info->height);
611   return(flags);
612 }
613 \f
614 /*
615 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
616 %                                                                             %
617 %                                                                             %
618 %                                                                             %
619 %   P a r s e A f f i n e G e o m e t r y                                     %
620 %                                                                             %
621 %                                                                             %
622 %                                                                             %
623 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
624 %
625 %  ParseAffineGeometry() returns an affine matrix as defined by a string of 4
626 %  to 6 comma/space separated floating point values.
627 %
628 %  The affine matrix determinant is checked for validity of the values.
629 %
630 %  The format of the ParseAffineGeometry method is:
631 %
632 %      MagickStatusType ParseAffineGeometry(const char *geometry,
633 %        AffineMatrix *affine_matrix,ExceptionInfo *exception)
634 %
635 %  A description of each parameter follows:
636 %
637 %    o geometry:  The geometry string (e.g. "1.0,0.0,0.0,1.0,3.2,1.2").
638 %
639 %    o affine_matrix: the affine matrix as defined by the geometry string.
640 %
641 %    o exception: return any errors or warnings in this structure.
642 %
643 */
644 MagickExport MagickStatusType ParseAffineGeometry(const char *geometry,
645   AffineMatrix *affine_matrix,ExceptionInfo *exception)
646 {
647   char
648     token[MaxTextExtent];
649
650   const char
651     *p;
652
653   double
654     determinant;
655
656   MagickStatusType
657     flags;
658
659   register ssize_t
660     i;
661
662   GetAffineMatrix(affine_matrix);
663   flags=NoValue;
664   p=(char *) geometry;
665   for (i=0; (*p != '\0') && (i < 6); i++)
666   {
667     GetMagickToken(p,&p,token);
668     if (*token == ',')
669       GetMagickToken(p,&p,token);
670     switch (i)
671     {
672       case 0:
673       {
674         affine_matrix->sx=StringToDouble(token,(char **) NULL);
675         break;
676       }
677       case 1:
678       {
679         affine_matrix->rx=StringToDouble(token,(char **) NULL);
680         break;
681       }
682       case 2:
683       {
684         affine_matrix->ry=StringToDouble(token,(char **) NULL);
685         break;
686       }
687       case 3:
688       {
689         affine_matrix->sy=StringToDouble(token,(char **) NULL);
690         break;
691       }
692       case 4:
693       {
694         affine_matrix->tx=StringToDouble(token,(char **) NULL);
695         flags|=XValue;
696         break;
697       }
698       case 5:
699       {
700         affine_matrix->ty=StringToDouble(token,(char **) NULL);
701         flags|=YValue;
702         break;
703       }
704     }
705   }
706   determinant=(affine_matrix->sx*affine_matrix->sy
707                  - affine_matrix->rx*affine_matrix->ry);
708   if (fabs(determinant) < MagickEpsilon)
709     (void) ThrowMagickException(exception,GetMagickModule(),OptionError,
710       "InvalidArgument","'%s' : 'Indeterminate Matrix'",geometry);
711   return(flags);
712 }
713 \f
714 /*
715 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
716 %                                                                             %
717 %                                                                             %
718 %                                                                             %
719 %   P a r s e G e o m e t r y                                                 %
720 %                                                                             %
721 %                                                                             %
722 %                                                                             %
723 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
724 %
725 %  ParseGeometry() parses a geometry specification and returns the sigma,
726 %  rho, xi, and psi values.  It also returns flags that indicates which
727 %  of the four values (sigma, rho, xi, psi) were located in the string, and
728 %  whether the xi or pi values are negative.
729 %
730 %  In addition, it reports if there are any of meta characters (%, !, <, >, @,
731 %  and ^) flags present. It does not report the location of the percentage
732 %  relative to the values.
733 %
734 %  The format of the ParseGeometry method is:
735 %
736 %      MagickStatusType ParseGeometry(const char *geometry,
737 %        GeometryInfo *geometry_info)
738 %
739 %  A description of each parameter follows:
740 %
741 %    o geometry:  The geometry string (e.g. "100x100+10+10").
742 %
743 %    o geometry_info:  returns the parsed width/height/x/y in this structure.
744 %
745 */
746 MagickExport MagickStatusType ParseGeometry(const char *geometry,
747   GeometryInfo *geometry_info)
748 {
749   char
750     *p,
751     pedantic_geometry[MaxTextExtent],
752     *q;
753
754   double
755     value;
756
757   int
758     c;
759
760   MagickStatusType
761     flags;
762
763   /*
764     Remove whitespaces meta characters from geometry specification.
765   */
766   assert(geometry_info != (GeometryInfo *) NULL);
767   flags=NoValue;
768   if ((geometry == (char *) NULL) || (*geometry == '\0'))
769     return(flags);
770   if (strlen(geometry) >= (MaxTextExtent-1))
771     return(flags);
772   (void) CopyMagickString(pedantic_geometry,geometry,MaxTextExtent);
773   for (p=pedantic_geometry; *p != '\0'; )
774   {
775     if (isspace((int) ((unsigned char) *p)) != 0)
776       {
777         (void) CopyMagickString(p,p+1,MaxTextExtent);
778         continue;
779       }
780     c=(int) ((unsigned char) *p);
781     switch (c)
782     {
783       case '%':
784       {
785         flags|=PercentValue;
786         (void) CopyMagickString(p,p+1,MaxTextExtent);
787         break;
788       }
789       case '!':
790       {
791         flags|=AspectValue;
792         (void) CopyMagickString(p,p+1,MaxTextExtent);
793         break;
794       }
795       case '<':
796       {
797         flags|=LessValue;
798         (void) CopyMagickString(p,p+1,MaxTextExtent);
799         break;
800       }
801       case '>':
802       {
803         flags|=GreaterValue;
804         (void) CopyMagickString(p,p+1,MaxTextExtent);
805         break;
806       }
807       case '^':
808       {
809         flags|=MinimumValue;
810         (void) CopyMagickString(p,p+1,MaxTextExtent);
811         break;
812       }
813       case '@':
814       {
815         flags|=AreaValue;
816         (void) CopyMagickString(p,p+1,MaxTextExtent);
817         break;
818       }
819       case '(':
820       case ')':
821       {
822         (void) CopyMagickString(p,p+1,MaxTextExtent);
823         break;
824       }
825       case '-':
826       case '+':
827       case ',':
828       case '0':
829       case '1':
830       case '2':
831       case '3':
832       case '4':
833       case '5':
834       case '6':
835       case '7':
836       case '8':
837       case '9':
838       case 'x':
839       case 'X':
840       case '/':
841       case ':':
842       case 215:
843       {
844         p++;
845         break;
846       }
847       case '.':
848       {
849         p++;
850         flags|=DecimalValue;
851         break;
852       }
853       default:
854         return(flags);
855     }
856   }
857   /*
858     Parse rho, sigma, xi, psi, and optionally chi.
859   */
860   p=pedantic_geometry;
861   if (*p == '\0')
862     return(flags);
863   q=p;
864   value=StringToDouble(p,&q);
865   if (LocaleNCompare(p,"0x",2) == 0)
866     value=(double) strtol(p,&q,10);
867   c=(int) ((unsigned char) *q);
868   if ((c == 215) || (*q == 'x') || (*q == 'X') || (*q == ',') ||
869       (*q == '/') || (*q == ':') || (*q =='\0'))
870     {
871       /*
872         Parse rho.
873       */
874       q=p;
875       if (LocaleNCompare(p,"0x",2) == 0)
876         value=(double) strtol(p,&p,10);
877       else
878         value=StringToDouble(p,&p);
879       if (p != q)
880         {
881           flags|=RhoValue;
882           geometry_info->rho=value;
883         }
884     }
885   q=p;
886   c=(int) ((unsigned char) *p);
887   if ((c == 215) || (*p == 'x') || (*p == 'X') || (*p == ',') || (*p == '/') ||
888       (*p == ':'))
889     {
890       /*
891         Parse sigma.
892       */
893       p++;
894       while (isspace((int) ((unsigned char) *p)) != 0)
895         p++;
896       c=(int) ((unsigned char) *q);
897       if (((c != 215) && (*q != 'x') && (*q != 'X')) || ((*p != '+') &&
898           (*p != '-')))
899         {
900           q=p;
901           value=StringToDouble(p,&p);
902           if (p != q)
903             {
904               flags|=SigmaValue;
905               geometry_info->sigma=value;
906             }
907         }
908     }
909   while (isspace((int) ((unsigned char) *p)) != 0)
910     p++;
911   if ((*p == '+') || (*p == '-') || (*p == ',') || (*p == '/') || (*p == ':'))
912     {
913       /*
914         Parse xi value.
915       */
916       if ((*p == ',') || (*p == '/') || (*p == ':'))
917         p++;
918       q=p;
919       value=StringToDouble(p,&p);
920       if (p != q)
921         {
922           flags|=XiValue;
923           if (*q == '-')
924             flags|=XiNegative;
925           geometry_info->xi=value;
926         }
927       while (isspace((int) ((unsigned char) *p)) != 0)
928         p++;
929       if ((*p == '+') || (*p == '-') || (*p == ',') || (*p == '/') ||
930           (*p == ':'))
931         {
932           /*
933             Parse psi value.
934           */
935           if ((*p == ',') || (*p == '/') || (*p == ':'))
936             p++;
937           q=p;
938           value=StringToDouble(p,&p);
939           if (p != q)
940             {
941               flags|=PsiValue;
942               if (*q == '-')
943                 flags|=PsiNegative;
944               geometry_info->psi=value;
945             }
946         }
947       while (isspace((int) ((unsigned char) *p)) != 0)
948         p++;
949       if ((*p == '+') || (*p == '-') || (*p == ',') || (*p == '/') ||
950           (*p == ':'))
951         {
952           /*
953             Parse chi value.
954           */
955           if ((*p == ',') || (*p == '/') || (*p == ':'))
956             p++;
957           q=p;
958           value=StringToDouble(p,&p);
959           if (p != q)
960             {
961               flags|=ChiValue;
962               if (*q == '-')
963                 flags|=ChiNegative;
964               geometry_info->chi=value;
965             }
966         }
967     }
968   if (strchr(pedantic_geometry,':') != (char *) NULL)
969     {
970       /*
971         Normalize sampling factor (e.g. 4:2:2 => 2x1).
972       */
973       geometry_info->rho/=geometry_info->sigma;
974       geometry_info->sigma=1.0;
975       if (geometry_info->xi == 0.0)
976         geometry_info->sigma=2.0;
977     }
978   if (((flags & SigmaValue) == 0) && ((flags & XiValue) != 0) &&
979       ((flags & PsiValue) == 0))
980     {
981       /*
982         Support negative height values (e.g. 30x-20).
983       */
984       geometry_info->sigma=geometry_info->xi;
985       geometry_info->xi=0.0;
986       flags|=SigmaValue;
987       flags&=(~XiValue);
988     }
989   return(flags);
990 }
991 \f
992 /*
993 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
994 %                                                                             %
995 %                                                                             %
996 %                                                                             %
997 %   P a r s e G r a v i t y G e o m e t r y                                   %
998 %                                                                             %
999 %                                                                             %
1000 %                                                                             %
1001 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1002 %
1003 %  ParseGravityGeometry() returns a region as defined by the geometry string
1004 %  with respect to the given image page (canvas) dimensions and the images
1005 %  gravity setting.
1006 %
1007 %  This is typically used for specifing a area within a given image for
1008 %  cropping images to a smaller size, chopping out rows and or columns, or
1009 %  resizing and positioning overlay images.
1010 %
1011 %  Percentages are relative to image size and not page size, and are set to
1012 %  nearest integer (pixel) size.
1013 %
1014 %  The format of the ParseGravityGeometry method is:
1015 %
1016 %      MagickStatusType ParseGravityGeometry(Image *image,const char *geometry,
1017 %        RectangeInfo *region_info,ExceptionInfo *exception)
1018 %
1019 %  A description of each parameter follows:
1020 %
1021 %    o geometry:  The geometry string (e.g. "100x100+10+10").
1022 %
1023 %    o region_info: the region as defined by the geometry string with respect
1024 %      to the image dimensions and its gravity.
1025 %
1026 %    o exception: return any errors or warnings in this structure.
1027 %
1028 */
1029 MagickExport MagickStatusType ParseGravityGeometry(const Image *image,
1030   const char *geometry,RectangleInfo *region_info,ExceptionInfo *exception)
1031 {
1032   MagickStatusType
1033     flags;
1034
1035   size_t
1036     height,
1037     width;
1038
1039   SetGeometry(image,region_info);
1040   if (image->page.width != 0)
1041     region_info->width=image->page.width;
1042   if (image->page.height != 0)
1043     region_info->height=image->page.height;
1044   flags=ParseAbsoluteGeometry(geometry,region_info);
1045   if (flags == NoValue)
1046     {
1047       (void) ThrowMagickException(exception,GetMagickModule(),OptionError,
1048         "InvalidGeometry","`%s'",geometry);
1049       return(flags);
1050     }
1051   if ((flags & PercentValue) != 0)
1052     {
1053       GeometryInfo
1054         geometry_info;
1055
1056       MagickStatusType
1057         status;
1058
1059       PointInfo
1060         scale;
1061
1062       /*
1063         Geometry is a percentage of the image size, not canvas size
1064       */
1065       if (image->gravity != UndefinedGravity)
1066         flags|=XValue | YValue;
1067       status=ParseGeometry(geometry,&geometry_info);
1068       scale.x=geometry_info.rho;
1069       if ((status & RhoValue) == 0)
1070         scale.x=100.0;
1071       scale.y=geometry_info.sigma;
1072       if ((status & SigmaValue) == 0)
1073         scale.y=scale.x;
1074       region_info->width=(size_t) floor((scale.x*image->columns/100.0)+0.5);
1075       region_info->height=(size_t) floor((scale.y*image->rows/100.0)+0.5);
1076     }
1077   /*
1078     Adjust offset according to gravity setting.
1079   */
1080   width=region_info->width;
1081   height=region_info->height;
1082   if (width == 0)
1083     region_info->width=image->page.width | image->columns;
1084   if (height == 0)
1085     region_info->height=image->page.height | image->rows;
1086   GravityAdjustGeometry(image->columns,image->rows,image->gravity,region_info);
1087   region_info->width=width;
1088   region_info->height=height;
1089   return(flags);
1090 }
1091 \f
1092 /*
1093 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1094 %                                                                             %
1095 %                                                                             %
1096 %                                                                             %
1097 +   P a r s e M e t a G e o m e t r y                                         %
1098 %                                                                             %
1099 %                                                                             %
1100 %                                                                             %
1101 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1102 %
1103 %  ParseMetaGeometry() is similar to GetGeometry() except the returned
1104 %  geometry is modified as determined by the meta characters:  %, !, <, >, @,
1105 %  and ^ in relation to image resizing.
1106 %
1107 %  Final image dimensions are adjusted so as to preserve the aspect ratio as
1108 %  much as possible, while generating a integer (pixel) size, and fitting the
1109 %  image within the specified geometry width and height.
1110 %
1111 %  Flags are interpreted...
1112 %     %   geometry size is given percentage of original image size
1113 %     !   do not try to preserve aspect ratio
1114 %     <   only enlarge images smaller that geometry
1115 %     >   only shrink images larger than geometry
1116 %     @   Fit image to contain at most this many pixels
1117 %     ^   Contain the given geometry given, (minimal dimensions given)
1118 %
1119 %  The format of the ParseMetaGeometry method is:
1120 %
1121 %      MagickStatusType ParseMetaGeometry(const char *geometry,ssize_t *x,
1122 %        ssize_t *y, size_t *width,size_t *height)
1123 %
1124 %  A description of each parameter follows:
1125 %
1126 %    o geometry:  The geometry string (e.g. "100x100+10+10").
1127 %
1128 %    o x,y:  The x and y offset, set according to the geometry specification.
1129 %
1130 %    o width,height:  The width and height of original image, modified by
1131 %      the given geometry specification.
1132 %
1133 */
1134
1135 static inline size_t MagickMax(const size_t x,
1136   const size_t y)
1137 {
1138   if (x > y)
1139     return(x);
1140   return(y);
1141 }
1142
1143 MagickExport MagickStatusType ParseMetaGeometry(const char *geometry,ssize_t *x,
1144   ssize_t *y,size_t *width,size_t *height)
1145 {
1146   GeometryInfo
1147     geometry_info;
1148
1149   MagickStatusType
1150     flags;
1151
1152   size_t
1153     former_height,
1154     former_width;
1155
1156   /*
1157     Ensure the image geometry is valid.
1158   */
1159   assert(x != (ssize_t *) NULL);
1160   assert(y != (ssize_t *) NULL);
1161   assert(width != (size_t *) NULL);
1162   assert(height != (size_t *) NULL);
1163   if ((geometry == (char *) NULL) || (*geometry == '\0'))
1164     return(NoValue);
1165   (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",geometry);
1166   /*
1167     Parse geometry using GetGeometry.
1168   */
1169   SetGeometryInfo(&geometry_info);
1170   former_width=(*width);
1171   former_height=(*height);
1172   flags=GetGeometry(geometry,x,y,width,height);
1173   if ((flags & PercentValue) != 0)
1174     {
1175       MagickStatusType
1176         flags;
1177
1178       PointInfo
1179         scale;
1180
1181       /*
1182         Geometry is a percentage of the image size.
1183       */
1184       flags=ParseGeometry(geometry,&geometry_info);
1185       scale.x=geometry_info.rho;
1186       if ((flags & RhoValue) == 0)
1187         scale.x=100.0;
1188       scale.y=geometry_info.sigma;
1189       if ((flags & SigmaValue) == 0)
1190         scale.y=scale.x;
1191       *width=(size_t) floor(scale.x*former_width/100.0+0.5);
1192       if (*width == 0)
1193         *width=1;
1194       *height=(size_t) floor(scale.y*former_height/100.0+0.5);
1195       if (*height == 0)
1196         *height=1;
1197       former_width=(*width);
1198       former_height=(*height);
1199     }
1200   if (((flags & AspectValue) != 0) || ((*width == former_width) &&
1201       (*height == former_height)))
1202     {
1203       if ((flags & RhoValue) == 0)
1204         *width=former_width;
1205       if ((flags & SigmaValue) == 0)
1206         *height=former_height;
1207     }
1208   else
1209     {
1210       double
1211         scale_factor;
1212
1213       /*
1214         Respect aspect ratio of the image.
1215       */
1216       if ((former_width == 0) || (former_height == 0))
1217         scale_factor=1.0;
1218       else
1219         if (((flags & RhoValue) != 0) && (flags & SigmaValue) != 0)
1220           {
1221             scale_factor=(double) *width/(double) former_width;
1222             if ((flags & MinimumValue) == 0)
1223               {
1224                 if (scale_factor > ((double) *height/(double) former_height))
1225                   scale_factor=(double) *height/(double) former_height;
1226               }
1227             else
1228               if (scale_factor < ((double) *height/(double) former_height))
1229                 scale_factor=(double) *height/(double) former_height;
1230           }
1231         else
1232           if ((flags & RhoValue) != 0)
1233             {
1234               scale_factor=(double) *width/(double) former_width;
1235               if (((flags & MinimumValue) != 0) &&
1236                   (scale_factor < ((double) *width/(double) former_height)))
1237                 scale_factor=(double) *width/(double) former_height;
1238             }
1239           else
1240             {
1241               scale_factor=(double) *height/(double) former_height;
1242               if (((flags & MinimumValue) != 0) &&
1243                   (scale_factor < ((double) *height/(double) former_width)))
1244                 scale_factor=(double) *height/(double) former_width;
1245             }
1246       *width=MagickMax((size_t) floor(scale_factor*former_width+0.5),1UL);
1247       *height=MagickMax((size_t) floor(scale_factor*former_height+0.5),1UL);
1248     }
1249   if ((flags & GreaterValue) != 0)
1250     {
1251       if (former_width < *width)
1252         *width=former_width;
1253       if (former_height < *height)
1254         *height=former_height;
1255     }
1256   if ((flags & LessValue) != 0)
1257     {
1258       if (former_width > *width)
1259         *width=former_width;
1260       if (former_height > *height)
1261         *height=former_height;
1262     }
1263   if ((flags & AreaValue) != 0)
1264     {
1265       double
1266         area,
1267         distance;
1268
1269       PointInfo
1270         scale;
1271
1272       /*
1273         Geometry is a maximum area in pixels.
1274       */
1275       (void) ParseGeometry(geometry,&geometry_info);
1276       area=geometry_info.rho;
1277       distance=sqrt((double) former_width*former_height);
1278       scale.x=(double) former_width/(distance/sqrt((double) area));
1279       scale.y=(double) former_height/(distance/sqrt((double) area));
1280       if ((scale.x < (double) *width) || (scale.y < (double) *height))
1281         {
1282           *width=(size_t) (former_width/(distance/sqrt(area))+0.5);
1283           *height=(size_t) (former_height/(distance/sqrt(area))+0.5);
1284         }
1285       former_width=(*width);
1286       former_height=(*height);
1287     }
1288   return(flags);
1289 }
1290 \f
1291 /*
1292 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1293 %                                                                             %
1294 %                                                                             %
1295 %                                                                             %
1296 %   P a r s e P a g e G e o m e t r y                                         %
1297 %                                                                             %
1298 %                                                                             %
1299 %                                                                             %
1300 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1301 %
1302 %  ParsePageGeometry() returns a region as defined by the geometry string with
1303 %  respect to the image page (canvas) dimensions.
1304 %
1305 %  WARNING: Percentage dimensions remain relative to the actual image
1306 %  dimensions, and not canvas dimensions.
1307 %
1308 %  The format of the ParsePageGeometry method is:
1309 %
1310 %      MagickStatusType ParsePageGeometry(const Image *image,
1311 %        const char *geometry,RectangeInfo *region_info,
1312 %        ExceptionInfo *exception)
1313 %
1314 %  A description of each parameter follows:
1315 %
1316 %    o geometry:  The geometry string (e.g. "100x100+10+10").
1317 %
1318 %    o region_info: the region as defined by the geometry string with
1319 %      respect to the image and its gravity.
1320 %
1321 %    o exception: return any errors or warnings in this structure.
1322 %
1323 */
1324 MagickExport MagickStatusType ParsePageGeometry(const Image *image,
1325   const char *geometry,RectangleInfo *region_info,ExceptionInfo *exception)
1326 {
1327   MagickStatusType
1328     flags;
1329
1330   SetGeometry(image,region_info);
1331   if (image->page.width != 0)
1332     region_info->width=image->page.width;
1333   if (image->page.height != 0)
1334     region_info->height=image->page.height;
1335   flags=ParseAbsoluteGeometry(geometry,region_info);
1336   if (flags == NoValue)
1337     {
1338       (void) ThrowMagickException(exception,GetMagickModule(),OptionError,
1339         "InvalidGeometry","`%s'",geometry);
1340       return(flags);
1341     }
1342   if ((flags & PercentValue) != 0)
1343     {
1344       region_info->width=image->columns;
1345       region_info->height=image->rows;
1346     }
1347   flags=ParseMetaGeometry(geometry,&region_info->x,&region_info->y,
1348     &region_info->width,&region_info->height);
1349   return(flags);
1350 }
1351 \f
1352 /*
1353 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1354 %                                                                             %
1355 %                                                                             %
1356 %                                                                             %
1357 %   P a r s e R e g i o n G e o m e t r y                                     %
1358 %                                                                             %
1359 %                                                                             %
1360 %                                                                             %
1361 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1362 %
1363 %  ParseRegionGeometry() returns a region as defined by the geometry string
1364 %  with respect to the image dimensions and aspect ratio.
1365 %
1366 %  This is basically a wrapper around ParseMetaGeometry.  This is typically
1367 %  used to parse a geometry string to work out the final integer dimensions
1368 %  for image resizing.
1369 %
1370 %  The format of the ParseRegionGeometry method is:
1371 %
1372 %      MagickStatusType ParseRegionGeometry(const Image *image,
1373 %        const char *geometry,RectangeInfo *region_info,
1374 %        ExceptionInfo *exception)
1375 %
1376 %  A description of each parameter follows:
1377 %
1378 %    o geometry:  The geometry string (e.g. "100x100+10+10").
1379 %
1380 %    o region_info: the region as defined by the geometry string.
1381 %
1382 %    o exception: return any errors or warnings in this structure.
1383 %
1384 */
1385 MagickExport MagickStatusType ParseRegionGeometry(const Image *image,
1386   const char *geometry,RectangleInfo *region_info,ExceptionInfo *exception)
1387 {
1388   MagickStatusType
1389     flags;
1390
1391   SetGeometry(image,region_info);
1392   flags=ParseMetaGeometry(geometry,&region_info->x,&region_info->y,
1393     &region_info->width,&region_info->height);
1394   if (flags == NoValue)
1395     (void) ThrowMagickException(exception,GetMagickModule(),OptionError,
1396       "InvalidGeometry","`%s'",geometry);
1397   return(flags);
1398 }
1399 \f
1400 /*
1401 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1402 %                                                                             %
1403 %                                                                             %
1404 %                                                                             %
1405 %   S e t G e o m e t r y                                                     %
1406 %                                                                             %
1407 %                                                                             %
1408 %                                                                             %
1409 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1410 %
1411 %  SetGeometry() sets the geometry to its default values.
1412 %
1413 %  The format of the SetGeometry method is:
1414 %
1415 %      SetGeometry(const Image *image,RectangleInfo *geometry)
1416 %
1417 %  A description of each parameter follows:
1418 %
1419 %    o image: the image.
1420 %
1421 %    o geometry: the geometry.
1422 %
1423 */
1424 MagickExport void SetGeometry(const Image *image,RectangleInfo *geometry)
1425 {
1426   assert(image != (Image *) NULL);
1427   assert(image->signature == MagickSignature);
1428   if (image->debug != MagickFalse)
1429     (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
1430   assert(geometry != (RectangleInfo *) NULL);
1431   (void) ResetMagickMemory(geometry,0,sizeof(*geometry));
1432   geometry->width=image->columns;
1433   geometry->height=image->rows;
1434 }
1435 \f
1436 /*
1437 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1438 %                                                                             %
1439 %                                                                             %
1440 %                                                                             %
1441 %   S e t G e o m e t r y I n f o                                             %
1442 %                                                                             %
1443 %                                                                             %
1444 %                                                                             %
1445 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1446 %
1447 %  SetGeometryInfo sets the GeometryInfo structure to its default values.
1448 %
1449 %  The format of the SetGeometryInfo method is:
1450 %
1451 %      SetGeometryInfo(GeometryInfo *geometry_info)
1452 %
1453 %  A description of each parameter follows:
1454 %
1455 %    o geometry_info: the geometry info structure.
1456 %
1457 */
1458 MagickExport void SetGeometryInfo(GeometryInfo *geometry_info)
1459 {
1460   assert(geometry_info != (GeometryInfo *) NULL);
1461   (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
1462   (void) ResetMagickMemory(geometry_info,0,sizeof(*geometry_info));
1463 }