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