MagickCore  6.7.5
geometry.c
Go to the documentation of this file.
00001 /*
00002 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
00003 %                                                                             %
00004 %                                                                             %
00005 %                                                                             %
00006 %           GGGG   EEEEE   OOO   M   M  EEEEE  TTTTT  RRRR   Y   Y            %
00007 %           G      E      O   O  MM MM  E        T    R   R   Y Y             %
00008 %           G  GG  EEE    O   O  M M M  EEE      T    RRRR     Y              %
00009 %           G   G  E      O   O  M   M  E        T    R R      Y              %
00010 %            GGGG  EEEEE   OOO   M   M  EEEEE    T    R  R     Y              %
00011 %                                                                             %
00012 %                                                                             %
00013 %                       MagickCore Geometry Methods                           %
00014 %                                                                             %
00015 %                             Software Design                                 %
00016 %                               John Cristy                                   %
00017 %                              January 2003                                   %
00018 %                                                                             %
00019 %                                                                             %
00020 %  Copyright 1999-2012 ImageMagick Studio LLC, a non-profit organization      %
00021 %  dedicated to making software imaging solutions freely available.           %
00022 %                                                                             %
00023 %  You may not use this file except in compliance with the License.  You may  %
00024 %  obtain a copy of the License at                                            %
00025 %                                                                             %
00026 %    http://www.imagemagick.org/script/license.php                            %
00027 %                                                                             %
00028 %  Unless required by applicable law or agreed to in writing, software        %
00029 %  distributed under the License is distributed on an "AS IS" BASIS,          %
00030 %  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.   %
00031 %  See the License for the specific language governing permissions and        %
00032 %  limitations under the License.                                             %
00033 %                                                                             %
00034 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
00035 %
00036 %
00037 */
00038 
00039 /*
00040   Include declarations.
00041 */
00042 #include "MagickCore/studio.h"
00043 #include "MagickCore/constitute.h"
00044 #include "MagickCore/draw.h"
00045 #include "MagickCore/exception.h"
00046 #include "MagickCore/exception-private.h"
00047 #include "MagickCore/geometry.h"
00048 #include "MagickCore/memory_.h"
00049 #include "MagickCore/string_.h"
00050 #include "MagickCore/string-private.h"
00051 #include "MagickCore/token.h"
00052 
00053 /*
00054 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
00055 %                                                                             %
00056 %                                                                             %
00057 %                                                                             %
00058 %   G e t G e o m e t r y                                                     %
00059 %                                                                             %
00060 %                                                                             %
00061 %                                                                             %
00062 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
00063 %
00064 %  GetGeometry() parses a geometry specification and returns the width,
00065 %  height, x, and y values.  It also returns flags that indicates which
00066 %  of the four values (width, height, x, y) were located in the string, and
00067 %  whether the x or y values are negative.  In addition, there are flags to
00068 %  report any meta characters (%, !, <, or >).
00069 %
00070 %  The format of the GetGeometry method is:
00071 %
00072 %      MagickStatusType GetGeometry(const char *geometry,ssize_t *x,ssize_t *y,
00073 %        size_t *width,size_t *height)
00074 %
00075 %  A description of each parameter follows:
00076 %
00077 %    o geometry:  The geometry.
00078 %
00079 %    o x,y:  The x and y offset as determined by the geometry specification.
00080 %
00081 %    o width,height:  The width and height as determined by the geometry
00082 %      specification.
00083 %
00084 */
00085 MagickExport MagickStatusType GetGeometry(const char *geometry,ssize_t *x,
00086   ssize_t *y,size_t *width,size_t *height)
00087 {
00088   char
00089     *p,
00090     pedantic_geometry[MaxTextExtent],
00091     *q;
00092 
00093   double
00094     value;
00095 
00096   int
00097     c;
00098 
00099   MagickStatusType
00100     flags;
00101 
00102   /*
00103     Remove whitespace and meta characters from geometry specification.
00104   */
00105   flags=NoValue;
00106   if ((geometry == (char *) NULL) || (*geometry == '\0'))
00107     return(flags);
00108   if (strlen(geometry) >= (MaxTextExtent-1))
00109     return(flags);
00110   (void) CopyMagickString(pedantic_geometry,geometry,MaxTextExtent);
00111   for (p=pedantic_geometry; *p != '\0'; )
00112   {
00113     if (isspace((int) ((unsigned char) *p)) != 0)
00114       {
00115         (void) CopyMagickString(p,p+1,MaxTextExtent);
00116         continue;
00117       }
00118     c=(int) ((unsigned int) *p);
00119     switch (c)
00120     {
00121       case '%':
00122       {
00123         flags|=PercentValue;
00124         (void) CopyMagickString(p,p+1,MaxTextExtent);
00125         break;
00126       }
00127       case '!':
00128       {
00129         flags|=AspectValue;
00130         (void) CopyMagickString(p,p+1,MaxTextExtent);
00131         break;
00132       }
00133       case '<':
00134       {
00135         flags|=LessValue;
00136         (void) CopyMagickString(p,p+1,MaxTextExtent);
00137         break;
00138       }
00139       case '>':
00140       {
00141         flags|=GreaterValue;
00142         (void) CopyMagickString(p,p+1,MaxTextExtent);
00143         break;
00144       }
00145       case '^':
00146       {
00147         flags|=MinimumValue;
00148         (void) CopyMagickString(p,p+1,MaxTextExtent);
00149         break;
00150       }
00151       case '@':
00152       {
00153         flags|=AreaValue;
00154         (void) CopyMagickString(p,p+1,MaxTextExtent);
00155         break;
00156       }
00157       case '(':
00158       case ')':
00159       {
00160         (void) CopyMagickString(p,p+1,MaxTextExtent);
00161         break;
00162       }
00163       case '-':
00164       case '.':
00165       case ',':
00166       case '+':
00167       case '0':
00168       case '1':
00169       case '2':
00170       case '3':
00171       case '4':
00172       case '5':
00173       case '6':
00174       case '7':
00175       case '8':
00176       case '9':
00177       case 'x':
00178       case 'X':
00179       case 215:
00180       {
00181         p++;
00182         break;
00183       }
00184       default:
00185         return(flags);
00186     }
00187   }
00188   /*
00189     Parse width, height, x, and y.
00190   */
00191   p=pedantic_geometry;
00192   if (*p == '\0')
00193     return(flags);
00194   q=p;
00195   value=StringToDouble(p,&q);
00196   (void) value;
00197   if (LocaleNCompare(p,"0x",2) == 0)
00198     value=(double) strtol(p,&q,10);
00199   c=(int) ((unsigned char) *q);
00200   if ((c == 215) || (*q == 'x') || (*q == 'X') || (*q == '\0'))
00201     {
00202       /*
00203         Parse width.
00204       */
00205       q=p;
00206       if (LocaleNCompare(p,"0x",2) == 0)
00207         *width=(size_t) strtol(p,&p,10);
00208       else
00209         *width=(size_t) floor(StringToDouble(p,&p)+0.5);
00210       if (p != q)
00211         flags|=WidthValue;
00212     }
00213   c=(*p);
00214   c=(int) ((unsigned char) *p);
00215   if ((c == 215) || (*p == 'x') || (*p == 'X'))
00216     {
00217       p++;
00218       if ((*p != '+') && (*p != '-'))
00219         {
00220           /*
00221             Parse height.
00222           */
00223           q=p;
00224           *height=(size_t) floor(StringToDouble(p,&p)+0.5);
00225           if (p != q)
00226             flags|=HeightValue;
00227         }
00228     }
00229   if ((*p == '+') || (*p == '-'))
00230     {
00231       /*
00232         Parse x value.
00233       */
00234       if (*p == '-')
00235         flags|=XNegative;
00236       q=p;
00237       *x=(ssize_t) ceil(StringToDouble(p,&p)-0.5);
00238       if (p != q)
00239         flags|=XValue;
00240       if ((*p == '+') || (*p == '-'))
00241         {
00242           /*
00243             Parse y value.
00244           */
00245           if (*p == '-')
00246             flags|=YNegative;
00247           q=p;
00248           *y=(ssize_t) ceil(StringToDouble(p,&p)-0.5);
00249           if (p != q)
00250             flags|=YValue;
00251         }
00252     }
00253   return(flags);
00254 }
00255 
00256 /*
00257 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
00258 %                                                                             %
00259 %                                                                             %
00260 %                                                                             %
00261 %  G e t P a g e G e o m e t r y                                              %
00262 %                                                                             %
00263 %                                                                             %
00264 %                                                                             %
00265 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
00266 %
00267 %  GetPageGeometry() replaces any page mneumonic with the equivalent size in
00268 %  picas.
00269 %
00270 %  The format of the GetPageGeometry method is:
00271 %
00272 %      char *GetPageGeometry(const char *page_geometry)
00273 %
00274 %  A description of each parameter follows.
00275 %
00276 %   o  page_geometry:  Specifies a pointer to an array of characters.  The
00277 %      string is either a Postscript page name (e.g. A4) or a postscript page
00278 %      geometry (e.g. 612x792+36+36).
00279 %
00280 */
00281 MagickExport char *GetPageGeometry(const char *page_geometry)
00282 {
00283   static const char
00284     *PageSizes[][2]=
00285     {
00286       { "4x6",  "288x432" },
00287       { "5x7",  "360x504" },
00288       { "7x9",  "504x648" },
00289       { "8x10", "576x720" },
00290       { "9x11",  "648x792" },
00291       { "9x12",  "648x864" },
00292       { "10x13",  "720x936" },
00293       { "10x14",  "720x1008" },
00294       { "11x17",  "792x1224" },
00295       { "a0",  "2384x3370" },
00296       { "a1",  "1684x2384" },
00297       { "a10", "73x105" },
00298       { "a2",  "1191x1684" },
00299       { "a3",  "842x1191" },
00300       { "a4",  "595x842" },
00301       { "a4smaLL", "595x842" },
00302       { "a5",  "420x595" },
00303       { "a6",  "297x420" },
00304       { "a7",  "210x297" },
00305       { "a8",  "148x210" },
00306       { "a9",  "105x148" },
00307       { "archa", "648x864" },
00308       { "archb", "864x1296" },
00309       { "archC", "1296x1728" },
00310       { "archd", "1728x2592" },
00311       { "arche", "2592x3456" },
00312       { "b0",  "2920x4127" },
00313       { "b1",  "2064x2920" },
00314       { "b10", "91x127" },
00315       { "b2",  "1460x2064" },
00316       { "b3",  "1032x1460" },
00317       { "b4",  "729x1032" },
00318       { "b5",  "516x729" },
00319       { "b6",  "363x516" },
00320       { "b7",  "258x363" },
00321       { "b8",  "181x258" },
00322       { "b9",  "127x181" },
00323       { "c0",  "2599x3676" },
00324       { "c1",  "1837x2599" },
00325       { "c2",  "1298x1837" },
00326       { "c3",  "918x1296" },
00327       { "c4",  "649x918" },
00328       { "c5",  "459x649" },
00329       { "c6",  "323x459" },
00330       { "c7",  "230x323" },
00331       { "executive", "540x720" },
00332       { "flsa", "612x936" },
00333       { "flse", "612x936" },
00334       { "folio",  "612x936" },
00335       { "halfletter", "396x612" },
00336       { "isob0", "2835x4008" },
00337       { "isob1", "2004x2835" },
00338       { "isob10", "88x125" },
00339       { "isob2", "1417x2004" },
00340       { "isob3", "1001x1417" },
00341       { "isob4", "709x1001" },
00342       { "isob5", "499x709" },
00343       { "isob6", "354x499" },
00344       { "isob7", "249x354" },
00345       { "isob8", "176x249" },
00346       { "isob9", "125x176" },
00347       { "jisb0", "1030x1456" },
00348       { "jisb1", "728x1030" },
00349       { "jisb2", "515x728" },
00350       { "jisb3", "364x515" },
00351       { "jisb4", "257x364" },
00352       { "jisb5", "182x257" },
00353       { "jisb6", "128x182" },
00354       { "ledger",  "1224x792" },
00355       { "legal",  "612x1008" },
00356       { "letter", "612x792" },
00357       { "lettersmaLL",  "612x792" },
00358       { "quarto",  "610x780" },
00359       { "statement",  "396x612" },
00360       { "tabloid",  "792x1224" },
00361       { (char *) NULL, (char *) NULL }
00362     };
00363 
00364   char
00365     *page;
00366 
00367   register ssize_t
00368     i;
00369 
00370   assert(page_geometry != (char *) NULL);
00371   (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",page_geometry);
00372   page=AcquireString(page_geometry);
00373   for (i=0; *PageSizes[i] != (char *) NULL; i++)
00374     if (LocaleNCompare(PageSizes[i][0],page,strlen(PageSizes[i][0])) == 0)
00375       {
00376         RectangleInfo
00377           geometry;
00378 
00379         MagickStatusType
00380           flags;
00381 
00382         /*
00383           Replace mneumonic with the equivalent size in dots-per-inch.
00384         */
00385         (void) CopyMagickString(page,PageSizes[i][1],MaxTextExtent);
00386         (void) ConcatenateMagickString(page,page_geometry+
00387           strlen(PageSizes[i][0]),MaxTextExtent);
00388         flags=GetGeometry(page,&geometry.x,&geometry.y,&geometry.width,
00389           &geometry.height);
00390         if ((flags & GreaterValue) == 0)
00391           (void) ConcatenateMagickString(page,">",MaxTextExtent);
00392         break;
00393       }
00394   return(page);
00395 }
00396 
00397 /*
00398 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
00399 %                                                                             %
00400 %                                                                             %
00401 %                                                                             %
00402 %   G r a v i t y A d j u s t G e o m e t r y                                 %
00403 %                                                                             %
00404 %                                                                             % %                                                                             %
00405 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
00406 %
00407 %  GravityAdjustGeometry() adjusts the offset of a region with regard to the
00408 %  given: width, height and gravity; against which it is positioned.
00409 %
00410 %  The region should also have an appropriate width and height to correctly
00411 %  set the right offset of the top left corner of the region.
00412 %
00413 %  The format of the GravityAdjustGeometry method is:
00414 %
00415 %      void GravityAdjustGeometry(const size_t width, const size_t height,
00416 %        const GravityType gravity,RectangleInfo *region);
00417 %
00418 %  A description of each parameter follows:
00419 %
00420 %    o width, height:  the larger area the region is relative to
00421 %
00422 %    o gravity: the edge/corner the current offset is relative to
00423 %
00424 %    o region:  The region requiring a offset adjustment relative to gravity
00425 %
00426 */
00427 MagickExport void GravityAdjustGeometry(const size_t width,
00428   const size_t height,const GravityType gravity,RectangleInfo *region)
00429 {
00430   if (region->height == 0)
00431     region->height=height;
00432   if (region->width == 0)
00433     region->width=width;
00434   switch (gravity)
00435   {
00436     case NorthEastGravity:
00437     case EastGravity:
00438     case SouthEastGravity:
00439     {
00440       region->x=(ssize_t) (width-region->width-region->x);
00441       break;
00442     }
00443     case NorthGravity:
00444     case SouthGravity:
00445     case CenterGravity:
00446     case StaticGravity:
00447     {
00448       region->x+=(ssize_t) (width/2-region->width/2);
00449       break;
00450     }
00451     case ForgetGravity:
00452     case NorthWestGravity:
00453     case WestGravity:
00454     case SouthWestGravity:
00455     default:
00456       break;
00457   }
00458   switch (gravity)
00459   {
00460     case SouthWestGravity:
00461     case SouthGravity:
00462     case SouthEastGravity:
00463     {
00464       region->y=(ssize_t) (height-region->height-region->y);
00465       break;
00466     }
00467     case EastGravity:
00468     case WestGravity:
00469     case CenterGravity:
00470     case StaticGravity:
00471     {
00472       region->y+=(ssize_t) (height/2-region->height/2);
00473       break;
00474     }
00475     case ForgetGravity:
00476     case NorthWestGravity:
00477     case NorthGravity:
00478     case NorthEastGravity:
00479     default:
00480       break;
00481   }
00482   return;
00483 }
00484 
00485 /*
00486 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
00487 %                                                                             %
00488 %                                                                             %
00489 %                                                                             %
00490 +     I s G e o m e t r y                                                     %
00491 %                                                                             %
00492 %                                                                             %
00493 %                                                                             %
00494 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
00495 %
00496 %  IsGeometry() returns MagickTrue if the geometry specification is valid.
00497 %  Examples are 100, 100x200, x200, 100x200+10+20, +10+20, 200%, 200x200!, etc.
00498 %
00499 %  The format of the IsGeometry method is:
00500 %
00501 %      MagickBooleanType IsGeometry(const char *geometry)
00502 %
00503 %  A description of each parameter follows:
00504 %
00505 %    o geometry: This string is the geometry specification.
00506 %
00507 */
00508 MagickExport MagickBooleanType IsGeometry(const char *geometry)
00509 {
00510   GeometryInfo
00511     geometry_info;
00512 
00513   MagickStatusType
00514     flags;
00515 
00516   if (geometry == (const char *) NULL)
00517     return(MagickFalse);
00518   flags=ParseGeometry(geometry,&geometry_info);
00519   if (flags == NoValue)
00520     flags=ParseGeometry(geometry+1,&geometry_info);  /* i.e. +-4+-4 */
00521   return(flags != NoValue ? MagickTrue : MagickFalse);
00522 }
00523 
00524 /*
00525 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
00526 %                                                                             %
00527 %                                                                             %
00528 %                                                                             %
00529 +     I s S c e n e G e o m e t r y                                           %
00530 %                                                                             %
00531 %                                                                             %
00532 %                                                                             %
00533 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
00534 %
00535 %  IsSceneGeometry() returns MagickTrue if the geometry is a valid scene
00536 %  specification (e.g. [1], [1-9], [1,7,4]).
00537 %
00538 %  The format of the IsSceneGeometry method is:
00539 %
00540 %      MagickBooleanType IsSceneGeometry(const char *geometry,
00541 %        const MagickBooleanType pedantic)
00542 %
00543 %  A description of each parameter follows:
00544 %
00545 %    o geometry: This string is the geometry specification.
00546 %
00547 %    o pedantic: A value other than 0 invokes a more restrictive set of
00548 %      conditions for a valid specification (e.g. [1], [1-4], [4-1]).
00549 %
00550 */
00551 MagickExport MagickBooleanType IsSceneGeometry(const char *geometry,
00552   const MagickBooleanType pedantic)
00553 {
00554   char
00555     *p;
00556 
00557   double
00558     value;
00559 
00560   if (geometry == (const char *) NULL)
00561     return(MagickFalse);
00562   p=(char *) geometry;
00563   value=StringToDouble(geometry,&p);
00564   (void) value;
00565   if (p == geometry)
00566     return(MagickFalse);
00567   if (strspn(geometry,"0123456789-, ") != strlen(geometry))
00568     return(MagickFalse);
00569   if ((pedantic != MagickFalse) && (strchr(geometry,',') != (char *) NULL))
00570     return(MagickFalse);
00571   return(MagickTrue);
00572 }
00573 
00574 /*
00575 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
00576 %                                                                             %
00577 %                                                                             %
00578 %                                                                             %
00579 %   P a r s e A b s o l u t e G e o m e t r y                                 %
00580 %                                                                             %
00581 %                                                                             %
00582 %                                                                             %
00583 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
00584 %
00585 %  ParseAbsoluteGeometry() returns a region as defined by the geometry string,
00586 %  without any modification by percentages or gravity.
00587 %
00588 %  It currently just a wrapper around GetGeometry(), but may be expanded in
00589 %  the future to handle other positioning information.
00590 %
00591 %  The format of the ParseAbsoluteGeometry method is:
00592 %
00593 %      MagickStatusType ParseAbsoluteGeometry(const char *geometry,
00594 %        RectangleInfo *region_info)
00595 %
00596 %  A description of each parameter follows:
00597 %
00598 %    o geometry:  The geometry string (e.g. "100x100+10+10").
00599 %
00600 %    o region_info: the region as defined by the geometry string.
00601 %
00602 */
00603 MagickExport MagickStatusType ParseAbsoluteGeometry(const char *geometry,
00604   RectangleInfo *region_info)
00605 {
00606   MagickStatusType
00607     flags;
00608 
00609   flags=GetGeometry(geometry,&region_info->x,&region_info->y,
00610     &region_info->width,&region_info->height);
00611   return(flags);
00612 }
00613 
00614 /*
00615 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
00616 %                                                                             %
00617 %                                                                             %
00618 %                                                                             %
00619 %   P a r s e A f f i n e G e o m e t r y                                     %
00620 %                                                                             %
00621 %                                                                             %
00622 %                                                                             %
00623 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
00624 %
00625 %  ParseAffineGeometry() returns an affine matrix as defined by a string of 4
00626 %  to 6 comma/space separated floating point values.
00627 %
00628 %  The affine matrix determinant is checked for validity of the values.
00629 %
00630 %  The format of the ParseAffineGeometry method is:
00631 %
00632 %      MagickStatusType ParseAffineGeometry(const char *geometry,
00633 %        AffineMatrix *affine_matrix,ExceptionInfo *exception)
00634 %
00635 %  A description of each parameter follows:
00636 %
00637 %    o geometry:  The geometry string (e.g. "1.0,0.0,0.0,1.0,3.2,1.2").
00638 %
00639 %    o affine_matrix: the affine matrix as defined by the geometry string.
00640 %
00641 %    o exception: return any errors or warnings in this structure.
00642 %
00643 */
00644 MagickExport MagickStatusType ParseAffineGeometry(const char *geometry,
00645   AffineMatrix *affine_matrix,ExceptionInfo *exception)
00646 {
00647   char
00648     token[MaxTextExtent];
00649 
00650   const char
00651     *p;
00652 
00653   double
00654     determinant;
00655 
00656   MagickStatusType
00657     flags;
00658 
00659   register ssize_t
00660     i;
00661 
00662   GetAffineMatrix(affine_matrix);
00663   flags=NoValue;
00664   p=(char *) geometry;
00665   for (i=0; (*p != '\0') && (i < 6); i++)
00666   {
00667     GetMagickToken(p,&p,token);
00668     if (*token == ',')
00669       GetMagickToken(p,&p,token);
00670     switch (i)
00671     {
00672       case 0:
00673       {
00674         affine_matrix->sx=StringToDouble(token,(char **) NULL);
00675         break;
00676       }
00677       case 1:
00678       {
00679         affine_matrix->rx=StringToDouble(token,(char **) NULL);
00680         break;
00681       }
00682       case 2:
00683       {
00684         affine_matrix->ry=StringToDouble(token,(char **) NULL);
00685         break;
00686       }
00687       case 3:
00688       {
00689         affine_matrix->sy=StringToDouble(token,(char **) NULL);
00690         break;
00691       }
00692       case 4:
00693       {
00694         affine_matrix->tx=StringToDouble(token,(char **) NULL);
00695         flags|=XValue;
00696         break;
00697       }
00698       case 5:
00699       {
00700         affine_matrix->ty=StringToDouble(token,(char **) NULL);
00701         flags|=YValue;
00702         break;
00703       }
00704     }
00705   }
00706   determinant=(affine_matrix->sx*affine_matrix->sy-affine_matrix->rx*
00707     affine_matrix->ry);
00708   if (fabs(determinant) < MagickEpsilon)
00709     (void) ThrowMagickException(exception,GetMagickModule(),OptionError,
00710       "InvalidGeometry","`%s'",geometry);
00711   return(flags);
00712 }
00713 
00714 /*
00715 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
00716 %                                                                             %
00717 %                                                                             %
00718 %                                                                             %
00719 %   P a r s e G e o m e t r y                                                 %
00720 %                                                                             %
00721 %                                                                             %
00722 %                                                                             %
00723 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
00724 %
00725 %  ParseGeometry() parses a geometry specification and returns the sigma,
00726 %  rho, xi, and psi values.  It also returns flags that indicates which
00727 %  of the four values (sigma, rho, xi, psi) were located in the string, and
00728 %  whether the xi or pi values are negative.
00729 %
00730 %  In addition, it reports if there are any of meta characters (%, !, <, >, @,
00731 %  and ^) flags present. It does not report the location of the percentage
00732 %  relative to the values.
00733 %
00734 %  The format of the ParseGeometry method is:
00735 %
00736 %      MagickStatusType ParseGeometry(const char *geometry,
00737 %        GeometryInfo *geometry_info)
00738 %
00739 %  A description of each parameter follows:
00740 %
00741 %    o geometry:  The geometry string (e.g. "100x100+10+10").
00742 %
00743 %    o geometry_info:  returns the parsed width/height/x/y in this structure.
00744 %
00745 */
00746 MagickExport MagickStatusType ParseGeometry(const char *geometry,
00747   GeometryInfo *geometry_info)
00748 {
00749   char
00750     *p,
00751     pedantic_geometry[MaxTextExtent],
00752     *q;
00753 
00754   double
00755     value;
00756 
00757   int
00758     c;
00759 
00760   MagickStatusType
00761     flags;
00762 
00763   /*
00764     Remove whitespaces meta characters from geometry specification.
00765   */
00766   assert(geometry_info != (GeometryInfo *) NULL);
00767   flags=NoValue;
00768   if ((geometry == (char *) NULL) || (*geometry == '\0'))
00769     return(flags);
00770   if (strlen(geometry) >= (MaxTextExtent-1))
00771     return(flags);
00772   (void) CopyMagickString(pedantic_geometry,geometry,MaxTextExtent);
00773   for (p=pedantic_geometry; *p != '\0'; )
00774   {
00775     if (isspace((int) ((unsigned char) *p)) != 0)
00776       {
00777         (void) CopyMagickString(p,p+1,MaxTextExtent);
00778         continue;
00779       }
00780     c=(int) ((unsigned char) *p);
00781     switch (c)
00782     {
00783       case '%':
00784       {
00785         flags|=PercentValue;
00786         (void) CopyMagickString(p,p+1,MaxTextExtent);
00787         break;
00788       }
00789       case '!':
00790       {
00791         flags|=AspectValue;
00792         (void) CopyMagickString(p,p+1,MaxTextExtent);
00793         break;
00794       }
00795       case '<':
00796       {
00797         flags|=LessValue;
00798         (void) CopyMagickString(p,p+1,MaxTextExtent);
00799         break;
00800       }
00801       case '>':
00802       {
00803         flags|=GreaterValue;
00804         (void) CopyMagickString(p,p+1,MaxTextExtent);
00805         break;
00806       }
00807       case '^':
00808       {
00809         flags|=MinimumValue;
00810         (void) CopyMagickString(p,p+1,MaxTextExtent);
00811         break;
00812       }
00813       case '@':
00814       {
00815         flags|=AreaValue;
00816         (void) CopyMagickString(p,p+1,MaxTextExtent);
00817         break;
00818       }
00819       case '(':
00820       case ')':
00821       {
00822         (void) CopyMagickString(p,p+1,MaxTextExtent);
00823         break;
00824       }
00825       case '-':
00826       case '+':
00827       case ',':
00828       case '0':
00829       case '1':
00830       case '2':
00831       case '3':
00832       case '4':
00833       case '5':
00834       case '6':
00835       case '7':
00836       case '8':
00837       case '9':
00838       case 'x':
00839       case 'X':
00840       case '/':
00841       case ':':
00842       case 215:
00843       {
00844         p++;
00845         break;
00846       }
00847       case '.':
00848       {
00849         p++;
00850         flags|=DecimalValue;
00851         break;
00852       }
00853       default:
00854         return(flags);
00855     }
00856   }
00857   /*
00858     Parse rho, sigma, xi, psi, and optionally chi.
00859   */
00860   p=pedantic_geometry;
00861   if (*p == '\0')
00862     return(flags);
00863   q=p;
00864   value=StringToDouble(p,&q);
00865   if (LocaleNCompare(p,"0x",2) == 0)
00866     value=(double) strtol(p,&q,10);
00867   c=(int) ((unsigned char) *q);
00868   if ((c == 215) || (*q == 'x') || (*q == 'X') || (*q == ',') ||
00869       (*q == '/') || (*q == ':') || (*q =='\0'))
00870     {
00871       /*
00872         Parse rho.
00873       */
00874       q=p;
00875       if (LocaleNCompare(p,"0x",2) == 0)
00876         value=(double) strtol(p,&p,10);
00877       else
00878         value=StringToDouble(p,&p);
00879       if (p != q)
00880         {
00881           flags|=RhoValue;
00882           geometry_info->rho=value;
00883         }
00884     }
00885   q=p;
00886   c=(int) ((unsigned char) *p);
00887   if ((c == 215) || (*p == 'x') || (*p == 'X') || (*p == ',') || (*p == '/') ||
00888       (*p == ':'))
00889     {
00890       /*
00891         Parse sigma.
00892       */
00893       p++;
00894       while (isspace((int) ((unsigned char) *p)) != 0)
00895         p++;
00896       c=(int) ((unsigned char) *q);
00897       if (((c != 215) && (*q != 'x') && (*q != 'X')) || ((*p != '+') &&
00898           (*p != '-')))
00899         {
00900           q=p;
00901           value=StringToDouble(p,&p);
00902           if (p != q)
00903             {
00904               flags|=SigmaValue;
00905               geometry_info->sigma=value;
00906             }
00907         }
00908     }
00909   while (isspace((int) ((unsigned char) *p)) != 0)
00910     p++;
00911   if ((*p == '+') || (*p == '-') || (*p == ',') || (*p == '/') || (*p == ':'))
00912     {
00913       /*
00914         Parse xi value.
00915       */
00916       if ((*p == ',') || (*p == '/') || (*p == ':'))
00917         p++;
00918       q=p;
00919       value=StringToDouble(p,&p);
00920       if (p != q)
00921         {
00922           flags|=XiValue;
00923           if (*q == '-')
00924             flags|=XiNegative;
00925           geometry_info->xi=value;
00926         }
00927       while (isspace((int) ((unsigned char) *p)) != 0)
00928         p++;
00929       if ((*p == '+') || (*p == '-') || (*p == ',') || (*p == '/') ||
00930           (*p == ':'))
00931         {
00932           /*
00933             Parse psi value.
00934           */
00935           if ((*p == ',') || (*p == '/') || (*p == ':'))
00936             p++;
00937           q=p;
00938           value=StringToDouble(p,&p);
00939           if (p != q)
00940             {
00941               flags|=PsiValue;
00942               if (*q == '-')
00943                 flags|=PsiNegative;
00944               geometry_info->psi=value;
00945             }
00946         }
00947       while (isspace((int) ((unsigned char) *p)) != 0)
00948         p++;
00949       if ((*p == '+') || (*p == '-') || (*p == ',') || (*p == '/') ||
00950           (*p == ':'))
00951         {
00952           /*
00953             Parse chi value.
00954           */
00955           if ((*p == ',') || (*p == '/') || (*p == ':'))
00956             p++;
00957           q=p;
00958           value=StringToDouble(p,&p);
00959           if (p != q)
00960             {
00961               flags|=ChiValue;
00962               if (*q == '-')
00963                 flags|=ChiNegative;
00964               geometry_info->chi=value;
00965             }
00966         }
00967     }
00968   if (strchr(pedantic_geometry,':') != (char *) NULL)
00969     {
00970       /*
00971         Normalize sampling factor (e.g. 4:2:2 => 2x1).
00972       */
00973       geometry_info->rho/=geometry_info->sigma;
00974       geometry_info->sigma=1.0;
00975       if (geometry_info->xi == 0.0)
00976         geometry_info->sigma=2.0;
00977     }
00978   if (((flags & SigmaValue) == 0) && ((flags & XiValue) != 0) &&
00979       ((flags & PsiValue) == 0))
00980     {
00981       /*
00982         Support negative height values (e.g. 30x-20).
00983       */
00984       geometry_info->sigma=geometry_info->xi;
00985       geometry_info->xi=0.0;
00986       flags|=SigmaValue;
00987       flags&=(~XiValue);
00988     }
00989   return(flags);
00990 }
00991 
00992 /*
00993 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
00994 %                                                                             %
00995 %                                                                             %
00996 %                                                                             %
00997 %   P a r s e G r a v i t y G e o m e t r y                                   %
00998 %                                                                             %
00999 %                                                                             %
01000 %                                                                             %
01001 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
01002 %
01003 %  ParseGravityGeometry() returns a region as defined by the geometry string
01004 %  with respect to the given image page (canvas) dimensions and the images
01005 %  gravity setting.
01006 %
01007 %  This is typically used for specifing a area within a given image for
01008 %  cropping images to a smaller size, chopping out rows and or columns, or
01009 %  resizing and positioning overlay images.
01010 %
01011 %  Percentages are relative to image size and not page size, and are set to
01012 %  nearest integer (pixel) size.
01013 %
01014 %  The format of the ParseGravityGeometry method is:
01015 %
01016 %      MagickStatusType ParseGravityGeometry(Image *image,const char *geometry,
01017 %        RectangeInfo *region_info,ExceptionInfo *exception)
01018 %
01019 %  A description of each parameter follows:
01020 %
01021 %    o geometry:  The geometry string (e.g. "100x100+10+10").
01022 %
01023 %    o region_info: the region as defined by the geometry string with respect
01024 %      to the image dimensions and its gravity.
01025 %
01026 %    o exception: return any errors or warnings in this structure.
01027 %
01028 */
01029 MagickExport MagickStatusType ParseGravityGeometry(const Image *image,
01030   const char *geometry,RectangleInfo *region_info,ExceptionInfo *exception)
01031 {
01032   MagickStatusType
01033     flags;
01034 
01035   size_t
01036     height,
01037     width;
01038 
01039   SetGeometry(image,region_info);
01040   if (image->page.width != 0)
01041     region_info->width=image->page.width;
01042   if (image->page.height != 0)
01043     region_info->height=image->page.height;
01044   flags=ParseAbsoluteGeometry(geometry,region_info);
01045   if (flags == NoValue)
01046     {
01047       (void) ThrowMagickException(exception,GetMagickModule(),OptionError,
01048         "InvalidGeometry","`%s'",geometry);
01049       return(flags);
01050     }
01051   if ((flags & PercentValue) != 0)
01052     {
01053       GeometryInfo
01054         geometry_info;
01055 
01056       MagickStatusType
01057         status;
01058 
01059       PointInfo
01060         scale;
01061 
01062       /*
01063         Geometry is a percentage of the image size, not canvas size
01064       */
01065       if (image->gravity != UndefinedGravity)
01066         flags|=XValue | YValue;
01067       status=ParseGeometry(geometry,&geometry_info);
01068       scale.x=geometry_info.rho;
01069       if ((status & RhoValue) == 0)
01070         scale.x=100.0;
01071       scale.y=geometry_info.sigma;
01072       if ((status & SigmaValue) == 0)
01073         scale.y=scale.x;
01074       region_info->width=(size_t) floor((scale.x*image->columns/100.0)+0.5);
01075       region_info->height=(size_t) floor((scale.y*image->rows/100.0)+0.5);
01076     }
01077   /*
01078     Adjust offset according to gravity setting.
01079   */
01080   width=region_info->width;
01081   height=region_info->height;
01082   if (width == 0)
01083     region_info->width=image->page.width | image->columns;
01084   if (height == 0)
01085     region_info->height=image->page.height | image->rows;
01086   GravityAdjustGeometry(image->columns,image->rows,image->gravity,region_info);
01087   region_info->width=width;
01088   region_info->height=height;
01089   return(flags);
01090 }
01091 
01092 /*
01093 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
01094 %                                                                             %
01095 %                                                                             %
01096 %                                                                             %
01097 +   P a r s e M e t a G e o m e t r y                                         %
01098 %                                                                             %
01099 %                                                                             %
01100 %                                                                             %
01101 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
01102 %
01103 %  ParseMetaGeometry() is similar to GetGeometry() except the returned
01104 %  geometry is modified as determined by the meta characters:  %, !, <, >, @,
01105 %  and ^ in relation to image resizing.
01106 %
01107 %  Final image dimensions are adjusted so as to preserve the aspect ratio as
01108 %  much as possible, while generating a integer (pixel) size, and fitting the
01109 %  image within the specified geometry width and height.
01110 %
01111 %  Flags are interpreted...
01112 %     %   geometry size is given percentage of original image size
01113 %     !   do not try to preserve aspect ratio
01114 %     <   only enlarge images smaller that geometry
01115 %     >   only shrink images larger than geometry
01116 %     @   Fit image to contain at most this many pixels
01117 %     ^   Contain the given geometry given, (minimal dimensions given)
01118 %
01119 %  The format of the ParseMetaGeometry method is:
01120 %
01121 %      MagickStatusType ParseMetaGeometry(const char *geometry,ssize_t *x,
01122 %        ssize_t *y, size_t *width,size_t *height)
01123 %
01124 %  A description of each parameter follows:
01125 %
01126 %    o geometry:  The geometry string (e.g. "100x100+10+10").
01127 %
01128 %    o x,y:  The x and y offset, set according to the geometry specification.
01129 %
01130 %    o width,height:  The width and height of original image, modified by
01131 %      the given geometry specification.
01132 %
01133 */
01134 
01135 static inline size_t MagickMax(const size_t x,
01136   const size_t y)
01137 {
01138   if (x > y)
01139     return(x);
01140   return(y);
01141 }
01142 
01143 MagickExport MagickStatusType ParseMetaGeometry(const char *geometry,ssize_t *x,
01144   ssize_t *y,size_t *width,size_t *height)
01145 {
01146   GeometryInfo
01147     geometry_info;
01148 
01149   MagickStatusType
01150     flags;
01151 
01152   size_t
01153     former_height,
01154     former_width;
01155 
01156   /*
01157     Ensure the image geometry is valid.
01158   */
01159   assert(x != (ssize_t *) NULL);
01160   assert(y != (ssize_t *) NULL);
01161   assert(width != (size_t *) NULL);
01162   assert(height != (size_t *) NULL);
01163   if ((geometry == (char *) NULL) || (*geometry == '\0'))
01164     return(NoValue);
01165   (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",geometry);
01166   /*
01167     Parse geometry using GetGeometry.
01168   */
01169   SetGeometryInfo(&geometry_info);
01170   former_width=(*width);
01171   former_height=(*height);
01172   flags=GetGeometry(geometry,x,y,width,height);
01173   if ((flags & PercentValue) != 0)
01174     {
01175       MagickStatusType
01176         flags;
01177 
01178       PointInfo
01179         scale;
01180 
01181       /*
01182         Geometry is a percentage of the image size.
01183       */
01184       flags=ParseGeometry(geometry,&geometry_info);
01185       scale.x=geometry_info.rho;
01186       if ((flags & RhoValue) == 0)
01187         scale.x=100.0;
01188       scale.y=geometry_info.sigma;
01189       if ((flags & SigmaValue) == 0)
01190         scale.y=scale.x;
01191       *width=(size_t) floor(scale.x*former_width/100.0+0.5);
01192       if (*width == 0)
01193         *width=1;
01194       *height=(size_t) floor(scale.y*former_height/100.0+0.5);
01195       if (*height == 0)
01196         *height=1;
01197       former_width=(*width);
01198       former_height=(*height);
01199     }
01200   if (((flags & AspectValue) != 0) || ((*width == former_width) &&
01201       (*height == former_height)))
01202     {
01203       if ((flags & RhoValue) == 0)
01204         *width=former_width;
01205       if ((flags & SigmaValue) == 0)
01206         *height=former_height;
01207     }
01208   else
01209     {
01210       double
01211         scale_factor;
01212 
01213       /*
01214         Respect aspect ratio of the image.
01215       */
01216       if ((former_width == 0) || (former_height == 0))
01217         scale_factor=1.0;
01218       else
01219         if (((flags & RhoValue) != 0) && (flags & SigmaValue) != 0)
01220           {
01221             scale_factor=(double) *width/(double) former_width;
01222             if ((flags & MinimumValue) == 0)
01223               {
01224                 if (scale_factor > ((double) *height/(double) former_height))
01225                   scale_factor=(double) *height/(double) former_height;
01226               }
01227             else
01228               if (scale_factor < ((double) *height/(double) former_height))
01229                 scale_factor=(double) *height/(double) former_height;
01230           }
01231         else
01232           if ((flags & RhoValue) != 0)
01233             {
01234               scale_factor=(double) *width/(double) former_width;
01235               if (((flags & MinimumValue) != 0) &&
01236                   (scale_factor < ((double) *width/(double) former_height)))
01237                 scale_factor=(double) *width/(double) former_height;
01238             }
01239           else
01240             {
01241               scale_factor=(double) *height/(double) former_height;
01242               if (((flags & MinimumValue) != 0) &&
01243                   (scale_factor < ((double) *height/(double) former_width)))
01244                 scale_factor=(double) *height/(double) former_width;
01245             }
01246       *width=MagickMax((size_t) floor(scale_factor*former_width+0.5),1UL);
01247       *height=MagickMax((size_t) floor(scale_factor*former_height+0.5),1UL);
01248     }
01249   if ((flags & GreaterValue) != 0)
01250     {
01251       if (former_width < *width)
01252         *width=former_width;
01253       if (former_height < *height)
01254         *height=former_height;
01255     }
01256   if ((flags & LessValue) != 0)
01257     {
01258       if (former_width > *width)
01259         *width=former_width;
01260       if (former_height > *height)
01261         *height=former_height;
01262     }
01263   if ((flags & AreaValue) != 0)
01264     {
01265       double
01266         area,
01267         distance;
01268 
01269       PointInfo
01270         scale;
01271 
01272       /*
01273         Geometry is a maximum area in pixels.
01274       */
01275       (void) ParseGeometry(geometry,&geometry_info);
01276       area=geometry_info.rho;
01277       distance=sqrt((double) former_width*former_height);
01278       scale.x=former_width/(distance/sqrt((double) area));
01279       scale.y=former_height/(distance/sqrt((double) area));
01280       if ((scale.x < (double) *width) || (scale.y < (double) *height))
01281         {
01282           *width=(size_t) (former_width/(distance/sqrt(area))+0.5);
01283           *height=(size_t) (former_height/(distance/sqrt(area))+0.5);
01284         }
01285       former_width=(*width);
01286       former_height=(*height);
01287     }
01288   return(flags);
01289 }
01290 
01291 /*
01292 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
01293 %                                                                             %
01294 %                                                                             %
01295 %                                                                             %
01296 %   P a r s e P a g e G e o m e t r y                                         %
01297 %                                                                             %
01298 %                                                                             %
01299 %                                                                             %
01300 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
01301 %
01302 %  ParsePageGeometry() returns a region as defined by the geometry string with
01303 %  respect to the image page (canvas) dimensions.
01304 %
01305 %  WARNING: Percentage dimensions remain relative to the actual image
01306 %  dimensions, and not canvas dimensions.
01307 %
01308 %  The format of the ParsePageGeometry method is:
01309 %
01310 %      MagickStatusType ParsePageGeometry(const Image *image,
01311 %        const char *geometry,RectangeInfo *region_info,
01312 %        ExceptionInfo *exception)
01313 %
01314 %  A description of each parameter follows:
01315 %
01316 %    o geometry:  The geometry string (e.g. "100x100+10+10").
01317 %
01318 %    o region_info: the region as defined by the geometry string with
01319 %      respect to the image and its gravity.
01320 %
01321 %    o exception: return any errors or warnings in this structure.
01322 %
01323 */
01324 MagickExport MagickStatusType ParsePageGeometry(const Image *image,
01325   const char *geometry,RectangleInfo *region_info,ExceptionInfo *exception)
01326 {
01327   MagickStatusType
01328     flags;
01329 
01330   SetGeometry(image,region_info);
01331   if (image->page.width != 0)
01332     region_info->width=image->page.width;
01333   if (image->page.height != 0)
01334     region_info->height=image->page.height;
01335   flags=ParseAbsoluteGeometry(geometry,region_info);
01336   if (flags == NoValue)
01337     {
01338       (void) ThrowMagickException(exception,GetMagickModule(),OptionError,
01339         "InvalidGeometry","`%s'",geometry);
01340       return(flags);
01341     }
01342   if ((flags & PercentValue) != 0)
01343     {
01344       region_info->width=image->columns;
01345       region_info->height=image->rows;
01346     }
01347   flags=ParseMetaGeometry(geometry,&region_info->x,&region_info->y,
01348     &region_info->width,&region_info->height);
01349   return(flags);
01350 }
01351 
01352 /*
01353 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
01354 %                                                                             %
01355 %                                                                             %
01356 %                                                                             %
01357 %   P a r s e R e g i o n G e o m e t r y                                     %
01358 %                                                                             %
01359 %                                                                             %
01360 %                                                                             %
01361 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
01362 %
01363 %  ParseRegionGeometry() returns a region as defined by the geometry string
01364 %  with respect to the image dimensions and aspect ratio.
01365 %
01366 %  This is basically a wrapper around ParseMetaGeometry.  This is typically
01367 %  used to parse a geometry string to work out the final integer dimensions
01368 %  for image resizing.
01369 %
01370 %  The format of the ParseRegionGeometry method is:
01371 %
01372 %      MagickStatusType ParseRegionGeometry(const Image *image,
01373 %        const char *geometry,RectangeInfo *region_info,
01374 %        ExceptionInfo *exception)
01375 %
01376 %  A description of each parameter follows:
01377 %
01378 %    o geometry:  The geometry string (e.g. "100x100+10+10").
01379 %
01380 %    o region_info: the region as defined by the geometry string.
01381 %
01382 %    o exception: return any errors or warnings in this structure.
01383 %
01384 */
01385 MagickExport MagickStatusType ParseRegionGeometry(const Image *image,
01386   const char *geometry,RectangleInfo *region_info,ExceptionInfo *exception)
01387 {
01388   MagickStatusType
01389     flags;
01390 
01391   SetGeometry(image,region_info);
01392   flags=ParseMetaGeometry(geometry,&region_info->x,&region_info->y,
01393     &region_info->width,&region_info->height);
01394   if (flags == NoValue)
01395     (void) ThrowMagickException(exception,GetMagickModule(),OptionError,
01396       "InvalidGeometry","`%s'",geometry);
01397   return(flags);
01398 }
01399 
01400 /*
01401 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
01402 %                                                                             %
01403 %                                                                             %
01404 %                                                                             %
01405 %   S e t G e o m e t r y                                                     %
01406 %                                                                             %
01407 %                                                                             %
01408 %                                                                             %
01409 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
01410 %
01411 %  SetGeometry() sets the geometry to its default values.
01412 %
01413 %  The format of the SetGeometry method is:
01414 %
01415 %      SetGeometry(const Image *image,RectangleInfo *geometry)
01416 %
01417 %  A description of each parameter follows:
01418 %
01419 %    o image: the image.
01420 %
01421 %    o geometry: the geometry.
01422 %
01423 */
01424 MagickExport void SetGeometry(const Image *image,RectangleInfo *geometry)
01425 {
01426   assert(image != (Image *) NULL);
01427   assert(image->signature == MagickSignature);
01428   if (image->debug != MagickFalse)
01429     (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
01430   assert(geometry != (RectangleInfo *) NULL);
01431   (void) ResetMagickMemory(geometry,0,sizeof(*geometry));
01432   geometry->width=image->columns;
01433   geometry->height=image->rows;
01434 }
01435 
01436 /*
01437 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
01438 %                                                                             %
01439 %                                                                             %
01440 %                                                                             %
01441 %   S e t G e o m e t r y I n f o                                             %
01442 %                                                                             %
01443 %                                                                             %
01444 %                                                                             %
01445 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
01446 %
01447 %  SetGeometryInfo sets the GeometryInfo structure to its default values.
01448 %
01449 %  The format of the SetGeometryInfo method is:
01450 %
01451 %      SetGeometryInfo(GeometryInfo *geometry_info)
01452 %
01453 %  A description of each parameter follows:
01454 %
01455 %    o geometry_info: the geometry info structure.
01456 %
01457 */
01458 MagickExport void SetGeometryInfo(GeometryInfo *geometry_info)
01459 {
01460   assert(geometry_info != (GeometryInfo *) NULL);
01461   (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
01462   (void) ResetMagickMemory(geometry_info,0,sizeof(*geometry_info));
01463 }