/src/imagemagick/MagickCore/geometry.c
Line | Count | Source (jump to first uncovered line) |
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 | | % Cristy % |
17 | | % Copyright 1999 ImageMagick Studio LLC, a non-profit organization % |
18 | | % dedicated to making software imaging solutions freely available. % |
19 | | % % |
20 | | % You may not use this file except in compliance with the License. You may % |
21 | | % obtain a copy of the License at % |
22 | | % % |
23 | | % https://imagemagick.org/script/license.php % |
24 | | % % |
25 | | % Unless required by applicable law or agreed to in writing, software % |
26 | | % distributed under the License is distributed on an "AS IS" BASIS, % |
27 | | % WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. % |
28 | | % See the License for the specific language governing permissions and % |
29 | | % limitations under the License. % |
30 | | % % |
31 | | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% |
32 | | % |
33 | | % |
34 | | */ |
35 | | |
36 | | /* |
37 | | Include declarations. |
38 | | */ |
39 | | #include "MagickCore/studio.h" |
40 | | #include "MagickCore/constitute.h" |
41 | | #include "MagickCore/draw.h" |
42 | | #include "MagickCore/exception.h" |
43 | | #include "MagickCore/exception-private.h" |
44 | | #include "MagickCore/geometry.h" |
45 | | #include "MagickCore/geometry-private.h" |
46 | | #include "MagickCore/image-private.h" |
47 | | #include "MagickCore/memory_.h" |
48 | | #include "MagickCore/pixel-accessor.h" |
49 | | #include "MagickCore/string_.h" |
50 | | #include "MagickCore/string-private.h" |
51 | | #include "MagickCore/token.h" |
52 | | |
53 | | /* |
54 | | Define declarations. |
55 | | */ |
56 | | #define MagickPagesize(name,geometry) { name, sizeof(name)-1, geometry } |
57 | | |
58 | | /* |
59 | | Structure declarations. |
60 | | */ |
61 | | typedef struct _PageInfo |
62 | | { |
63 | | const char |
64 | | name[12]; |
65 | | |
66 | | size_t |
67 | | extent; |
68 | | |
69 | | const char |
70 | | geometry[10]; |
71 | | } PageInfo; |
72 | | |
73 | | static const PageInfo |
74 | | Pagesizes[] = |
75 | | { |
76 | | MagickPagesize("4x6", "288x432"), |
77 | | MagickPagesize("5x7", "360x504"), |
78 | | MagickPagesize("7x9", "504x648"), |
79 | | MagickPagesize("8x10", "576x720"), |
80 | | MagickPagesize("9x11", "648x792"), |
81 | | MagickPagesize("9x12", "648x864"), |
82 | | MagickPagesize("10x13", "720x936"), |
83 | | MagickPagesize("10x14", "720x1008"), |
84 | | MagickPagesize("11x17", "792x1224"), |
85 | | MagickPagesize("4A0", "4768x6741"), |
86 | | MagickPagesize("2A0", "3370x4768"), |
87 | | MagickPagesize("a0", "2384x3370"), |
88 | | MagickPagesize("a10", "74x105"), |
89 | | MagickPagesize("a1", "1684x2384"), |
90 | | MagickPagesize("a2", "1191x1684"), |
91 | | MagickPagesize("a3", "842x1191"), |
92 | | MagickPagesize("a4small", "595x842"), |
93 | | MagickPagesize("a4", "595x842"), |
94 | | MagickPagesize("a5", "420x595"), |
95 | | MagickPagesize("a6", "298x420"), |
96 | | MagickPagesize("a7", "210x298"), |
97 | | MagickPagesize("a8", "147x210"), |
98 | | MagickPagesize("a9", "105x147"), |
99 | | MagickPagesize("archa", "648x864"), |
100 | | MagickPagesize("archb", "864x1296"), |
101 | | MagickPagesize("archC", "1296x1728"), |
102 | | MagickPagesize("archd", "1728x2592"), |
103 | | MagickPagesize("arche", "2592x3456"), |
104 | | MagickPagesize("b0", "2920x4127"), |
105 | | MagickPagesize("b10", "91x127"), |
106 | | MagickPagesize("b1", "2064x2920"), |
107 | | MagickPagesize("b2", "1460x2064"), |
108 | | MagickPagesize("b3", "1032x1460"), |
109 | | MagickPagesize("b4", "729x1032"), |
110 | | MagickPagesize("b5", "516x729"), |
111 | | MagickPagesize("b6", "363x516"), |
112 | | MagickPagesize("b7", "258x363"), |
113 | | MagickPagesize("b8", "181x258"), |
114 | | MagickPagesize("b9", "127x181"), |
115 | | MagickPagesize("c0", "2599x3676"), |
116 | | MagickPagesize("c1", "1837x2599"), |
117 | | MagickPagesize("c2", "1298x1837"), |
118 | | MagickPagesize("c3", "918x1296"), |
119 | | MagickPagesize("c4", "649x918"), |
120 | | MagickPagesize("c5", "459x649"), |
121 | | MagickPagesize("c6", "323x459"), |
122 | | MagickPagesize("c7", "230x323"), |
123 | | MagickPagesize("csheet", "1224x1584"), |
124 | | MagickPagesize("dsheet", "1584x2448"), |
125 | | MagickPagesize("esheet", "2448x3168"), |
126 | | MagickPagesize("executive", "540x720"), |
127 | | MagickPagesize("flsa", "612x936"), |
128 | | MagickPagesize("flse", "612x936"), |
129 | | MagickPagesize("folio", "612x936"), |
130 | | MagickPagesize("halfletter", "396x612"), |
131 | | MagickPagesize("isob0", "2835x4008"), |
132 | | MagickPagesize("isob10", "88x125"), |
133 | | MagickPagesize("isob1", "2004x2835"), |
134 | | MagickPagesize("isob2", "1417x2004"), |
135 | | MagickPagesize("isob3", "1001x1417"), |
136 | | MagickPagesize("isob4", "709x1001"), |
137 | | MagickPagesize("isob5", "499x709"), |
138 | | MagickPagesize("isob6", "354x499"), |
139 | | MagickPagesize("isob7", "249x354"), |
140 | | MagickPagesize("isob8", "176x249"), |
141 | | MagickPagesize("isob9", "125x176"), |
142 | | MagickPagesize("jisb0", "1030x1456"), |
143 | | MagickPagesize("jisb1", "728x1030"), |
144 | | MagickPagesize("jisb2", "515x728"), |
145 | | MagickPagesize("jisb3", "364x515"), |
146 | | MagickPagesize("jisb4", "257x364"), |
147 | | MagickPagesize("jisb5", "182x257"), |
148 | | MagickPagesize("jisb6", "128x182"), |
149 | | MagickPagesize("ledger", "1224x792"), |
150 | | MagickPagesize("legal", "612x1008"), |
151 | | MagickPagesize("lettersmall", "612x792"), |
152 | | MagickPagesize("letter", "612x792"), |
153 | | MagickPagesize("monarch", "279x540"), |
154 | | MagickPagesize("quarto", "610x780"), |
155 | | MagickPagesize("statement", "396x612"), |
156 | | MagickPagesize("tabloid", "792x1224"), |
157 | | MagickPagesize("", "") |
158 | | }; |
159 | | |
160 | | /* |
161 | | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% |
162 | | % % |
163 | | % % |
164 | | % % |
165 | | % G e t G e o m e t r y % |
166 | | % % |
167 | | % % |
168 | | % % |
169 | | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% |
170 | | % |
171 | | % GetGeometry() parses a geometry specification and returns the width, |
172 | | % height, x, and y values. It also returns flags that indicates which |
173 | | % of the four values (width, height, x, y) were located in the string, and |
174 | | % whether the x or y values are negative. In addition, there are flags to |
175 | | % report any meta characters (%, !, <, or >). |
176 | | % |
177 | | % The value must form a proper geometry style specification of WxH+X+Y |
178 | | % of integers only, and values can not be separated by comma, colon, or |
179 | | % slash characters. See ParseGeometry() below. |
180 | | % |
181 | | % Offsets may be prefixed by multiple signs to make offset string |
182 | | % substitutions easier to handle from shell scripts. |
183 | | % For example: "-10-10", "-+10-+10", or "+-10+-10" will generate negative |
184 | | % offsets, while "+10+10", "++10++10", or "--10--10" will generate positive |
185 | | % offsets. |
186 | | % |
187 | | % The format of the GetGeometry method is: |
188 | | % |
189 | | % MagickStatusType GetGeometry(const char *geometry,ssize_t *x,ssize_t *y, |
190 | | % size_t *width,size_t *height) |
191 | | % |
192 | | % A description of each parameter follows: |
193 | | % |
194 | | % o geometry: The geometry. |
195 | | % |
196 | | % o x,y: The x and y offset as determined by the geometry specification. |
197 | | % |
198 | | % o width,height: The width and height as determined by the geometry |
199 | | % specification. |
200 | | % |
201 | | */ |
202 | | MagickExport MagickStatusType GetGeometry(const char *geometry,ssize_t *x, |
203 | | ssize_t *y,size_t *width,size_t *height) |
204 | 461k | { |
205 | 461k | char |
206 | 461k | *p, |
207 | 461k | pedantic_geometry[MagickPathExtent], |
208 | 461k | *q; |
209 | | |
210 | 461k | double |
211 | 461k | value; |
212 | | |
213 | 461k | int |
214 | 461k | c; |
215 | | |
216 | 461k | MagickStatusType |
217 | 461k | flags; |
218 | | |
219 | | /* |
220 | | Remove whitespace and meta characters from geometry specification. |
221 | | */ |
222 | 461k | flags=NoValue; |
223 | 461k | if ((geometry == (char *) NULL) || (*geometry == '\0')) |
224 | 2.16k | return(flags); |
225 | 459k | if (strlen(geometry) >= (MagickPathExtent-1)) |
226 | 13 | return(flags); |
227 | 459k | (void) CopyMagickString(pedantic_geometry,geometry,MagickPathExtent); |
228 | 7.76M | for (p=pedantic_geometry; *p != '\0'; ) |
229 | 7.31M | { |
230 | 7.31M | if (isspace((int) ((unsigned char) *p)) != 0) |
231 | 104k | { |
232 | 104k | (void) CopyMagickString(p,p+1,MagickPathExtent); |
233 | 104k | continue; |
234 | 104k | } |
235 | 7.21M | c=(int) *p; |
236 | 7.21M | switch (c) |
237 | 7.21M | { |
238 | 58.4k | case '%': |
239 | 58.4k | { |
240 | 58.4k | flags|=PercentValue; |
241 | 58.4k | (void) CopyMagickString(p,p+1,MagickPathExtent); |
242 | 58.4k | break; |
243 | 0 | } |
244 | 52.1k | case '!': |
245 | 52.1k | { |
246 | 52.1k | flags|=AspectValue; |
247 | 52.1k | (void) CopyMagickString(p,p+1,MagickPathExtent); |
248 | 52.1k | break; |
249 | 0 | } |
250 | 37.6k | case '<': |
251 | 37.6k | { |
252 | 37.6k | flags|=LessValue; |
253 | 37.6k | (void) CopyMagickString(p,p+1,MagickPathExtent); |
254 | 37.6k | break; |
255 | 0 | } |
256 | 49.8k | case '>': |
257 | 49.8k | { |
258 | 49.8k | flags|=GreaterValue; |
259 | 49.8k | (void) CopyMagickString(p,p+1,MagickPathExtent); |
260 | 49.8k | break; |
261 | 0 | } |
262 | 33.9k | case '#': |
263 | 33.9k | { |
264 | 33.9k | flags|=MaximumValue; |
265 | 33.9k | (void) CopyMagickString(p,p+1,MagickPathExtent); |
266 | 33.9k | break; |
267 | 0 | } |
268 | 20.6k | case '^': |
269 | 20.6k | { |
270 | 20.6k | flags|=MinimumValue; |
271 | 20.6k | (void) CopyMagickString(p,p+1,MagickPathExtent); |
272 | 20.6k | break; |
273 | 0 | } |
274 | 36.5k | case '@': |
275 | 36.5k | { |
276 | 36.5k | flags|=AreaValue; |
277 | 36.5k | (void) CopyMagickString(p,p+1,MagickPathExtent); |
278 | 36.5k | break; |
279 | 0 | } |
280 | 25.6k | case '(': |
281 | 64.5k | case ')': |
282 | 64.5k | { |
283 | 64.5k | (void) CopyMagickString(p,p+1,MagickPathExtent); |
284 | 64.5k | break; |
285 | 25.6k | } |
286 | 215k | case 'x': |
287 | 245k | case 'X': |
288 | 245k | { |
289 | 245k | flags|=SeparatorValue; |
290 | 245k | p++; |
291 | 245k | break; |
292 | 215k | } |
293 | 130k | case '-': |
294 | 160k | case ',': |
295 | 747k | case '+': |
296 | 3.96M | case '0': |
297 | 4.40M | case '1': |
298 | 4.74M | case '2': |
299 | 4.91M | case '3': |
300 | 5.20M | case '4': |
301 | 5.42M | case '5': |
302 | 5.59M | case '6': |
303 | 5.80M | case '7': |
304 | 5.95M | case '8': |
305 | 6.11M | case '9': |
306 | 6.11M | case 215: |
307 | 6.14M | case 'e': |
308 | 6.17M | case 'E': |
309 | 6.17M | { |
310 | 6.17M | p++; |
311 | 6.17M | break; |
312 | 6.14M | } |
313 | 386k | case '.': |
314 | 386k | { |
315 | 386k | p++; |
316 | 386k | flags|=DecimalValue; |
317 | 386k | break; |
318 | 6.14M | } |
319 | 43.3k | case ':': |
320 | 43.3k | { |
321 | 43.3k | p++; |
322 | 43.3k | flags|=AspectRatioValue; |
323 | 43.3k | break; |
324 | 6.14M | } |
325 | 9.61k | default: |
326 | 9.61k | return(flags); |
327 | 7.21M | } |
328 | 7.21M | } |
329 | | /* |
330 | | Parse width, height, x, and y. |
331 | | */ |
332 | 449k | p=pedantic_geometry; |
333 | 449k | if (*p == '\0') |
334 | 2.38k | return(flags); |
335 | 447k | q=p; |
336 | 447k | value=StringToDouble(p,&q); |
337 | 447k | (void) value; |
338 | 447k | if (LocaleNCompare(p,"0x",2) == 0) |
339 | 47.9k | value=(double) strtol(p,&q,10); |
340 | 447k | if ((*p != '+') && (*p != '-')) |
341 | 254k | { |
342 | 254k | c=(int) ((unsigned char) *q); |
343 | 254k | if ((c == 215) || (*q == 'x') || (*q == 'X') || (*q == ':') || |
344 | 254k | (*q == '\0')) |
345 | 251k | { |
346 | | /* |
347 | | Parse width. |
348 | | */ |
349 | 251k | q=p; |
350 | 251k | if (width != (size_t *) NULL) |
351 | 251k | { |
352 | 251k | if (LocaleNCompare(p,"0x",2) == 0) |
353 | 47.9k | *width=(size_t) strtol(p,&p,10); |
354 | 203k | else |
355 | 203k | *width=CastDoubleToSizeT(StringToDouble(p,&p)+0.5); |
356 | 251k | } |
357 | 251k | if (p != q) |
358 | 229k | flags|=WidthValue; |
359 | 251k | } |
360 | 254k | } |
361 | 447k | if ((*p != '+') && (*p != '-')) |
362 | 254k | { |
363 | 254k | c=(int) ((unsigned char) *p); |
364 | 254k | if ((c == 215) || (*p == 'x') || (*p == 'X') || (*p == ':')) |
365 | 230k | { |
366 | 230k | p++; |
367 | 230k | if ((*p != '+') && (*p != '-')) |
368 | 215k | { |
369 | | /* |
370 | | Parse height. |
371 | | */ |
372 | 215k | q=p; |
373 | 215k | if (height != (size_t *) NULL) |
374 | 215k | *height=CastDoubleToSizeT(StringToDouble(p,&p)+0.5); |
375 | 215k | if (p != q) |
376 | 205k | flags|=HeightValue; |
377 | 215k | } |
378 | 230k | } |
379 | 254k | } |
380 | 447k | if ((*p == '+') || (*p == '-')) |
381 | 319k | { |
382 | | /* |
383 | | Parse x value. |
384 | | */ |
385 | 669k | while ((*p == '+') || (*p == '-')) |
386 | 349k | { |
387 | 349k | if (*p == '-') |
388 | 51.7k | flags^=XNegative; /* negate sign */ |
389 | 349k | p++; |
390 | 349k | } |
391 | 319k | q=p; |
392 | 319k | if (x != (ssize_t *) NULL) |
393 | 319k | *x=CastDoubleToSsizeT(StringToDouble(p,&p)); |
394 | 319k | if (p != q) |
395 | 305k | { |
396 | 305k | flags|=XValue; |
397 | 305k | if (((flags & XNegative) != 0) && (x != (ssize_t *) NULL)) |
398 | 26.2k | *x=CastDoubleToSsizeT(-1.0**x); |
399 | 305k | } |
400 | 319k | } |
401 | 447k | if ((*p == '+') || (*p == '-')) |
402 | 287k | { |
403 | | /* |
404 | | Parse y value. |
405 | | */ |
406 | 598k | while ((*p == '+') || (*p == '-')) |
407 | 311k | { |
408 | 311k | if (*p == '-') |
409 | 34.5k | flags^=YNegative; /* negate sign */ |
410 | 311k | p++; |
411 | 311k | } |
412 | 287k | q=p; |
413 | 287k | if (y != (ssize_t *) NULL) |
414 | 287k | *y=CastDoubleToSsizeT(StringToDouble(p,&p)); |
415 | 287k | if (p != q) |
416 | 279k | { |
417 | 279k | flags|=YValue; |
418 | 279k | if (((flags & YNegative) != 0) && (y != (ssize_t *) NULL)) |
419 | 18.9k | *y=CastDoubleToSsizeT(-1.0**y); |
420 | 279k | } |
421 | 287k | } |
422 | 447k | if ((flags & PercentValue) != 0) |
423 | 33.5k | { |
424 | 33.5k | if (((flags & SeparatorValue) == 0) && ((flags & HeightValue) == 0)) |
425 | 15.7k | { |
426 | 15.7k | if ((height != (size_t *) NULL) && (width != (size_t *) NULL)) |
427 | 15.7k | *height=(*width); |
428 | 15.7k | flags|=HeightValue; |
429 | 15.7k | } |
430 | 33.5k | if (((flags & SeparatorValue) != 0) && ((flags & WidthValue) == 0) && |
431 | 33.5k | (height != (size_t *) NULL) && (width != (size_t *) NULL)) |
432 | 5.51k | *width=(*height); |
433 | 33.5k | } |
434 | | #if 0 |
435 | | /* Debugging Geometry */ |
436 | | (void) fprintf(stderr,"GetGeometry...\n"); |
437 | | (void) fprintf(stderr,"Input: %s\n",geometry); |
438 | | (void) fprintf(stderr,"Flags: %c %c %s %s\n", |
439 | | (flags & WidthValue) ? 'W' : ' ',(flags & HeightValue) ? 'H' : ' ', |
440 | | (flags & XValue) ? ((flags & XNegative) ? "-X" : "+X") : " ", |
441 | | (flags & YValue) ? ((flags & YNegative) ? "-Y" : "+Y") : " "); |
442 | | (void) fprintf(stderr,"Geometry: %ldx%ld%+ld%+ld\n",(long) *width,(long) |
443 | | *height,(long) *x,(long) *y); |
444 | | #endif |
445 | 447k | return(flags); |
446 | 449k | } |
447 | | |
448 | | /* |
449 | | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% |
450 | | % % |
451 | | % % |
452 | | % % |
453 | | % G e t P a g e G e o m e t r y % |
454 | | % % |
455 | | % % |
456 | | % % |
457 | | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% |
458 | | % |
459 | | % GetPageGeometry() replaces any page mnemonic with the equivalent size in |
460 | | % picas. |
461 | | % |
462 | | % The format of the GetPageGeometry method is: |
463 | | % |
464 | | % char *GetPageGeometry(const char *page_geometry) |
465 | | % |
466 | | % A description of each parameter follows. |
467 | | % |
468 | | % o page_geometry: Specifies a pointer to an array of characters. The |
469 | | % string is either a Postscript page name (e.g. A4) or a postscript page |
470 | | % geometry (e.g. 612x792+36+36). |
471 | | % |
472 | | */ |
473 | | MagickExport char *GetPageGeometry(const char *page_geometry) |
474 | 64.7k | { |
475 | 64.7k | char |
476 | 64.7k | page[MagickPathExtent]; |
477 | | |
478 | 64.7k | ssize_t |
479 | 64.7k | i; |
480 | | |
481 | 64.7k | assert(page_geometry != (char *) NULL); |
482 | 64.7k | if (IsEventLogging() != MagickFalse) |
483 | 0 | (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",page_geometry); |
484 | 64.7k | (void) CopyMagickString(page,page_geometry,MagickPathExtent); |
485 | 4.15M | for (i=0; *Pagesizes[i].name != '\0'; i++) |
486 | 4.11M | { |
487 | 4.11M | int |
488 | 4.11M | status; |
489 | | |
490 | 4.11M | if (Pagesizes[i].extent == 0) |
491 | 0 | break; /* sentinel */ |
492 | 4.11M | status=LocaleNCompare(Pagesizes[i].name,page_geometry,Pagesizes[i].extent); |
493 | 4.11M | if (status == 0) |
494 | 20.1k | { |
495 | 20.1k | MagickStatusType |
496 | 20.1k | flags; |
497 | | |
498 | 20.1k | RectangleInfo |
499 | 20.1k | geometry; |
500 | | |
501 | | /* |
502 | | Replace mnemonic with the equivalent size in dots-per-inch. |
503 | | */ |
504 | 20.1k | (void) FormatLocaleString(page,MagickPathExtent,"%s%.80s", |
505 | 20.1k | Pagesizes[i].geometry,page_geometry+Pagesizes[i].extent); |
506 | 20.1k | flags=GetGeometry(page,&geometry.x,&geometry.y,&geometry.width, |
507 | 20.1k | &geometry.height); |
508 | 20.1k | if ((flags & GreaterValue) == 0) |
509 | 14.8k | (void) ConcatenateMagickString(page,">",MagickPathExtent); |
510 | 20.1k | break; |
511 | 20.1k | } |
512 | 4.11M | } |
513 | 64.7k | return(AcquireString(page)); |
514 | 64.7k | } |
515 | | |
516 | | /* |
517 | | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% |
518 | | % % |
519 | | % % |
520 | | % % |
521 | | % G r a v i t y A d j u s t G e o m e t r y % |
522 | | % % |
523 | | % % |
524 | | % % |
525 | | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% |
526 | | % |
527 | | % GravityAdjustGeometry() adjusts the offset of a region with regard to the |
528 | | % given: width, height and gravity; against which it is positioned. |
529 | | % |
530 | | % The region should also have an appropriate width and height to correctly |
531 | | % set the right offset of the top left corner of the region. |
532 | | % |
533 | | % The format of the GravityAdjustGeometry method is: |
534 | | % |
535 | | % void GravityAdjustGeometry(const size_t width, const size_t height, |
536 | | % const GravityType gravity,RectangleInfo *region); |
537 | | % |
538 | | % A description of each parameter follows: |
539 | | % |
540 | | % o width, height: the larger area the region is relative to |
541 | | % |
542 | | % o gravity: the edge/corner the current offset is relative to |
543 | | % |
544 | | % o region: The region requiring a offset adjustment relative to gravity |
545 | | % |
546 | | */ |
547 | | MagickExport void GravityAdjustGeometry(const size_t width, |
548 | | const size_t height,const GravityType gravity,RectangleInfo *region) |
549 | 8.82k | { |
550 | 8.82k | if (region->height == 0) |
551 | 1.42k | region->height=height; |
552 | 8.82k | if (region->width == 0) |
553 | 1.42k | region->width=width; |
554 | 8.82k | switch (gravity) |
555 | 8.82k | { |
556 | 0 | case NorthEastGravity: |
557 | 713 | case EastGravity: |
558 | 713 | case SouthEastGravity: |
559 | 713 | { |
560 | 713 | region->x=CastDoubleToSsizeT((double) width-region->width-region->x); |
561 | 713 | break; |
562 | 713 | } |
563 | 1.06k | case NorthGravity: |
564 | 1.78k | case SouthGravity: |
565 | 1.78k | case CenterGravity: |
566 | 1.78k | { |
567 | 1.78k | region->x=CastDoubleToSsizeT((double) width/2.0-region->width/2.0+ |
568 | 1.78k | region->x); |
569 | 1.78k | break; |
570 | 1.78k | } |
571 | 5.62k | case ForgetGravity: |
572 | 5.62k | case NorthWestGravity: |
573 | 6.33k | case WestGravity: |
574 | 6.33k | case SouthWestGravity: |
575 | 6.33k | default: |
576 | 6.33k | break; |
577 | 8.82k | } |
578 | 8.82k | switch (gravity) |
579 | 8.82k | { |
580 | 0 | case SouthWestGravity: |
581 | 713 | case SouthGravity: |
582 | 713 | case SouthEastGravity: |
583 | 713 | { |
584 | 713 | region->y=CastDoubleToSsizeT((double) height-region->height-region->y); |
585 | 713 | break; |
586 | 713 | } |
587 | 713 | case EastGravity: |
588 | 1.42k | case WestGravity: |
589 | 1.42k | case CenterGravity: |
590 | 1.42k | { |
591 | 1.42k | region->y=CastDoubleToSsizeT((double) height/2.0-region->height/2.0+ |
592 | 1.42k | region->y); |
593 | 1.42k | break; |
594 | 1.42k | } |
595 | 5.62k | case ForgetGravity: |
596 | 5.62k | case NorthWestGravity: |
597 | 6.69k | case NorthGravity: |
598 | 6.69k | case NorthEastGravity: |
599 | 6.69k | default: |
600 | 6.69k | break; |
601 | 8.82k | } |
602 | 8.82k | return; |
603 | 8.82k | } |
604 | | |
605 | | /* |
606 | | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% |
607 | | % % |
608 | | % % |
609 | | % % |
610 | | + I s G e o m e t r y % |
611 | | % % |
612 | | % % |
613 | | % % |
614 | | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% |
615 | | % |
616 | | % IsGeometry() returns MagickTrue if the geometry specification is valid. |
617 | | % Examples are 100, 100x200, x200, 100x200+10+20, +10+20, 200%, 200x200!, etc. |
618 | | % |
619 | | % The format of the IsGeometry method is: |
620 | | % |
621 | | % MagickBooleanType IsGeometry(const char *geometry) |
622 | | % |
623 | | % A description of each parameter follows: |
624 | | % |
625 | | % o geometry: This string is the geometry specification. |
626 | | % |
627 | | */ |
628 | | MagickExport MagickBooleanType IsGeometry(const char *geometry) |
629 | 213k | { |
630 | 213k | GeometryInfo |
631 | 213k | geometry_info; |
632 | | |
633 | 213k | MagickStatusType |
634 | 213k | flags; |
635 | | |
636 | 213k | if (geometry == (const char *) NULL) |
637 | 0 | return(MagickFalse); |
638 | 213k | flags=ParseGeometry(geometry,&geometry_info); |
639 | 213k | return(flags != NoValue ? MagickTrue : MagickFalse); |
640 | 213k | } |
641 | | |
642 | | /* |
643 | | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% |
644 | | % % |
645 | | % % |
646 | | % % |
647 | | + I s S c e n e G e o m e t r y % |
648 | | % % |
649 | | % % |
650 | | % % |
651 | | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% |
652 | | % |
653 | | % IsSceneGeometry() returns MagickTrue if the geometry is a valid scene |
654 | | % specification (e.g. [1], [1-9], [1,7,4]). |
655 | | % |
656 | | % The format of the IsSceneGeometry method is: |
657 | | % |
658 | | % MagickBooleanType IsSceneGeometry(const char *geometry, |
659 | | % const MagickBooleanType pedantic) |
660 | | % |
661 | | % A description of each parameter follows: |
662 | | % |
663 | | % o geometry: This string is the geometry specification. |
664 | | % |
665 | | % o pedantic: A value other than 0 invokes a more restrictive set of |
666 | | % conditions for a valid specification (e.g. [1], [1-4], [4-1]). |
667 | | % |
668 | | */ |
669 | | MagickExport MagickBooleanType IsSceneGeometry(const char *geometry, |
670 | | const MagickBooleanType pedantic) |
671 | 646k | { |
672 | 646k | char |
673 | 646k | *p; |
674 | | |
675 | 646k | double |
676 | 646k | value; |
677 | | |
678 | 646k | if (geometry == (const char *) NULL) |
679 | 400k | return(MagickFalse); |
680 | 246k | p=(char *) geometry; |
681 | 246k | value=StringToDouble(geometry,&p); |
682 | 246k | if (IsNaN(value) != 0) |
683 | 310 | return(MagickFalse); |
684 | 245k | if (value > (double) MAGICK_SSIZE_MAX) |
685 | 8.23k | return(MagickFalse); |
686 | 237k | if (value < (double) MAGICK_SSIZE_MIN) |
687 | 893 | return(MagickFalse); |
688 | 236k | if (p == geometry) |
689 | 124k | return(MagickFalse); |
690 | 112k | if (strspn(geometry,"0123456789-, ") != strlen(geometry)) |
691 | 78.9k | return(MagickFalse); |
692 | 33.5k | if ((pedantic != MagickFalse) && (strchr(geometry,',') != (char *) NULL)) |
693 | 0 | return(MagickFalse); |
694 | 33.5k | return(MagickTrue); |
695 | 33.5k | } |
696 | | |
697 | | /* |
698 | | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% |
699 | | % % |
700 | | % % |
701 | | % % |
702 | | + L i s t P a g e s i z e s % |
703 | | % % |
704 | | % % |
705 | | % % |
706 | | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% |
707 | | % |
708 | | % ListPagesizes() lists the pagesizes and their associated geometry. |
709 | | % |
710 | | % The format of the ListPagesizes method is: |
711 | | % |
712 | | % MagickBooleanType ListPagesizes(FILE *file,ExceptionInfo *exception) |
713 | | % |
714 | | % A description of each parameter follows. |
715 | | % |
716 | | % o file: An pointer to the output FILE. |
717 | | % |
718 | | % o exception: return any errors or warnings in this structure. |
719 | | % |
720 | | */ |
721 | | MagickExport MagickBooleanType ListPagesizes(FILE *file, |
722 | | ExceptionInfo *magick_unused(exception)) |
723 | 0 | { |
724 | 0 | #define MaxMagickSpaces ((int) sizeof(Pagesizes[0].name)) |
725 | |
|
726 | 0 | const char |
727 | 0 | *spacer = " "; |
728 | |
|
729 | 0 | ssize_t |
730 | 0 | i; |
731 | |
|
732 | 0 | magick_unreferenced(exception); |
733 | 0 | if (file == (FILE *) NULL) |
734 | 0 | file=stdout; |
735 | 0 | (void) FormatLocaleFile(file,"\nPagesize Geometry \n"); |
736 | 0 | (void) FormatLocaleFile(file,"---------------------\n"); |
737 | 0 | for (i=0; *Pagesizes[i].name != '\0'; i++) |
738 | 0 | (void) FormatLocaleFile(file,"%s%.*s%s\n",Pagesizes[i].name, |
739 | 0 | MaxMagickSpaces-(int) Pagesizes[i].extent,spacer,Pagesizes[i].geometry); |
740 | 0 | return(MagickTrue); |
741 | 0 | } |
742 | | |
743 | | /* |
744 | | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% |
745 | | % % |
746 | | % % |
747 | | % % |
748 | | % P a r s e A b s o l u t e G e o m e t r y % |
749 | | % % |
750 | | % % |
751 | | % % |
752 | | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% |
753 | | % |
754 | | % ParseAbsoluteGeometry() returns a region as defined by the geometry string, |
755 | | % without any modification by percentages or gravity. |
756 | | % |
757 | | % It currently just a wrapper around GetGeometry(), but may be expanded in |
758 | | % the future to handle other positioning information. |
759 | | % |
760 | | % The format of the ParseAbsoluteGeometry method is: |
761 | | % |
762 | | % MagickStatusType ParseAbsoluteGeometry(const char *geometry, |
763 | | % RectangleInfo *region_info) |
764 | | % |
765 | | % A description of each parameter follows: |
766 | | % |
767 | | % o geometry: The geometry string (e.g. "100x100+10+10"). |
768 | | % |
769 | | % o region_info: the region as defined by the geometry string. |
770 | | % |
771 | | */ |
772 | | MagickExport MagickStatusType ParseAbsoluteGeometry(const char *geometry, |
773 | | RectangleInfo *region_info) |
774 | 333k | { |
775 | 333k | MagickStatusType |
776 | 333k | flags; |
777 | | |
778 | 333k | flags=GetGeometry(geometry,®ion_info->x,®ion_info->y, |
779 | 333k | ®ion_info->width,®ion_info->height); |
780 | 333k | return(flags); |
781 | 333k | } |
782 | | |
783 | | /* |
784 | | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% |
785 | | % % |
786 | | % % |
787 | | % % |
788 | | % P a r s e A f f i n e G e o m e t r y % |
789 | | % % |
790 | | % % |
791 | | % % |
792 | | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% |
793 | | % |
794 | | % ParseAffineGeometry() returns an affine matrix as defined by a string of 4 |
795 | | % to 6 comma/space separated floating point values. |
796 | | % |
797 | | % The affine matrix determinant is checked for validity of the values. |
798 | | % |
799 | | % The format of the ParseAffineGeometry method is: |
800 | | % |
801 | | % MagickStatusType ParseAffineGeometry(const char *geometry, |
802 | | % AffineMatrix *affine_matrix,ExceptionInfo *exception) |
803 | | % |
804 | | % A description of each parameter follows: |
805 | | % |
806 | | % o geometry: The geometry string (e.g. "1.0,0.0,0.0,1.0,3.2,1.2"). |
807 | | % |
808 | | % o affine_matrix: the affine matrix as defined by the geometry string. |
809 | | % |
810 | | % o exception: return any errors or warnings in this structure. |
811 | | % |
812 | | */ |
813 | | MagickExport MagickStatusType ParseAffineGeometry(const char *geometry, |
814 | | AffineMatrix *affine_matrix,ExceptionInfo *exception) |
815 | 0 | { |
816 | 0 | char |
817 | 0 | token[MagickPathExtent]; |
818 | |
|
819 | 0 | const char |
820 | 0 | *p; |
821 | |
|
822 | 0 | double |
823 | 0 | determinant; |
824 | |
|
825 | 0 | MagickStatusType |
826 | 0 | flags; |
827 | |
|
828 | 0 | ssize_t |
829 | 0 | i; |
830 | |
|
831 | 0 | GetAffineMatrix(affine_matrix); |
832 | 0 | flags=NoValue; |
833 | 0 | p=(char *) geometry; |
834 | 0 | for (i=0; (*p != '\0') && (i < 6); i++) |
835 | 0 | { |
836 | 0 | (void) GetNextToken(p,&p,MagickPathExtent,token); |
837 | 0 | if (*token == ',') |
838 | 0 | (void) GetNextToken(p,&p,MagickPathExtent,token); |
839 | 0 | switch (i) |
840 | 0 | { |
841 | 0 | case 0: |
842 | 0 | { |
843 | 0 | affine_matrix->sx=StringToDouble(token,(char **) NULL); |
844 | 0 | break; |
845 | 0 | } |
846 | 0 | case 1: |
847 | 0 | { |
848 | 0 | affine_matrix->rx=StringToDouble(token,(char **) NULL); |
849 | 0 | break; |
850 | 0 | } |
851 | 0 | case 2: |
852 | 0 | { |
853 | 0 | affine_matrix->ry=StringToDouble(token,(char **) NULL); |
854 | 0 | break; |
855 | 0 | } |
856 | 0 | case 3: |
857 | 0 | { |
858 | 0 | affine_matrix->sy=StringToDouble(token,(char **) NULL); |
859 | 0 | break; |
860 | 0 | } |
861 | 0 | case 4: |
862 | 0 | { |
863 | 0 | affine_matrix->tx=StringToDouble(token,(char **) NULL); |
864 | 0 | flags|=XValue; |
865 | 0 | break; |
866 | 0 | } |
867 | 0 | case 5: |
868 | 0 | { |
869 | 0 | affine_matrix->ty=StringToDouble(token,(char **) NULL); |
870 | 0 | flags|=YValue; |
871 | 0 | break; |
872 | 0 | } |
873 | 0 | } |
874 | 0 | } |
875 | 0 | determinant=(affine_matrix->sx*affine_matrix->sy-affine_matrix->rx* |
876 | 0 | affine_matrix->ry); |
877 | 0 | if (fabs(determinant) < MagickEpsilon) |
878 | 0 | (void) ThrowMagickException(exception,GetMagickModule(),OptionError, |
879 | 0 | "InvalidArgument","'%s' : 'Indeterminate Matrix'",geometry); |
880 | 0 | return(flags); |
881 | 0 | } |
882 | | |
883 | | /* |
884 | | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% |
885 | | % % |
886 | | % % |
887 | | % % |
888 | | % P a r s e G e o m e t r y % |
889 | | % % |
890 | | % % |
891 | | % % |
892 | | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% |
893 | | % |
894 | | % ParseGeometry() parses a geometry specification and returns the sigma, |
895 | | % rho, xi, and psi values. It also returns flags that indicates which |
896 | | % of the four values (sigma, rho, xi, psi) were located in the string, and |
897 | | % whether the xi or pi values are negative. |
898 | | % |
899 | | % In addition, it reports if there are any of meta characters (%, !, <, >, @, |
900 | | % and ^) flags present. It does not report the location of the percentage |
901 | | % relative to the values. |
902 | | % |
903 | | % Values may also be separated by commas, colons, or slashes, and offsets. |
904 | | % Chroma subsampling definitions have to be in the form of a:b:c. Offsets may |
905 | | % be prefixed by multiple signs to make offset string substitutions easier to |
906 | | % handle from shell scripts. For example: "-10-10", "-+10-+10", or "+-10+-10" |
907 | | % will generate negative offsets, while "+10+10", "++10++10", or "--10--10" |
908 | | % will generate positive offsets. |
909 | | % |
910 | | % The format of the ParseGeometry method is: |
911 | | % |
912 | | % MagickStatusType ParseGeometry(const char *geometry, |
913 | | % GeometryInfo *geometry_info) |
914 | | % |
915 | | % A description of each parameter follows: |
916 | | % |
917 | | % o geometry: The geometry string (e.g. "100x100+10+10"). |
918 | | % |
919 | | % o geometry_info: returns the parsed width/height/x/y in this structure. |
920 | | % |
921 | | */ |
922 | | MagickExport MagickStatusType ParseGeometry(const char *geometry, |
923 | | GeometryInfo *geometry_info) |
924 | 505k | { |
925 | 505k | char |
926 | 505k | *p, |
927 | 505k | pedantic_geometry[MagickPathExtent], |
928 | 505k | *q; |
929 | | |
930 | 505k | double |
931 | 505k | value; |
932 | | |
933 | 505k | GeometryInfo |
934 | 505k | coordinate; |
935 | | |
936 | 505k | int |
937 | 505k | c; |
938 | | |
939 | 505k | MagickStatusType |
940 | 505k | flags; |
941 | | |
942 | | /* |
943 | | Remove whitespaces meta characters from geometry specification. |
944 | | */ |
945 | 505k | assert(geometry_info != (GeometryInfo *) NULL); |
946 | 505k | (void) memset(geometry_info,0,sizeof(*geometry_info)); |
947 | 505k | flags=NoValue; |
948 | 505k | if ((geometry == (char *) NULL) || (*geometry == '\0')) |
949 | 7.97k | return(flags); |
950 | 497k | if (strlen(geometry) >= (MagickPathExtent-1)) |
951 | 193 | return(flags); |
952 | 497k | c=MagickSscanf(geometry,"%lf%*[ ,]%lf%*[ ,]%lf%*[ ,]%lf",&coordinate.rho, |
953 | 497k | &coordinate.sigma,&coordinate.xi,&coordinate.psi); |
954 | 497k | if (c == 4) |
955 | 2.41k | { |
956 | | /* |
957 | | Special case: coordinate (e.g. 0,0 255,255). |
958 | | */ |
959 | 2.41k | geometry_info->rho=coordinate.rho; |
960 | 2.41k | geometry_info->sigma=coordinate.sigma; |
961 | 2.41k | geometry_info->xi=coordinate.xi; |
962 | 2.41k | geometry_info->psi=coordinate.psi; |
963 | 2.41k | flags|=RhoValue | SigmaValue | XiValue | PsiValue; |
964 | 2.41k | return(flags); |
965 | 2.41k | } |
966 | 494k | (void) CopyMagickString(pedantic_geometry,geometry,MagickPathExtent); |
967 | 7.47M | for (p=pedantic_geometry; *p != '\0'; ) |
968 | 7.06M | { |
969 | 7.06M | c=(int) ((unsigned char) *p); |
970 | 7.06M | if (isspace((int) ((unsigned char) c)) != 0) |
971 | 185k | { |
972 | 185k | (void) CopyMagickString(p,p+1,MagickPathExtent); |
973 | 185k | continue; |
974 | 185k | } |
975 | 6.87M | switch (c) |
976 | 6.87M | { |
977 | 96.9k | case '%': |
978 | 96.9k | { |
979 | 96.9k | flags|=PercentValue; |
980 | 96.9k | (void) CopyMagickString(p,p+1,MagickPathExtent); |
981 | 96.9k | break; |
982 | 0 | } |
983 | 39.5k | case '!': |
984 | 39.5k | { |
985 | 39.5k | flags|=AspectValue; |
986 | 39.5k | (void) CopyMagickString(p,p+1,MagickPathExtent); |
987 | 39.5k | break; |
988 | 0 | } |
989 | 62.4k | case '<': |
990 | 62.4k | { |
991 | 62.4k | flags|=LessValue; |
992 | 62.4k | (void) CopyMagickString(p,p+1,MagickPathExtent); |
993 | 62.4k | break; |
994 | 0 | } |
995 | 41.2k | case '>': |
996 | 41.2k | { |
997 | 41.2k | flags|=GreaterValue; |
998 | 41.2k | (void) CopyMagickString(p,p+1,MagickPathExtent); |
999 | 41.2k | break; |
1000 | 0 | } |
1001 | 46.4k | case '#': |
1002 | 46.4k | { |
1003 | 46.4k | flags|=MaximumValue; |
1004 | 46.4k | (void) CopyMagickString(p,p+1,MagickPathExtent); |
1005 | 46.4k | break; |
1006 | 0 | } |
1007 | 29.6k | case '^': |
1008 | 29.6k | { |
1009 | 29.6k | flags|=MinimumValue; |
1010 | 29.6k | (void) CopyMagickString(p,p+1,MagickPathExtent); |
1011 | 29.6k | break; |
1012 | 0 | } |
1013 | 61.5k | case '@': |
1014 | 61.5k | { |
1015 | 61.5k | flags|=AreaValue; |
1016 | 61.5k | (void) CopyMagickString(p,p+1,MagickPathExtent); |
1017 | 61.5k | break; |
1018 | 0 | } |
1019 | 69.9k | case '(': |
1020 | 69.9k | { |
1021 | 69.9k | if (*(p+1) == ')') |
1022 | 1.43k | return(flags); |
1023 | 68.5k | (void) CopyMagickString(p,p+1,MagickPathExtent); |
1024 | 68.5k | break; |
1025 | 69.9k | } |
1026 | 50.9k | case ')': |
1027 | 50.9k | { |
1028 | 50.9k | (void) CopyMagickString(p,p+1,MagickPathExtent); |
1029 | 50.9k | break; |
1030 | 69.9k | } |
1031 | 167k | case 'x': |
1032 | 210k | case 'X': |
1033 | 210k | { |
1034 | 210k | flags|=SeparatorValue; |
1035 | 210k | p++; |
1036 | 210k | break; |
1037 | 167k | } |
1038 | 273k | case '-': |
1039 | 576k | case '+': |
1040 | 688k | case ',': |
1041 | 3.12M | case '0': |
1042 | 3.56M | case '1': |
1043 | 3.89M | case '2': |
1044 | 4.06M | case '3': |
1045 | 4.34M | case '4': |
1046 | 4.61M | case '5': |
1047 | 4.79M | case '6': |
1048 | 5.07M | case '7': |
1049 | 5.24M | case '8': |
1050 | 5.37M | case '9': |
1051 | 5.44M | case '/': |
1052 | 5.44M | case 215: |
1053 | 5.48M | case 'e': |
1054 | 5.54M | case 'E': |
1055 | 5.54M | { |
1056 | 5.54M | p++; |
1057 | 5.54M | break; |
1058 | 5.48M | } |
1059 | 422k | case '.': |
1060 | 422k | { |
1061 | 422k | p++; |
1062 | 422k | flags|=DecimalValue; |
1063 | 422k | break; |
1064 | 5.48M | } |
1065 | 121k | case ':': |
1066 | 121k | { |
1067 | 121k | p++; |
1068 | 121k | flags|=AspectRatioValue; |
1069 | 121k | break; |
1070 | 5.48M | } |
1071 | 81.0k | default: |
1072 | 81.0k | return(NoValue); |
1073 | 6.87M | } |
1074 | 6.87M | } |
1075 | | /* |
1076 | | Parse rho, sigma, xi, psi, and optionally chi. |
1077 | | */ |
1078 | 412k | p=pedantic_geometry; |
1079 | 412k | if (*p == '\0') |
1080 | 5.88k | return(flags); |
1081 | 406k | q=p; |
1082 | 406k | value=StringToDouble(p,&q); |
1083 | 406k | if (LocaleNCompare(p,"0x",2) == 0) |
1084 | 4.83k | (void) strtol(p,&q,10); |
1085 | 406k | c=(int) ((unsigned char) *q); |
1086 | 406k | if ((c == 215) || (*q == 'x') || (*q == 'X') || (*q == ':') || |
1087 | 406k | (*q == ',') || (*q == '/') || (*q =='\0')) |
1088 | 284k | { |
1089 | | /* |
1090 | | Parse rho. |
1091 | | */ |
1092 | 284k | q=p; |
1093 | 284k | if (LocaleNCompare(p,"0x",2) == 0) |
1094 | 4.83k | value=(double) strtol(p,&p,10); |
1095 | 279k | else |
1096 | 279k | value=StringToDouble(p,&p); |
1097 | 284k | if (p != q) |
1098 | 234k | { |
1099 | 234k | flags|=RhoValue; |
1100 | 234k | geometry_info->rho=value; |
1101 | 234k | } |
1102 | 284k | } |
1103 | 406k | q=p; |
1104 | 406k | c=(int) ((unsigned char) *p); |
1105 | 406k | if ((c == 215) || (*p == 'x') || (*p == 'X') || (*p == ':') || (*p == ',') || |
1106 | 406k | (*p == '/')) |
1107 | 242k | { |
1108 | | /* |
1109 | | Parse sigma. |
1110 | | */ |
1111 | 242k | p++; |
1112 | 242k | while (isspace((int) ((unsigned char) *p)) != 0) |
1113 | 0 | p++; |
1114 | 242k | c=(int) ((unsigned char) *q); |
1115 | 242k | if (((c != 215) && (*q != 'x') && (*q != 'X') && (*q != ':')) || |
1116 | 242k | ((*p != '+') && (*p != '-'))) |
1117 | 207k | { |
1118 | 207k | q=p; |
1119 | 207k | value=StringToDouble(p,&p); |
1120 | 207k | if (p != q) |
1121 | 177k | { |
1122 | 177k | flags|=SigmaValue; |
1123 | 177k | geometry_info->sigma=value; |
1124 | 177k | } |
1125 | 207k | } |
1126 | 242k | } |
1127 | 406k | while (isspace((int) ((unsigned char) *p)) != 0) |
1128 | 0 | p++; |
1129 | 406k | if ((*p == '+') || (*p == '-') || (*p == ',') || (*p == '/') || (*p == ':')) |
1130 | 199k | { |
1131 | | /* |
1132 | | Parse xi value. |
1133 | | */ |
1134 | 199k | if ((*p == ',') || (*p == '/') || (*p == ':') ) |
1135 | 18.4k | p++; |
1136 | 436k | while ((*p == '+') || (*p == '-')) |
1137 | 236k | { |
1138 | 236k | if (*p == '-') |
1139 | 84.4k | flags^=XiNegative; /* negate sign */ |
1140 | 236k | p++; |
1141 | 236k | } |
1142 | 199k | q=p; |
1143 | 199k | value=StringToDouble(p,&p); |
1144 | 199k | if (p != q) |
1145 | 165k | { |
1146 | 165k | flags|=XiValue; |
1147 | 165k | if ((flags & XiNegative) != 0) |
1148 | 41.7k | value=(-value); |
1149 | 165k | geometry_info->xi=value; |
1150 | 165k | } |
1151 | 199k | while (isspace((int) ((unsigned char) *p)) != 0) |
1152 | 0 | p++; |
1153 | 199k | if ((*p == '+') || (*p == '-') || (*p == ',') || (*p == '/') || |
1154 | 199k | (*p == ':')) |
1155 | 142k | { |
1156 | | /* |
1157 | | Parse psi value. |
1158 | | */ |
1159 | 142k | if ((*p == ',') || (*p == '/') || (*p == ':')) |
1160 | 25.9k | p++; |
1161 | 305k | while ((*p == '+') || (*p == '-')) |
1162 | 162k | { |
1163 | 162k | if (*p == '-') |
1164 | 50.0k | flags^=PsiNegative; /* negate sign */ |
1165 | 162k | p++; |
1166 | 162k | } |
1167 | 142k | q=p; |
1168 | 142k | value=StringToDouble(p,&p); |
1169 | 142k | if (p != q) |
1170 | 120k | { |
1171 | 120k | flags|=PsiValue; |
1172 | 120k | if ((flags & PsiNegative) != 0) |
1173 | 15.3k | value=(-value); |
1174 | 120k | geometry_info->psi=value; |
1175 | 120k | } |
1176 | 142k | } |
1177 | 199k | while (isspace((int) ((unsigned char) *p)) != 0) |
1178 | 0 | p++; |
1179 | 199k | if ((*p == '+') || (*p == '-') || (*p == ',') || (*p == '/') || |
1180 | 199k | (*p == ':')) |
1181 | 27.5k | { |
1182 | | /* |
1183 | | Parse chi value. |
1184 | | */ |
1185 | 27.5k | if ((*p == ',') || (*p == '/') || (*p == ':')) |
1186 | 15.0k | p++; |
1187 | 64.8k | while ((*p == '+') || (*p == '-')) |
1188 | 37.2k | { |
1189 | 37.2k | if (*p == '-') |
1190 | 24.0k | flags^=ChiNegative; /* negate sign */ |
1191 | 37.2k | p++; |
1192 | 37.2k | } |
1193 | 27.5k | q=p; |
1194 | 27.5k | value=StringToDouble(p,&p); |
1195 | 27.5k | if (p != q) |
1196 | 16.5k | { |
1197 | 16.5k | flags|=ChiValue; |
1198 | 16.5k | if ((flags & ChiNegative) != 0) |
1199 | 7.88k | value=(-value); |
1200 | 16.5k | geometry_info->chi=value; |
1201 | 16.5k | } |
1202 | 27.5k | } |
1203 | 199k | } |
1204 | 406k | if (strchr(pedantic_geometry,':') != (char *) NULL) |
1205 | 67.7k | { |
1206 | | /* |
1207 | | Normalize sampling factor (e.g. 4:2:2 => 2x1). |
1208 | | */ |
1209 | 67.7k | if ((flags & SigmaValue) != 0) |
1210 | 22.2k | geometry_info->rho*=MagickSafeReciprocal(geometry_info->sigma); |
1211 | 67.7k | geometry_info->sigma=1.0; |
1212 | 67.7k | if (((flags & XiValue) != 0) && (geometry_info->xi == 0.0)) |
1213 | 9.25k | geometry_info->sigma=2.0; |
1214 | 67.7k | } |
1215 | 406k | if (((flags & RhoValue) != 0) && ((flags & SigmaValue) == 0) && |
1216 | 406k | ((flags & XiValue) != 0) && ((flags & XiNegative) != 0)) |
1217 | 20.1k | { |
1218 | 20.1k | if ((flags & PsiValue) == 0) |
1219 | 13.6k | { |
1220 | | /* |
1221 | | Support negative height values (e.g. 30x-20). |
1222 | | */ |
1223 | 13.6k | geometry_info->sigma=geometry_info->xi; |
1224 | 13.6k | geometry_info->xi=0.0; |
1225 | 13.6k | flags|=SigmaValue; |
1226 | 13.6k | flags&=(unsigned int) (~XiValue); |
1227 | 13.6k | } |
1228 | 6.58k | else |
1229 | 6.58k | if ((flags & ChiValue) == 0) |
1230 | 3.88k | { |
1231 | | /* |
1232 | | Support negative height values (e.g. 30x-20+10). |
1233 | | */ |
1234 | 3.88k | geometry_info->sigma=geometry_info->xi; |
1235 | 3.88k | geometry_info->xi=geometry_info->psi; |
1236 | 3.88k | flags|=SigmaValue; |
1237 | 3.88k | flags|=XiValue; |
1238 | 3.88k | flags&=(unsigned int) (~PsiValue); |
1239 | 3.88k | } |
1240 | 2.69k | else |
1241 | 2.69k | { |
1242 | | /* |
1243 | | Support negative height values (e.g. 30x-20+10+10). |
1244 | | */ |
1245 | 2.69k | geometry_info->sigma=geometry_info->xi; |
1246 | 2.69k | geometry_info->xi=geometry_info->psi; |
1247 | 2.69k | geometry_info->psi=geometry_info->chi; |
1248 | 2.69k | flags|=SigmaValue; |
1249 | 2.69k | flags|=XiValue; |
1250 | 2.69k | flags|=PsiValue; |
1251 | 2.69k | flags&=(unsigned int) (~ChiValue); |
1252 | 2.69k | } |
1253 | 20.1k | } |
1254 | 406k | if ((flags & PercentValue) != 0) |
1255 | 52.6k | { |
1256 | 52.6k | if (((flags & SeparatorValue) == 0) && ((flags & SigmaValue) == 0)) |
1257 | 25.5k | geometry_info->sigma=geometry_info->rho; |
1258 | 52.6k | if (((flags & SeparatorValue) != 0) && ((flags & RhoValue) == 0)) |
1259 | 7.96k | geometry_info->rho=geometry_info->sigma; |
1260 | 52.6k | } |
1261 | | #if 0 |
1262 | | /* Debugging Geometry */ |
1263 | | (void) fprintf(stderr,"ParseGeometry...\n"); |
1264 | | (void) fprintf(stderr,"Flags: %c %c %s %s %s\n", |
1265 | | (flags & RhoValue) ? 'W' : ' ',(flags & SigmaValue) ? 'H' : ' ', |
1266 | | (flags & XiValue) ? ((flags & XiNegative) ? "-X" : "+X") : " ", |
1267 | | (flags & PsiValue) ? ((flags & PsiNegative) ? "-Y" : "+Y") : " ", |
1268 | | (flags & ChiValue) ? ((flags & ChiNegative) ? "-Z" : "+Z") : " "); |
1269 | | (void) fprintf(stderr,"Geometry: %lg,%lg,%lg,%lg,%lg\n",geometry_info->rho, |
1270 | | geometry_info->sigma,geometry_info->xi,geometry_info->psi, |
1271 | | geometry_info->chi); |
1272 | | #endif |
1273 | 406k | return(flags); |
1274 | 412k | } |
1275 | | |
1276 | | /* |
1277 | | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% |
1278 | | % % |
1279 | | % % |
1280 | | % % |
1281 | | % P a r s e G r a v i t y G e o m e t r y % |
1282 | | % % |
1283 | | % % |
1284 | | % % |
1285 | | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% |
1286 | | % |
1287 | | % ParseGravityGeometry() returns a region as defined by the geometry string |
1288 | | % with respect to the given image page (canvas) dimensions and the images |
1289 | | % gravity setting. |
1290 | | % |
1291 | | % This is typically used for specifying a area within a given image for |
1292 | | % cropping images to a smaller size, chopping out rows and or columns, or |
1293 | | % resizing and positioning overlay images. |
1294 | | % |
1295 | | % Percentages are relative to image size and not page size, and are set to |
1296 | | % nearest integer (pixel) size. |
1297 | | % |
1298 | | % The format of the ParseGravityGeometry method is: |
1299 | | % |
1300 | | % MagickStatusType ParseGravityGeometry(Image *image,const char *geometry, |
1301 | | % RectangleInfo *region_info,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 respect |
1308 | | % to the image dimensions and its gravity. |
1309 | | % |
1310 | | % o exception: return any errors or warnings in this structure. |
1311 | | % |
1312 | | */ |
1313 | | MagickExport MagickStatusType ParseGravityGeometry(const Image *image, |
1314 | | const char *geometry,RectangleInfo *region_info,ExceptionInfo *exception) |
1315 | 5.97k | { |
1316 | 5.97k | MagickStatusType |
1317 | 5.97k | flags; |
1318 | | |
1319 | 5.97k | size_t |
1320 | 5.97k | height, |
1321 | 5.97k | width; |
1322 | | |
1323 | 5.97k | if (IsEventLogging() != MagickFalse) |
1324 | 0 | (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",geometry); |
1325 | 5.97k | if ((geometry == (char *) NULL) || (*geometry == '\0')) |
1326 | 0 | return(NoValue); |
1327 | 5.97k | SetGeometry(image,region_info); |
1328 | 5.97k | if (image->page.width != 0) |
1329 | 0 | region_info->width=image->page.width; |
1330 | 5.97k | if (image->page.height != 0) |
1331 | 0 | region_info->height=image->page.height; |
1332 | 5.97k | flags=ParseAbsoluteGeometry(geometry,region_info); |
1333 | 5.97k | if (flags == NoValue) |
1334 | 0 | { |
1335 | 0 | (void) ThrowMagickException(exception,GetMagickModule(),OptionError, |
1336 | 0 | "InvalidGeometry","`%s'",geometry); |
1337 | 0 | return(flags); |
1338 | 0 | } |
1339 | 5.97k | if ((flags & PercentValue) != 0) |
1340 | 0 | { |
1341 | 0 | GeometryInfo |
1342 | 0 | geometry_info; |
1343 | |
|
1344 | 0 | MagickStatusType |
1345 | 0 | status; |
1346 | |
|
1347 | 0 | PointInfo |
1348 | 0 | scale; |
1349 | | |
1350 | | /* |
1351 | | Geometry is a percentage of the image size, not canvas size |
1352 | | */ |
1353 | 0 | if (image->gravity != UndefinedGravity) |
1354 | 0 | flags|=XValue | YValue; |
1355 | 0 | status=ParseGeometry(geometry,&geometry_info); |
1356 | 0 | scale.x=geometry_info.rho; |
1357 | 0 | if ((status & RhoValue) == 0) |
1358 | 0 | scale.x=100.0; |
1359 | 0 | scale.y=geometry_info.sigma; |
1360 | 0 | if ((status & SigmaValue) == 0) |
1361 | 0 | scale.y=scale.x; |
1362 | 0 | region_info->width=CastDoubleToSizeT(scale.x*image->columns/100.0+0.5); |
1363 | 0 | region_info->height=CastDoubleToSizeT(scale.y*image->rows/100.0+0.5); |
1364 | 0 | } |
1365 | 5.97k | if ((flags & AspectRatioValue) != 0) |
1366 | 0 | { |
1367 | 0 | double |
1368 | 0 | geometry_ratio, |
1369 | 0 | image_ratio; |
1370 | |
|
1371 | 0 | GeometryInfo |
1372 | 0 | geometry_info; |
1373 | | |
1374 | | /* |
1375 | | Geometry is a relative to image size and aspect ratio. |
1376 | | */ |
1377 | 0 | if (image->gravity != UndefinedGravity) |
1378 | 0 | flags|=XValue | YValue; |
1379 | 0 | (void) ParseGeometry(geometry,&geometry_info); |
1380 | 0 | geometry_ratio=geometry_info.rho; |
1381 | 0 | image_ratio=(double) image->columns/image->rows; |
1382 | 0 | region_info->width=image->columns; |
1383 | 0 | region_info->height=image->rows; |
1384 | 0 | if ((flags & MaximumValue) != 0) |
1385 | 0 | { |
1386 | 0 | if (geometry_ratio < image_ratio) |
1387 | 0 | region_info->height=CastDoubleToSizeT((double) image->rows* |
1388 | 0 | image_ratio/geometry_ratio+0.5); |
1389 | 0 | else |
1390 | 0 | region_info->width=CastDoubleToSizeT((double) image->columns* |
1391 | 0 | geometry_ratio/image_ratio+0.5); |
1392 | 0 | } |
1393 | 0 | else |
1394 | 0 | if (geometry_ratio >= image_ratio) |
1395 | 0 | region_info->height=CastDoubleToSizeT((double) image->rows* |
1396 | 0 | image_ratio/geometry_ratio+0.5); |
1397 | 0 | else |
1398 | 0 | region_info->width=CastDoubleToSizeT((double) image->columns* |
1399 | 0 | geometry_ratio/image_ratio+0.5); |
1400 | 0 | } |
1401 | | /* |
1402 | | Adjust offset according to gravity setting. |
1403 | | */ |
1404 | 5.97k | width=region_info->width; |
1405 | 5.97k | height=region_info->height; |
1406 | 5.97k | if (width == 0) |
1407 | 0 | region_info->width=image->page.width | image->columns; |
1408 | 5.97k | if (height == 0) |
1409 | 0 | region_info->height=image->page.height | image->rows; |
1410 | 5.97k | GravityAdjustGeometry(image->columns,image->rows,image->gravity,region_info); |
1411 | 5.97k | if ((flags & LessValue) != 0) |
1412 | 0 | if ((region_info->width < image->columns) && |
1413 | 0 | (region_info->height < image->rows)) |
1414 | 0 | { |
1415 | 0 | SetGeometry(image,region_info); |
1416 | 0 | return(NoValue); |
1417 | 0 | } |
1418 | 5.97k | if ((flags & GreaterValue) != 0) |
1419 | 0 | if ((region_info->width > image->columns) && |
1420 | 0 | (region_info->height > image->rows)) |
1421 | 0 | { |
1422 | 0 | SetGeometry(image,region_info); |
1423 | 0 | return(NoValue); |
1424 | 0 | } |
1425 | 5.97k | region_info->width=width; |
1426 | 5.97k | region_info->height=height; |
1427 | 5.97k | return(flags); |
1428 | 5.97k | } |
1429 | | |
1430 | | /* |
1431 | | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% |
1432 | | % % |
1433 | | % % |
1434 | | % % |
1435 | | + P a r s e M e t a G e o m e t r y % |
1436 | | % % |
1437 | | % % |
1438 | | % % |
1439 | | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% |
1440 | | % |
1441 | | % ParseMetaGeometry() is similar to GetGeometry() except the returned |
1442 | | % geometry is modified as determined by the meta characters: %, !, <, >, @, |
1443 | | % :, and ^ in relation to image resizing. |
1444 | | % |
1445 | | % Final image dimensions are adjusted so as to preserve the aspect ratio as |
1446 | | % much as possible, while generating a integer (pixel) size, and fitting the |
1447 | | % image within the specified geometry width and height. |
1448 | | % |
1449 | | % Flags are interpreted... |
1450 | | % % geometry size is given percentage of original width and height given |
1451 | | % ! do not try to preserve aspect ratio |
1452 | | % < only enlarge images smaller that geometry |
1453 | | % > only shrink images larger than geometry |
1454 | | % @ fit image to contain at most this many pixels |
1455 | | % : width and height denotes an aspect ratio |
1456 | | % ^ contain the given geometry given, (minimal dimensions given) |
1457 | | % |
1458 | | % The format of the ParseMetaGeometry method is: |
1459 | | % |
1460 | | % MagickStatusType ParseMetaGeometry(const char *geometry,ssize_t *x, |
1461 | | % ssize_t *y, size_t *width,size_t *height) |
1462 | | % |
1463 | | % A description of each parameter follows: |
1464 | | % |
1465 | | % o geometry: The geometry string (e.g. "100x100+10+10"). |
1466 | | % |
1467 | | % o x,y: The x and y offset, set according to the geometry specification. |
1468 | | % |
1469 | | % o width,height: The width and height of original image, modified by |
1470 | | % the given geometry specification. |
1471 | | % |
1472 | | */ |
1473 | | MagickExport MagickStatusType ParseMetaGeometry(const char *geometry,ssize_t *x, |
1474 | | ssize_t *y,size_t *width,size_t *height) |
1475 | 107k | { |
1476 | 107k | GeometryInfo |
1477 | 107k | geometry_info; |
1478 | | |
1479 | 107k | MagickStatusType |
1480 | 107k | flags; |
1481 | | |
1482 | 107k | size_t |
1483 | 107k | stasis_height, |
1484 | 107k | stasis_width; |
1485 | | |
1486 | | /* |
1487 | | Ensure the image geometry is valid. |
1488 | | */ |
1489 | 107k | assert(x != (ssize_t *) NULL); |
1490 | 107k | assert(y != (ssize_t *) NULL); |
1491 | 107k | assert(width != (size_t *) NULL); |
1492 | 107k | assert(height != (size_t *) NULL); |
1493 | 107k | if (IsEventLogging() != MagickFalse) |
1494 | 0 | (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",geometry); |
1495 | 107k | if ((geometry == (char *) NULL) || (*geometry == '\0')) |
1496 | 0 | return(NoValue); |
1497 | | /* |
1498 | | Parse geometry using GetGeometry. |
1499 | | */ |
1500 | 107k | stasis_width=(*width); |
1501 | 107k | stasis_height=(*height); |
1502 | 107k | SetGeometryInfo(&geometry_info); |
1503 | 107k | flags=GetGeometry(geometry,x,y,width,height); |
1504 | 107k | if ((flags & PercentValue) != 0) |
1505 | 2.73k | { |
1506 | 2.73k | MagickStatusType |
1507 | 2.73k | percent_flags; |
1508 | | |
1509 | 2.73k | PointInfo |
1510 | 2.73k | scale; |
1511 | | |
1512 | | /* |
1513 | | Geometry is a percentage of the image size. |
1514 | | */ |
1515 | 2.73k | percent_flags=ParseGeometry(geometry,&geometry_info); |
1516 | 2.73k | scale.x=geometry_info.rho; |
1517 | 2.73k | if ((percent_flags & RhoValue) == 0) |
1518 | 886 | scale.x=100.0; |
1519 | 2.73k | scale.y=geometry_info.sigma; |
1520 | 2.73k | if ((percent_flags & SigmaValue) == 0) |
1521 | 1.89k | scale.y=scale.x; |
1522 | 2.73k | *width=CastDoubleToSizeT(scale.x*stasis_width/100.0+0.5); |
1523 | 2.73k | *height=CastDoubleToSizeT(scale.y*stasis_height/100.0+0.5); |
1524 | 2.73k | stasis_width=(*width); |
1525 | 2.73k | stasis_height=(*height); |
1526 | 2.73k | } |
1527 | 107k | if ((flags & AspectRatioValue) != 0) |
1528 | 1.89k | { |
1529 | 1.89k | double |
1530 | 1.89k | geometry_ratio, |
1531 | 1.89k | image_ratio; |
1532 | | |
1533 | | /* |
1534 | | Geometry is a relative to image size and aspect ratio. |
1535 | | */ |
1536 | 1.89k | (void) ParseGeometry(geometry,&geometry_info); |
1537 | 1.89k | geometry_ratio=geometry_info.rho; |
1538 | 1.89k | image_ratio=(double) stasis_width*MagickSafeReciprocal((double) |
1539 | 1.89k | stasis_height); |
1540 | 1.89k | if (geometry_ratio >= image_ratio) |
1541 | 1.05k | { |
1542 | 1.05k | *width=stasis_width; |
1543 | 1.05k | *height=CastDoubleToSizeT((double) (MagickSafeReciprocal( |
1544 | 1.05k | geometry_ratio)*stasis_height*image_ratio)+0.5); |
1545 | 1.05k | } |
1546 | 836 | else |
1547 | 836 | { |
1548 | 836 | *width=CastDoubleToSizeT(MagickSafeReciprocal(image_ratio)* |
1549 | 836 | stasis_width*geometry_ratio+0.5); |
1550 | 836 | *height=stasis_height; |
1551 | 836 | } |
1552 | 1.89k | stasis_width=(*width); |
1553 | 1.89k | stasis_height=(*height); |
1554 | 1.89k | } |
1555 | 107k | if (((flags & AspectValue) != 0) || ((*width == stasis_width) && |
1556 | 101k | (*height == stasis_height))) |
1557 | 101k | { |
1558 | 101k | if ((flags & RhoValue) == 0) |
1559 | 94.3k | *width=stasis_width; |
1560 | 101k | if ((flags & SigmaValue) == 0) |
1561 | 93.5k | *height=stasis_height; |
1562 | 101k | } |
1563 | 5.99k | else |
1564 | 5.99k | { |
1565 | 5.99k | double |
1566 | 5.99k | scale_factor; |
1567 | | |
1568 | | /* |
1569 | | Respect aspect ratio of the image. |
1570 | | */ |
1571 | 5.99k | if ((stasis_width == 0) || (stasis_height == 0)) |
1572 | 1 | scale_factor=1.0; |
1573 | 5.99k | else |
1574 | 5.99k | if (((flags & RhoValue) != 0) && (flags & SigmaValue) != 0) |
1575 | 1.33k | { |
1576 | 1.33k | scale_factor=(double) *width/(double) stasis_width; |
1577 | 1.33k | if ((flags & MinimumValue) == 0) |
1578 | 1.22k | { |
1579 | 1.22k | if (scale_factor > ((double) *height/(double) stasis_height)) |
1580 | 90 | scale_factor=(double) *height/(double) stasis_height; |
1581 | 1.22k | } |
1582 | 108 | else |
1583 | 108 | if (scale_factor < ((double) *height/(double) stasis_height)) |
1584 | 76 | scale_factor=(double) *height/(double) stasis_height; |
1585 | 1.33k | } |
1586 | 4.66k | else |
1587 | 4.66k | if ((flags & RhoValue) != 0) |
1588 | 4.15k | { |
1589 | 4.15k | scale_factor=(double) *width/(double) stasis_width; |
1590 | 4.15k | if (((flags & MinimumValue) != 0) && |
1591 | 4.15k | (scale_factor < ((double) *width/(double) stasis_height))) |
1592 | 74 | scale_factor=(double) *width/(double) stasis_height; |
1593 | 4.15k | } |
1594 | 511 | else |
1595 | 511 | { |
1596 | 511 | scale_factor=(double) *height/(double) stasis_height; |
1597 | 511 | if (((flags & MinimumValue) != 0) && |
1598 | 511 | (scale_factor < ((double) *height/(double) stasis_width))) |
1599 | 10 | scale_factor=(double) *height/(double) stasis_width; |
1600 | 511 | } |
1601 | 5.99k | *width=CastDoubleToSizeT(MagickMax(floor(scale_factor*stasis_width+0.5),1.0)); |
1602 | 5.99k | *height=CastDoubleToSizeT(MagickMax(floor(scale_factor*stasis_height+0.5),1.0)); |
1603 | 5.99k | } |
1604 | 107k | if ((flags & GreaterValue) != 0) |
1605 | 1.21k | { |
1606 | 1.21k | if (stasis_width < *width) |
1607 | 849 | *width=stasis_width; |
1608 | 1.21k | if (stasis_height < *height) |
1609 | 858 | *height=stasis_height; |
1610 | 1.21k | } |
1611 | 107k | if ((flags & LessValue) != 0) |
1612 | 1.29k | { |
1613 | 1.29k | if (stasis_width > *width) |
1614 | 54 | *width=stasis_width; |
1615 | 1.29k | if (stasis_height > *height) |
1616 | 89 | *height=stasis_height; |
1617 | 1.29k | } |
1618 | 107k | if ((flags & AreaValue) != 0) |
1619 | 1.31k | { |
1620 | 1.31k | double |
1621 | 1.31k | area, |
1622 | 1.31k | distance; |
1623 | | |
1624 | 1.31k | PointInfo |
1625 | 1.31k | scale; |
1626 | | |
1627 | | /* |
1628 | | Geometry is a maximum area in pixels. |
1629 | | */ |
1630 | 1.31k | (void) ParseGeometry(geometry,&geometry_info); |
1631 | 1.31k | area=geometry_info.rho+sqrt(MagickEpsilon); |
1632 | 1.31k | distance=sqrt((double) stasis_width*stasis_height); |
1633 | 1.31k | scale.x=(double) stasis_width*MagickSafeReciprocal(distance* |
1634 | 1.31k | MagickSafeReciprocal(sqrt(area))); |
1635 | 1.31k | scale.y=(double) stasis_height*MagickSafeReciprocal(distance* |
1636 | 1.31k | MagickSafeReciprocal(sqrt(area))); |
1637 | 1.31k | if ((scale.x < (double) *width) || (scale.y < (double) *height)) |
1638 | 526 | { |
1639 | 526 | *width=CastDoubleToSizeT((double) stasis_width*MagickSafeReciprocal( |
1640 | 526 | distance*MagickSafeReciprocal(sqrt(area)))+0.5); |
1641 | 526 | *height=CastDoubleToSizeT((double) stasis_height*MagickSafeReciprocal( |
1642 | 526 | distance*MagickSafeReciprocal(sqrt(area)))+0.5); |
1643 | 526 | } |
1644 | 1.31k | } |
1645 | 107k | return(flags); |
1646 | 107k | } |
1647 | | |
1648 | | /* |
1649 | | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% |
1650 | | % % |
1651 | | % % |
1652 | | % % |
1653 | | % P a r s e P a g e G e o m e t r y % |
1654 | | % % |
1655 | | % % |
1656 | | % % |
1657 | | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% |
1658 | | % |
1659 | | % ParsePageGeometry() returns a region as defined by the geometry string with |
1660 | | % respect to the image page (canvas) dimensions. |
1661 | | % |
1662 | | % WARNING: Percentage dimensions remain relative to the actual image |
1663 | | % dimensions, and not canvas dimensions. |
1664 | | % |
1665 | | % The format of the ParsePageGeometry method is: |
1666 | | % |
1667 | | % MagickStatusType ParsePageGeometry(const Image *image, |
1668 | | % const char *geometry,RectangleInfo *region_info, |
1669 | | % ExceptionInfo *exception) |
1670 | | % |
1671 | | % A description of each parameter follows: |
1672 | | % |
1673 | | % o geometry: The geometry string (e.g. "100x100+10+10"). |
1674 | | % |
1675 | | % o region_info: the region as defined by the geometry string with |
1676 | | % respect to the image and its gravity. |
1677 | | % |
1678 | | % o exception: return any errors or warnings in this structure. |
1679 | | % |
1680 | | */ |
1681 | | MagickExport MagickStatusType ParsePageGeometry(const Image *image, |
1682 | | const char *geometry,RectangleInfo *region_info,ExceptionInfo *exception) |
1683 | 92.2k | { |
1684 | 92.2k | MagickStatusType |
1685 | 92.2k | flags; |
1686 | | |
1687 | 92.2k | SetGeometry(image,region_info); |
1688 | 92.2k | if (image->page.width != 0) |
1689 | 0 | region_info->width=image->page.width; |
1690 | 92.2k | if (image->page.height != 0) |
1691 | 0 | region_info->height=image->page.height; |
1692 | 92.2k | flags=ParseAbsoluteGeometry(geometry,region_info); |
1693 | 92.2k | if (flags == NoValue) |
1694 | 0 | { |
1695 | 0 | (void) ThrowMagickException(exception,GetMagickModule(),OptionError, |
1696 | 0 | "InvalidGeometry","`%s'",geometry); |
1697 | 0 | return(flags); |
1698 | 0 | } |
1699 | 92.2k | if ((flags & PercentValue) != 0) |
1700 | 0 | { |
1701 | 0 | region_info->width=image->columns; |
1702 | 0 | region_info->height=image->rows; |
1703 | 0 | } |
1704 | 92.2k | flags=ParseMetaGeometry(geometry,®ion_info->x,®ion_info->y, |
1705 | 92.2k | ®ion_info->width,®ion_info->height); |
1706 | 92.2k | if ((((flags & WidthValue) != 0) || ((flags & HeightValue) != 0)) && |
1707 | 92.2k | (((flags & PercentValue) != 0) || ((flags & SeparatorValue) == 0))) |
1708 | 0 | { |
1709 | 0 | if ((flags & WidthValue) == 0) |
1710 | 0 | region_info->width=region_info->height; |
1711 | 0 | if ((flags & HeightValue) == 0) |
1712 | 0 | region_info->height=region_info->width; |
1713 | 0 | } |
1714 | 92.2k | return(flags); |
1715 | 92.2k | } |
1716 | | |
1717 | | /* |
1718 | | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% |
1719 | | % % |
1720 | | % % |
1721 | | % % |
1722 | | % P a r s e R e g i o n G e o m e t r y % |
1723 | | % % |
1724 | | % % |
1725 | | % % |
1726 | | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% |
1727 | | % |
1728 | | % ParseRegionGeometry() returns a region as defined by the geometry string |
1729 | | % with respect to the image dimensions and aspect ratio. |
1730 | | % |
1731 | | % This is basically a wrapper around ParseMetaGeometry. This is typically |
1732 | | % used to parse a geometry string to work out the final integer dimensions |
1733 | | % for image resizing. |
1734 | | % |
1735 | | % The format of the ParseRegionGeometry method is: |
1736 | | % |
1737 | | % MagickStatusType ParseRegionGeometry(const Image *image, |
1738 | | % const char *geometry,RectangleInfo *region_info, |
1739 | | % ExceptionInfo *exception) |
1740 | | % |
1741 | | % A description of each parameter follows: |
1742 | | % |
1743 | | % o geometry: The geometry string (e.g. "100x100+10+10"). |
1744 | | % |
1745 | | % o region_info: the region as defined by the geometry string. |
1746 | | % |
1747 | | % o exception: return any errors or warnings in this structure. |
1748 | | % |
1749 | | */ |
1750 | | MagickExport MagickStatusType ParseRegionGeometry(const Image *image, |
1751 | | const char *geometry,RectangleInfo *region_info,ExceptionInfo *exception) |
1752 | 15.5k | { |
1753 | 15.5k | MagickStatusType |
1754 | 15.5k | flags; |
1755 | | |
1756 | 15.5k | SetGeometry(image,region_info); |
1757 | 15.5k | flags=ParseMetaGeometry(geometry,®ion_info->x,®ion_info->y, |
1758 | 15.5k | ®ion_info->width,®ion_info->height); |
1759 | 15.5k | if (flags == NoValue) |
1760 | 0 | (void) ThrowMagickException(exception,GetMagickModule(),OptionError, |
1761 | 0 | "InvalidGeometry","`%s'",geometry); |
1762 | 15.5k | return(flags); |
1763 | 15.5k | } |
1764 | | |
1765 | | /* |
1766 | | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% |
1767 | | % % |
1768 | | % % |
1769 | | % % |
1770 | | % S e t G e o m e t r y % |
1771 | | % % |
1772 | | % % |
1773 | | % % |
1774 | | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% |
1775 | | % |
1776 | | % SetGeometry() sets the geometry to its default values. |
1777 | | % |
1778 | | % The format of the SetGeometry method is: |
1779 | | % |
1780 | | % SetGeometry(const Image *image,RectangleInfo *geometry) |
1781 | | % |
1782 | | % A description of each parameter follows: |
1783 | | % |
1784 | | % o image: the image. |
1785 | | % |
1786 | | % o geometry: the geometry. |
1787 | | % |
1788 | | */ |
1789 | | MagickExport void SetGeometry(const Image *image,RectangleInfo *geometry) |
1790 | 229k | { |
1791 | 229k | assert(image != (Image *) NULL); |
1792 | 229k | assert(image->signature == MagickCoreSignature); |
1793 | 229k | if (IsEventLogging() != MagickFalse) |
1794 | 0 | (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename); |
1795 | 229k | assert(geometry != (RectangleInfo *) NULL); |
1796 | 229k | (void) memset(geometry,0,sizeof(*geometry)); |
1797 | 229k | geometry->width=image->columns; |
1798 | 229k | geometry->height=image->rows; |
1799 | 229k | } |
1800 | | |
1801 | | /* |
1802 | | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% |
1803 | | % % |
1804 | | % % |
1805 | | % % |
1806 | | % S e t G e o m e t r y I n f o % |
1807 | | % % |
1808 | | % % |
1809 | | % % |
1810 | | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% |
1811 | | % |
1812 | | % SetGeometryInfo sets the GeometryInfo structure to its default values. |
1813 | | % |
1814 | | % The format of the SetGeometryInfo method is: |
1815 | | % |
1816 | | % SetGeometryInfo(GeometryInfo *geometry_info) |
1817 | | % |
1818 | | % A description of each parameter follows: |
1819 | | % |
1820 | | % o geometry_info: the geometry info structure. |
1821 | | % |
1822 | | */ |
1823 | | MagickExport void SetGeometryInfo(GeometryInfo *geometry_info) |
1824 | 327k | { |
1825 | 327k | assert(geometry_info != (GeometryInfo *) NULL); |
1826 | 327k | if (IsEventLogging() != MagickFalse) |
1827 | 0 | (void) LogMagickEvent(TraceEvent,GetMagickModule(),"..."); |
1828 | 327k | (void) memset(geometry_info,0,sizeof(*geometry_info)); |
1829 | 327k | } |