MagickCore  7.0.7
Convert, Edit, Or Compose Bitmap Images
transform.c
Go to the documentation of this file.
1 /*
2 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3 % %
4 % %
5 % %
6 % TTTTT RRRR AAA N N SSSSS FFFFF OOO RRRR M M %
7 % T R R A A NN N SS F O O R R MM MM %
8 % T RRRR AAAAA N N N SSS FFF O O RRRR M M M %
9 % T R R A A N NN SS F O O R R M M %
10 % T R R A A N N SSSSS F OOO R R M M %
11 % %
12 % %
13 % MagickCore Image Transform Methods %
14 % %
15 % Software Design %
16 % Cristy %
17 % July 1992 %
18 % %
19 % %
20 % Copyright 1999-2018 ImageMagick Studio LLC, a non-profit organization %
21 % dedicated to making software imaging solutions freely available. %
22 % %
23 % You may not use this file except in compliance with the License. You may %
24 % obtain a copy of the License at %
25 % %
26 % https://www.imagemagick.org/script/license.php %
27 % %
28 % Unless required by applicable law or agreed to in writing, software %
29 % distributed under the License is distributed on an "AS IS" BASIS, %
30 % WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. %
31 % See the License for the specific language governing permissions and %
32 % limitations under the License. %
33 % %
34 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
35 %
36 %
37 */
38 
39 /*
40  Include declarations.
41 */
42 #include "MagickCore/studio.h"
43 #include "MagickCore/attribute.h"
44 #include "MagickCore/cache.h"
45 #include "MagickCore/cache-view.h"
46 #include "MagickCore/color.h"
49 #include "MagickCore/composite.h"
50 #include "MagickCore/distort.h"
51 #include "MagickCore/draw.h"
52 #include "MagickCore/effect.h"
53 #include "MagickCore/exception.h"
55 #include "MagickCore/geometry.h"
56 #include "MagickCore/image.h"
57 #include "MagickCore/memory_.h"
58 #include "MagickCore/layer.h"
59 #include "MagickCore/list.h"
60 #include "MagickCore/monitor.h"
63 #include "MagickCore/resource_.h"
64 #include "MagickCore/resize.h"
65 #include "MagickCore/statistic.h"
66 #include "MagickCore/string_.h"
68 #include "MagickCore/transform.h"
70 
71 /*
72 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
73 % %
74 % %
75 % %
76 % A u t o O r i e n t I m a g e %
77 % %
78 % %
79 % %
80 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
81 %
82 % AutoOrientImage() adjusts an image so that its orientation is suitable for
83 % viewing (i.e. top-left orientation).
84 %
85 % The format of the AutoOrientImage method is:
86 %
87 % Image *AutoOrientImage(const Image *image,
88 % const OrientationType orientation,ExceptionInfo *exception)
89 %
90 % A description of each parameter follows:
91 %
92 % o image: The image.
93 %
94 % o orientation: Current image orientation.
95 %
96 % o exception: Return any errors or warnings in this structure.
97 %
98 */
100  const OrientationType orientation,ExceptionInfo *exception)
101 {
102  Image
103  *orient_image;
104 
105  assert(image != (const Image *) NULL);
106  assert(image->signature == MagickCoreSignature);
107  assert(exception != (ExceptionInfo *) NULL);
108  assert(exception->signature == MagickCoreSignature);
109  orient_image=(Image *) NULL;
110  switch(orientation)
111  {
113  case TopLeftOrientation:
114  default:
115  {
116  orient_image=CloneImage(image,0,0,MagickTrue,exception);
117  break;
118  }
119  case TopRightOrientation:
120  {
121  orient_image=FlopImage(image,exception);
122  break;
123  }
125  {
126  orient_image=RotateImage(image,180.0,exception);
127  break;
128  }
130  {
131  orient_image=FlipImage(image,exception);
132  break;
133  }
134  case LeftTopOrientation:
135  {
136  orient_image=TransposeImage(image,exception);
137  break;
138  }
139  case RightTopOrientation:
140  {
141  orient_image=RotateImage(image,90.0,exception);
142  break;
143  }
145  {
146  orient_image=TransverseImage(image,exception);
147  break;
148  }
150  {
151  orient_image=RotateImage(image,270.0,exception);
152  break;
153  }
154  }
155  if (orient_image != (Image *) NULL)
156  orient_image->orientation=TopLeftOrientation;
157  return(orient_image);
158 }
159 
160 /*
161 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
162 % %
163 % %
164 % %
165 % C h o p I m a g e %
166 % %
167 % %
168 % %
169 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
170 %
171 % ChopImage() removes a region of an image and collapses the image to occupy
172 % the removed portion.
173 %
174 % The format of the ChopImage method is:
175 %
176 % Image *ChopImage(const Image *image,const RectangleInfo *chop_info)
177 % ExceptionInfo *exception)
178 %
179 % A description of each parameter follows:
180 %
181 % o image: the image.
182 %
183 % o chop_info: Define the region of the image to chop.
184 %
185 % o exception: return any errors or warnings in this structure.
186 %
187 */
188 MagickExport Image *ChopImage(const Image *image,const RectangleInfo *chop_info,
189  ExceptionInfo *exception)
190 {
191 #define ChopImageTag "Chop/Image"
192 
193  CacheView
194  *chop_view,
195  *image_view;
196 
197  Image
198  *chop_image;
199 
201  status;
202 
204  progress;
205 
207  extent;
208 
209  ssize_t
210  y;
211 
212  /*
213  Check chop geometry.
214  */
215  assert(image != (const Image *) NULL);
216  assert(image->signature == MagickCoreSignature);
217  if (image->debug != MagickFalse)
218  (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
219  assert(exception != (ExceptionInfo *) NULL);
220  assert(exception->signature == MagickCoreSignature);
221  assert(chop_info != (RectangleInfo *) NULL);
222  if (((chop_info->x+(ssize_t) chop_info->width) < 0) ||
223  ((chop_info->y+(ssize_t) chop_info->height) < 0) ||
224  (chop_info->x > (ssize_t) image->columns) ||
225  (chop_info->y > (ssize_t) image->rows))
226  ThrowImageException(OptionWarning,"GeometryDoesNotContainImage");
227  extent=(*chop_info);
228  if ((extent.x+(ssize_t) extent.width) > (ssize_t) image->columns)
229  extent.width=(size_t) ((ssize_t) image->columns-extent.x);
230  if ((extent.y+(ssize_t) extent.height) > (ssize_t) image->rows)
231  extent.height=(size_t) ((ssize_t) image->rows-extent.y);
232  if (extent.x < 0)
233  {
234  extent.width-=(size_t) (-extent.x);
235  extent.x=0;
236  }
237  if (extent.y < 0)
238  {
239  extent.height-=(size_t) (-extent.y);
240  extent.y=0;
241  }
242  chop_image=CloneImage(image,image->columns-extent.width,image->rows-
243  extent.height,MagickTrue,exception);
244  if (chop_image == (Image *) NULL)
245  return((Image *) NULL);
246  /*
247  Extract chop image.
248  */
249  status=MagickTrue;
250  progress=0;
251  image_view=AcquireVirtualCacheView(image,exception);
252  chop_view=AcquireAuthenticCacheView(chop_image,exception);
253 #if defined(MAGICKCORE_OPENMP_SUPPORT)
254  #pragma omp parallel for schedule(static,4) shared(status) \
255  magick_number_threads(image,chop_image,extent.y,1)
256 #endif
257  for (y=0; y < (ssize_t) extent.y; y++)
258  {
259  register const Quantum
260  *magick_restrict p;
261 
262  register ssize_t
263  x;
264 
265  register Quantum
266  *magick_restrict q;
267 
268  if (status == MagickFalse)
269  continue;
270  p=GetCacheViewVirtualPixels(image_view,0,y,image->columns,1,exception);
271  q=QueueCacheViewAuthenticPixels(chop_view,0,y,chop_image->columns,1,
272  exception);
273  if ((p == (const Quantum *) NULL) || (q == (Quantum *) NULL))
274  {
275  status=MagickFalse;
276  continue;
277  }
278  for (x=0; x < (ssize_t) image->columns; x++)
279  {
280  if ((x < extent.x) || (x >= (ssize_t) (extent.x+extent.width)))
281  {
282  register ssize_t
283  i;
284 
285  for (i=0; i < (ssize_t) GetPixelChannels(image); i++)
286  {
287  PixelChannel channel = GetPixelChannelChannel(image,i);
288  PixelTrait traits = GetPixelChannelTraits(image,channel);
289  PixelTrait chop_traits=GetPixelChannelTraits(chop_image,channel);
290  if ((traits == UndefinedPixelTrait) ||
291  (chop_traits == UndefinedPixelTrait))
292  continue;
293  SetPixelChannel(chop_image,channel,p[i],q);
294  }
295  q+=GetPixelChannels(chop_image);
296  }
297  p+=GetPixelChannels(image);
298  }
299  if (SyncCacheViewAuthenticPixels(chop_view,exception) == MagickFalse)
300  status=MagickFalse;
301  if (image->progress_monitor != (MagickProgressMonitor) NULL)
302  {
304  proceed;
305 
306 #if defined(MAGICKCORE_OPENMP_SUPPORT)
307  #pragma omp critical (MagickCore_ChopImage)
308 #endif
309  proceed=SetImageProgress(image,ChopImageTag,progress++,image->rows);
310  if (proceed == MagickFalse)
311  status=MagickFalse;
312  }
313  }
314  /*
315  Extract chop image.
316  */
317 #if defined(MAGICKCORE_OPENMP_SUPPORT)
318  #pragma omp parallel for schedule(static,4) shared(progress,status) \
319  magick_number_threads(image,chop_image,image->rows-(extent.y+extent.height),1)
320 #endif
321  for (y=0; y < (ssize_t) (image->rows-(extent.y+extent.height)); y++)
322  {
323  register const Quantum
324  *magick_restrict p;
325 
326  register ssize_t
327  x;
328 
329  register Quantum
330  *magick_restrict q;
331 
332  if (status == MagickFalse)
333  continue;
334  p=GetCacheViewVirtualPixels(image_view,0,extent.y+extent.height+y,
335  image->columns,1,exception);
336  q=QueueCacheViewAuthenticPixels(chop_view,0,extent.y+y,chop_image->columns,
337  1,exception);
338  if ((p == (const Quantum *) NULL) || (q == (Quantum *) NULL))
339  {
340  status=MagickFalse;
341  continue;
342  }
343  for (x=0; x < (ssize_t) image->columns; x++)
344  {
345  if ((x < extent.x) || (x >= (ssize_t) (extent.x+extent.width)))
346  {
347  register ssize_t
348  i;
349 
350  for (i=0; i < (ssize_t) GetPixelChannels(image); i++)
351  {
352  PixelChannel channel = GetPixelChannelChannel(image,i);
353  PixelTrait traits = GetPixelChannelTraits(image,channel);
354  PixelTrait chop_traits=GetPixelChannelTraits(chop_image,channel);
355  if ((traits == UndefinedPixelTrait) ||
356  (chop_traits == UndefinedPixelTrait))
357  continue;
358  SetPixelChannel(chop_image,channel,p[i],q);
359  }
360  q+=GetPixelChannels(chop_image);
361  }
362  p+=GetPixelChannels(image);
363  }
364  if (SyncCacheViewAuthenticPixels(chop_view,exception) == MagickFalse)
365  status=MagickFalse;
366  if (image->progress_monitor != (MagickProgressMonitor) NULL)
367  {
369  proceed;
370 
371 #if defined(MAGICKCORE_OPENMP_SUPPORT)
372  #pragma omp critical (MagickCore_ChopImage)
373 #endif
374  proceed=SetImageProgress(image,ChopImageTag,progress++,image->rows);
375  if (proceed == MagickFalse)
376  status=MagickFalse;
377  }
378  }
379  chop_view=DestroyCacheView(chop_view);
380  image_view=DestroyCacheView(image_view);
381  chop_image->type=image->type;
382  if (status == MagickFalse)
383  chop_image=DestroyImage(chop_image);
384  return(chop_image);
385 }
386 
387 /*
388 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
389 % %
390 % %
391 % %
392 + C o n s o l i d a t e C M Y K I m a g e %
393 % %
394 % %
395 % %
396 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
397 %
398 % ConsolidateCMYKImage() consolidates separate C, M, Y, and K planes into a
399 % single image.
400 %
401 % The format of the ConsolidateCMYKImage method is:
402 %
403 % Image *ConsolidateCMYKImage(const Image *image,ExceptionInfo *exception)
404 %
405 % A description of each parameter follows:
406 %
407 % o image: the image sequence.
408 %
409 % o exception: return any errors or warnings in this structure.
410 %
411 */
413  ExceptionInfo *exception)
414 {
415  CacheView
416  *cmyk_view,
417  *image_view;
418 
419  Image
420  *cmyk_image,
421  *cmyk_images;
422 
423  register ssize_t
424  j;
425 
426  ssize_t
427  y;
428 
429  /*
430  Consolidate separate C, M, Y, and K planes into a single image.
431  */
432  assert(images != (Image *) NULL);
433  assert(images->signature == MagickCoreSignature);
434  if (images->debug != MagickFalse)
435  (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",images->filename);
436  assert(exception != (ExceptionInfo *) NULL);
437  assert(exception->signature == MagickCoreSignature);
438  cmyk_images=NewImageList();
439  for (j=0; j < (ssize_t) GetImageListLength(images); j+=4)
440  {
441  register ssize_t
442  i;
443 
444  assert(images != (Image *) NULL);
445  cmyk_image=CloneImage(images,images->columns,images->rows,MagickTrue,
446  exception);
447  if (cmyk_image == (Image *) NULL)
448  break;
449  if (SetImageStorageClass(cmyk_image,DirectClass,exception) == MagickFalse)
450  break;
451  (void) SetImageColorspace(cmyk_image,CMYKColorspace,exception);
452  for (i=0; i < 4; i++)
453  {
454  image_view=AcquireVirtualCacheView(images,exception);
455  cmyk_view=AcquireAuthenticCacheView(cmyk_image,exception);
456  for (y=0; y < (ssize_t) images->rows; y++)
457  {
458  register const Quantum
459  *magick_restrict p;
460 
461  register ssize_t
462  x;
463 
464  register Quantum
465  *magick_restrict q;
466 
467  p=GetCacheViewVirtualPixels(image_view,0,y,images->columns,1,exception);
468  q=QueueCacheViewAuthenticPixels(cmyk_view,0,y,cmyk_image->columns,1,
469  exception);
470  if ((p == (const Quantum *) NULL) || (q == (Quantum *) NULL))
471  break;
472  for (x=0; x < (ssize_t) images->columns; x++)
473  {
474  Quantum
475  pixel;
476 
477  pixel=QuantumRange-GetPixelIntensity(images,p);
478  switch (i)
479  {
480  case 0: SetPixelCyan(cmyk_image,pixel,q); break;
481  case 1: SetPixelMagenta(cmyk_image,pixel,q); break;
482  case 2: SetPixelYellow(cmyk_image,pixel,q); break;
483  case 3: SetPixelBlack(cmyk_image,pixel,q); break;
484  default: break;
485  }
486  p+=GetPixelChannels(images);
487  q+=GetPixelChannels(cmyk_image);
488  }
489  if (SyncCacheViewAuthenticPixels(cmyk_view,exception) == MagickFalse)
490  break;
491  }
492  cmyk_view=DestroyCacheView(cmyk_view);
493  image_view=DestroyCacheView(image_view);
494  images=GetNextImageInList(images);
495  if (images == (Image *) NULL)
496  break;
497  }
498  AppendImageToList(&cmyk_images,cmyk_image);
499  }
500  return(cmyk_images);
501 }
502 
503 /*
504 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
505 % %
506 % %
507 % %
508 % C r o p I m a g e %
509 % %
510 % %
511 % %
512 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
513 %
514 % CropImage() extracts a region of the image starting at the offset defined
515 % by geometry. Region must be fully defined, and no special handling of
516 % geometry flags is performed.
517 %
518 % The format of the CropImage method is:
519 %
520 % Image *CropImage(const Image *image,const RectangleInfo *geometry,
521 % ExceptionInfo *exception)
522 %
523 % A description of each parameter follows:
524 %
525 % o image: the image.
526 %
527 % o geometry: Define the region of the image to crop with members
528 % x, y, width, and height.
529 %
530 % o exception: return any errors or warnings in this structure.
531 %
532 */
533 MagickExport Image *CropImage(const Image *image,const RectangleInfo *geometry,
534  ExceptionInfo *exception)
535 {
536 #define CropImageTag "Crop/Image"
537 
538  CacheView
539  *crop_view,
540  *image_view;
541 
542  Image
543  *crop_image;
544 
546  status;
547 
549  progress;
550 
551  OffsetInfo
552  offset;
553 
555  bounding_box,
556  page;
557 
558  ssize_t
559  y;
560 
561  /*
562  Check crop geometry.
563  */
564  assert(image != (const Image *) NULL);
565  assert(image->signature == MagickCoreSignature);
566  if (image->debug != MagickFalse)
567  (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
568  assert(geometry != (const RectangleInfo *) NULL);
569  assert(exception != (ExceptionInfo *) NULL);
570  assert(exception->signature == MagickCoreSignature);
571  bounding_box=image->page;
572  if ((bounding_box.width == 0) || (bounding_box.height == 0))
573  {
574  bounding_box.width=image->columns;
575  bounding_box.height=image->rows;
576  }
577  page=(*geometry);
578  if (page.width == 0)
579  page.width=bounding_box.width;
580  if (page.height == 0)
581  page.height=bounding_box.height;
582  if (((bounding_box.x-page.x) >= (ssize_t) page.width) ||
583  ((bounding_box.y-page.y) >= (ssize_t) page.height) ||
584  ((page.x-bounding_box.x) > (ssize_t) image->columns) ||
585  ((page.y-bounding_box.y) > (ssize_t) image->rows))
586  {
587  /*
588  Crop is not within virtual canvas, return 1 pixel transparent image.
589  */
591  "GeometryDoesNotContainImage","`%s'",image->filename);
592  crop_image=CloneImage(image,1,1,MagickTrue,exception);
593  if (crop_image == (Image *) NULL)
594  return((Image *) NULL);
596  crop_image->alpha_trait=BlendPixelTrait;
597  (void) SetImageBackgroundColor(crop_image,exception);
598  crop_image->page=bounding_box;
599  crop_image->page.x=(-1);
600  crop_image->page.y=(-1);
601  if (crop_image->dispose == BackgroundDispose)
602  crop_image->dispose=NoneDispose;
603  return(crop_image);
604  }
605  if ((page.x < 0) && (bounding_box.x >= 0))
606  {
607  page.width+=page.x-bounding_box.x;
608  page.x=0;
609  }
610  else
611  {
612  page.width-=bounding_box.x-page.x;
613  page.x-=bounding_box.x;
614  if (page.x < 0)
615  page.x=0;
616  }
617  if ((page.y < 0) && (bounding_box.y >= 0))
618  {
619  page.height+=page.y-bounding_box.y;
620  page.y=0;
621  }
622  else
623  {
624  page.height-=bounding_box.y-page.y;
625  page.y-=bounding_box.y;
626  if (page.y < 0)
627  page.y=0;
628  }
629  if ((page.x+(ssize_t) page.width) > (ssize_t) image->columns)
630  page.width=image->columns-page.x;
631  if ((geometry->width != 0) && (page.width > geometry->width))
632  page.width=geometry->width;
633  if ((page.y+(ssize_t) page.height) > (ssize_t) image->rows)
634  page.height=image->rows-page.y;
635  if ((geometry->height != 0) && (page.height > geometry->height))
636  page.height=geometry->height;
637  bounding_box.x+=page.x;
638  bounding_box.y+=page.y;
639  if ((page.width == 0) || (page.height == 0))
640  {
642  "GeometryDoesNotContainImage","`%s'",image->filename);
643  return((Image *) NULL);
644  }
645  /*
646  Initialize crop image attributes.
647  */
648  crop_image=CloneImage(image,page.width,page.height,MagickTrue,exception);
649  if (crop_image == (Image *) NULL)
650  return((Image *) NULL);
651  crop_image->page.width=image->page.width;
652  crop_image->page.height=image->page.height;
653  offset.x=(ssize_t) (bounding_box.x+bounding_box.width);
654  offset.y=(ssize_t) (bounding_box.y+bounding_box.height);
655  if ((offset.x > (ssize_t) image->page.width) ||
656  (offset.y > (ssize_t) image->page.height))
657  {
658  crop_image->page.width=bounding_box.width;
659  crop_image->page.height=bounding_box.height;
660  }
661  crop_image->page.x=bounding_box.x;
662  crop_image->page.y=bounding_box.y;
663  /*
664  Crop image.
665  */
666  status=MagickTrue;
667  progress=0;
668  image_view=AcquireVirtualCacheView(image,exception);
669  crop_view=AcquireAuthenticCacheView(crop_image,exception);
670 #if defined(MAGICKCORE_OPENMP_SUPPORT)
671  #pragma omp parallel for schedule(static,4) shared(status) \
672  magick_number_threads(image,crop_image,crop_image->rows,1)
673 #endif
674  for (y=0; y < (ssize_t) crop_image->rows; y++)
675  {
676  register const Quantum
677  *magick_restrict p;
678 
679  register Quantum
680  *magick_restrict q;
681 
682  register ssize_t
683  x;
684 
685  if (status == MagickFalse)
686  continue;
687  p=GetCacheViewVirtualPixels(image_view,page.x,page.y+y,crop_image->columns,
688  1,exception);
689  q=QueueCacheViewAuthenticPixels(crop_view,0,y,crop_image->columns,1,
690  exception);
691  if ((p == (const Quantum *) NULL) || (q == (Quantum *) NULL))
692  {
693  status=MagickFalse;
694  continue;
695  }
696  for (x=0; x < (ssize_t) crop_image->columns; x++)
697  {
698  register ssize_t
699  i;
700 
701  if (GetPixelWriteMask(image,p) <= (QuantumRange/2))
702  {
703  SetPixelBackgoundColor(crop_image,q);
704  p+=GetPixelChannels(image);
705  q+=GetPixelChannels(crop_image);
706  continue;
707  }
708  for (i=0; i < (ssize_t) GetPixelChannels(image); i++)
709  {
710  PixelChannel channel = GetPixelChannelChannel(image,i);
711  PixelTrait traits = GetPixelChannelTraits(image,channel);
712  PixelTrait crop_traits=GetPixelChannelTraits(crop_image,channel);
713  if ((traits == UndefinedPixelTrait) ||
714  (crop_traits == UndefinedPixelTrait))
715  continue;
716  SetPixelChannel(crop_image,channel,p[i],q);
717  }
718  p+=GetPixelChannels(image);
719  q+=GetPixelChannels(crop_image);
720  }
721  if (SyncCacheViewAuthenticPixels(crop_view,exception) == MagickFalse)
722  status=MagickFalse;
723  if (image->progress_monitor != (MagickProgressMonitor) NULL)
724  {
726  proceed;
727 
728 #if defined(MAGICKCORE_OPENMP_SUPPORT)
729  #pragma omp critical (MagickCore_CropImage)
730 #endif
731  proceed=SetImageProgress(image,CropImageTag,progress++,image->rows);
732  if (proceed == MagickFalse)
733  status=MagickFalse;
734  }
735  }
736  crop_view=DestroyCacheView(crop_view);
737  image_view=DestroyCacheView(image_view);
738  crop_image->type=image->type;
739  if (status == MagickFalse)
740  crop_image=DestroyImage(crop_image);
741  return(crop_image);
742 }
743 
744 /*
745 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
746 % %
747 % %
748 % %
749 % C r o p I m a g e T o T i l e s %
750 % %
751 % %
752 % %
753 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
754 %
755 % CropImageToTiles() crops a single image, into a possible list of tiles.
756 % This may include a single sub-region of the image. This basically applies
757 % all the normal geometry flags for Crop.
758 %
759 % Image *CropImageToTiles(const Image *image,
760 % const RectangleInfo *crop_geometry, ExceptionInfo *exception)
761 %
762 % A description of each parameter follows:
763 %
764 % o image: the image The transformed image is returned as this parameter.
765 %
766 % o crop_geometry: A crop geometry string.
767 %
768 % o exception: return any errors or warnings in this structure.
769 %
770 */
771 
772 static inline double MagickRound(double x)
773 {
774  /*
775  Round the fraction to nearest integer.
776  */
777  if ((x-floor(x)) < (ceil(x)-x))
778  return(floor(x));
779  return(ceil(x));
780 }
781 
783  const char *crop_geometry,ExceptionInfo *exception)
784 {
785  Image
786  *next,
787  *crop_image;
788 
790  flags;
791 
793  geometry;
794 
795  assert(image != (Image *) NULL);
796  assert(image->signature == MagickCoreSignature);
797  if (image->debug != MagickFalse)
798  (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
799  crop_image=NewImageList();
800  next=NewImageList();
801  flags=ParseGravityGeometry(image,crop_geometry,&geometry,exception);
802  if ((flags & AreaValue) != 0)
803  {
804  PointInfo
805  delta,
806  offset;
807 
809  crop;
810 
811  size_t
812  height,
813  width;
814 
815  /*
816  Crop into NxM tiles (@ flag).
817  */
818  width=image->columns;
819  height=image->rows;
820  if (geometry.width == 0)
821  geometry.width=1;
822  if (geometry.height == 0)
823  geometry.height=1;
824  if ((flags & AspectValue) == 0)
825  {
826  width-=(geometry.x < 0 ? -1 : 1)*geometry.x;
827  height-=(geometry.y < 0 ? -1 : 1)*geometry.y;
828  }
829  else
830  {
831  width+=(geometry.x < 0 ? -1 : 1)*geometry.x;
832  height+=(geometry.y < 0 ? -1 : 1)*geometry.y;
833  }
834  delta.x=(double) width/geometry.width;
835  delta.y=(double) height/geometry.height;
836  if (delta.x < 1.0)
837  delta.x=1.0;
838  if (delta.y < 1.0)
839  delta.y=1.0;
840  for (offset.y=0; offset.y < (double) height; )
841  {
842  if ((flags & AspectValue) == 0)
843  {
844  crop.y=(ssize_t) MagickRound((double) (offset.y-
845  (geometry.y > 0 ? 0 : geometry.y)));
846  offset.y+=delta.y; /* increment now to find width */
847  crop.height=(size_t) MagickRound((double) (offset.y+
848  (geometry.y < 0 ? 0 : geometry.y)));
849  }
850  else
851  {
852  crop.y=(ssize_t) MagickRound((double) (offset.y-
853  (geometry.y > 0 ? geometry.y : 0)));
854  offset.y+=delta.y; /* increment now to find width */
855  crop.height=(size_t) MagickRound((double)
856  (offset.y+(geometry.y < -1 ? geometry.y : 0)));
857  }
858  crop.height-=crop.y;
859  crop.y+=image->page.y;
860  for (offset.x=0; offset.x < (double) width; )
861  {
862  if ((flags & AspectValue) == 0)
863  {
864  crop.x=(ssize_t) MagickRound((double) (offset.x-
865  (geometry.x > 0 ? 0 : geometry.x)));
866  offset.x+=delta.x; /* increment now to find height */
867  crop.width=(size_t) MagickRound((double) (offset.x+
868  (geometry.x < 0 ? 0 : geometry.x)));
869  }
870  else
871  {
872  crop.x=(ssize_t) MagickRound((double) (offset.x-
873  (geometry.x > 0 ? geometry.x : 0)));
874  offset.x+=delta.x; /* increment now to find height */
875  crop.width=(size_t) MagickRound((double) (offset.x+
876  (geometry.x < 0 ? geometry.x : 0)));
877  }
878  crop.width-=crop.x;
879  crop.x+=image->page.x;
880  next=CropImage(image,&crop,exception);
881  if (next != (Image *) NULL)
882  AppendImageToList(&crop_image,next);
883  }
884  }
885  ClearMagickException(exception);
886  return(crop_image);
887  }
888  if (((geometry.width == 0) && (geometry.height == 0)) ||
889  ((flags & XValue) != 0) || ((flags & YValue) != 0))
890  {
891  /*
892  Crop a single region at +X+Y.
893  */
894  crop_image=CropImage(image,&geometry,exception);
895  if ((crop_image != (Image *) NULL) && ((flags & AspectValue) != 0))
896  {
897  crop_image->page.width=geometry.width;
898  crop_image->page.height=geometry.height;
899  crop_image->page.x-=geometry.x;
900  crop_image->page.y-=geometry.y;
901  }
902  return(crop_image);
903  }
904  if ((image->columns > geometry.width) || (image->rows > geometry.height))
905  {
907  page;
908 
909  size_t
910  height,
911  width;
912 
913  ssize_t
914  x,
915  y;
916 
917  /*
918  Crop into tiles of fixed size WxH.
919  */
920  page=image->page;
921  if (page.width == 0)
922  page.width=image->columns;
923  if (page.height == 0)
924  page.height=image->rows;
925  width=geometry.width;
926  if (width == 0)
927  width=page.width;
928  height=geometry.height;
929  if (height == 0)
930  height=page.height;
931  next=NewImageList();
932  for (y=0; y < (ssize_t) page.height; y+=(ssize_t) height)
933  {
934  for (x=0; x < (ssize_t) page.width; x+=(ssize_t) width)
935  {
936  geometry.width=width;
937  geometry.height=height;
938  geometry.x=x;
939  geometry.y=y;
940  next=CropImage(image,&geometry,exception);
941  if (next == (Image *) NULL)
942  break;
943  AppendImageToList(&crop_image,next);
944  }
945  if (next == (Image *) NULL)
946  break;
947  }
948  return(crop_image);
949  }
950  return(CloneImage(image,0,0,MagickTrue,exception));
951 }
952 
953 /*
954 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
955 % %
956 % %
957 % %
958 % E x c e r p t I m a g e %
959 % %
960 % %
961 % %
962 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
963 %
964 % ExcerptImage() returns a excerpt of the image as defined by the geometry.
965 %
966 % The format of the ExcerptImage method is:
967 %
968 % Image *ExcerptImage(const Image *image,const RectangleInfo *geometry,
969 % ExceptionInfo *exception)
970 %
971 % A description of each parameter follows:
972 %
973 % o image: the image.
974 %
975 % o geometry: Define the region of the image to extend with members
976 % x, y, width, and height.
977 %
978 % o exception: return any errors or warnings in this structure.
979 %
980 */
982  const RectangleInfo *geometry,ExceptionInfo *exception)
983 {
984 #define ExcerptImageTag "Excerpt/Image"
985 
986  CacheView
987  *excerpt_view,
988  *image_view;
989 
990  Image
991  *excerpt_image;
992 
994  status;
995 
997  progress;
998 
999  ssize_t
1000  y;
1001 
1002  /*
1003  Allocate excerpt image.
1004  */
1005  assert(image != (const Image *) NULL);
1006  assert(image->signature == MagickCoreSignature);
1007  if (image->debug != MagickFalse)
1008  (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
1009  assert(geometry != (const RectangleInfo *) NULL);
1010  assert(exception != (ExceptionInfo *) NULL);
1011  assert(exception->signature == MagickCoreSignature);
1012  excerpt_image=CloneImage(image,geometry->width,geometry->height,MagickTrue,
1013  exception);
1014  if (excerpt_image == (Image *) NULL)
1015  return((Image *) NULL);
1016  /*
1017  Excerpt each row.
1018  */
1019  status=MagickTrue;
1020  progress=0;
1021  image_view=AcquireVirtualCacheView(image,exception);
1022  excerpt_view=AcquireAuthenticCacheView(excerpt_image,exception);
1023 #if defined(MAGICKCORE_OPENMP_SUPPORT)
1024  #pragma omp parallel for schedule(static,4) shared(progress,status) \
1025  magick_number_threads(image,excerpt_image,excerpt_image->rows,1)
1026 #endif
1027  for (y=0; y < (ssize_t) excerpt_image->rows; y++)
1028  {
1029  register const Quantum
1030  *magick_restrict p;
1031 
1032  register Quantum
1033  *magick_restrict q;
1034 
1035  register ssize_t
1036  x;
1037 
1038  if (status == MagickFalse)
1039  continue;
1040  p=GetCacheViewVirtualPixels(image_view,geometry->x,geometry->y+y,
1041  geometry->width,1,exception);
1042  q=GetCacheViewAuthenticPixels(excerpt_view,0,y,excerpt_image->columns,1,
1043  exception);
1044  if ((p == (const Quantum *) NULL) || (q == (Quantum *) NULL))
1045  {
1046  status=MagickFalse;
1047  continue;
1048  }
1049  for (x=0; x < (ssize_t) excerpt_image->columns; x++)
1050  {
1051  register ssize_t
1052  i;
1053 
1054  if (GetPixelWriteMask(image,p) <= (QuantumRange/2))
1055  {
1056  SetPixelBackgoundColor(excerpt_image,q);
1057  p+=GetPixelChannels(image);
1058  q+=GetPixelChannels(excerpt_image);
1059  continue;
1060  }
1061  for (i=0; i < (ssize_t) GetPixelChannels(image); i++)
1062  {
1063  PixelChannel channel = GetPixelChannelChannel(image,i);
1064  PixelTrait traits = GetPixelChannelTraits(image,channel);
1065  PixelTrait excerpt_traits=GetPixelChannelTraits(excerpt_image,channel);
1066  if ((traits == UndefinedPixelTrait) ||
1067  (excerpt_traits == UndefinedPixelTrait))
1068  continue;
1069  SetPixelChannel(excerpt_image,channel,p[i],q);
1070  }
1071  p+=GetPixelChannels(image);
1072  q+=GetPixelChannels(excerpt_image);
1073  }
1074  if (SyncCacheViewAuthenticPixels(excerpt_view,exception) == MagickFalse)
1075  status=MagickFalse;
1076  if (image->progress_monitor != (MagickProgressMonitor) NULL)
1077  {
1079  proceed;
1080 
1081 #if defined(MAGICKCORE_OPENMP_SUPPORT)
1082  #pragma omp critical (MagickCore_ExcerptImage)
1083 #endif
1084  proceed=SetImageProgress(image,ExcerptImageTag,progress++,image->rows);
1085  if (proceed == MagickFalse)
1086  status=MagickFalse;
1087  }
1088  }
1089  excerpt_view=DestroyCacheView(excerpt_view);
1090  image_view=DestroyCacheView(image_view);
1091  excerpt_image->type=image->type;
1092  if (status == MagickFalse)
1093  excerpt_image=DestroyImage(excerpt_image);
1094  return(excerpt_image);
1095 }
1096 
1097 /*
1098 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1099 % %
1100 % %
1101 % %
1102 % E x t e n t I m a g e %
1103 % %
1104 % %
1105 % %
1106 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1107 %
1108 % ExtentImage() extends the image as defined by the geometry, gravity, and
1109 % image background color. Set the (x,y) offset of the geometry to move the
1110 % original image relative to the extended image.
1111 %
1112 % The format of the ExtentImage method is:
1113 %
1114 % Image *ExtentImage(const Image *image,const RectangleInfo *geometry,
1115 % ExceptionInfo *exception)
1116 %
1117 % A description of each parameter follows:
1118 %
1119 % o image: the image.
1120 %
1121 % o geometry: Define the region of the image to extend with members
1122 % x, y, width, and height.
1123 %
1124 % o exception: return any errors or warnings in this structure.
1125 %
1126 */
1128  const RectangleInfo *geometry,ExceptionInfo *exception)
1129 {
1130  Image
1131  *extent_image;
1132 
1133  /*
1134  Allocate extent image.
1135  */
1136  assert(image != (const Image *) NULL);
1137  assert(image->signature == MagickCoreSignature);
1138  if (image->debug != MagickFalse)
1139  (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
1140  assert(geometry != (const RectangleInfo *) NULL);
1141  assert(exception != (ExceptionInfo *) NULL);
1142  assert(exception->signature == MagickCoreSignature);
1143  if ((image->columns == geometry->width) &&
1144  (image->rows == geometry->height) &&
1145  (geometry->x == 0) && (geometry->y == 0))
1146  return(CloneImage(image,0,0,MagickTrue,exception));
1147  extent_image=CloneImage(image,geometry->width,geometry->height,MagickTrue,
1148  exception);
1149  if (extent_image == (Image *) NULL)
1150  return((Image *) NULL);
1151  (void) SetImageBackgroundColor(extent_image,exception);
1152  (void) CompositeImage(extent_image,image,image->compose,MagickTrue,
1153  -geometry->x,-geometry->y,exception);
1154  return(extent_image);
1155 }
1156 
1157 /*
1158 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1159 % %
1160 % %
1161 % %
1162 % F l i p I m a g e %
1163 % %
1164 % %
1165 % %
1166 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1167 %
1168 % FlipImage() creates a vertical mirror image by reflecting the pixels
1169 % around the central x-axis.
1170 %
1171 % The format of the FlipImage method is:
1172 %
1173 % Image *FlipImage(const Image *image,ExceptionInfo *exception)
1174 %
1175 % A description of each parameter follows:
1176 %
1177 % o image: the image.
1178 %
1179 % o exception: return any errors or warnings in this structure.
1180 %
1181 */
1183 {
1184 #define FlipImageTag "Flip/Image"
1185 
1186  CacheView
1187  *flip_view,
1188  *image_view;
1189 
1190  Image
1191  *flip_image;
1192 
1194  status;
1195 
1197  progress;
1198 
1200  page;
1201 
1202  ssize_t
1203  y;
1204 
1205  assert(image != (const Image *) NULL);
1206  assert(image->signature == MagickCoreSignature);
1207  if (image->debug != MagickFalse)
1208  (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
1209  assert(exception != (ExceptionInfo *) NULL);
1210  assert(exception->signature == MagickCoreSignature);
1211  flip_image=CloneImage(image,image->columns,image->rows,MagickTrue,exception);
1212  if (flip_image == (Image *) NULL)
1213  return((Image *) NULL);
1214  /*
1215  Flip image.
1216  */
1217  status=MagickTrue;
1218  progress=0;
1219  page=image->page;
1220  image_view=AcquireVirtualCacheView(image,exception);
1221  flip_view=AcquireAuthenticCacheView(flip_image,exception);
1222 #if defined(MAGICKCORE_OPENMP_SUPPORT)
1223  #pragma omp parallel for schedule(static,4) shared(status) \
1224  magick_number_threads(image,flip_image,flip_image->rows,1)
1225 #endif
1226  for (y=0; y < (ssize_t) flip_image->rows; y++)
1227  {
1228  register const Quantum
1229  *magick_restrict p;
1230 
1231  register Quantum
1232  *magick_restrict q;
1233 
1234  register ssize_t
1235  x;
1236 
1237  if (status == MagickFalse)
1238  continue;
1239  p=GetCacheViewVirtualPixels(image_view,0,y,image->columns,1,exception);
1240  q=QueueCacheViewAuthenticPixels(flip_view,0,(ssize_t) (flip_image->rows-y-
1241  1),flip_image->columns,1,exception);
1242  if ((p == (const Quantum *) NULL) || (q == (Quantum *) NULL))
1243  {
1244  status=MagickFalse;
1245  continue;
1246  }
1247  for (x=0; x < (ssize_t) flip_image->columns; x++)
1248  {
1249  register ssize_t
1250  i;
1251 
1252  if (GetPixelWriteMask(image,p) <= (QuantumRange/2))
1253  {
1254  SetPixelBackgoundColor(flip_image,q);
1255  p+=GetPixelChannels(image);
1256  q+=GetPixelChannels(flip_image);
1257  continue;
1258  }
1259  for (i=0; i < (ssize_t) GetPixelChannels(image); i++)
1260  {
1261  PixelChannel channel = GetPixelChannelChannel(image,i);
1262  PixelTrait traits = GetPixelChannelTraits(image,channel);
1263  PixelTrait flip_traits=GetPixelChannelTraits(flip_image,channel);
1264  if ((traits == UndefinedPixelTrait) ||
1265  (flip_traits == UndefinedPixelTrait))
1266  continue;
1267  SetPixelChannel(flip_image,channel,p[i],q);
1268  }
1269  p+=GetPixelChannels(image);
1270  q+=GetPixelChannels(flip_image);
1271  }
1272  if (SyncCacheViewAuthenticPixels(flip_view,exception) == MagickFalse)
1273  status=MagickFalse;
1274  if (image->progress_monitor != (MagickProgressMonitor) NULL)
1275  {
1277  proceed;
1278 
1279 #if defined(MAGICKCORE_OPENMP_SUPPORT)
1280  #pragma omp critical (MagickCore_FlipImage)
1281 #endif
1282  proceed=SetImageProgress(image,FlipImageTag,progress++,image->rows);
1283  if (proceed == MagickFalse)
1284  status=MagickFalse;
1285  }
1286  }
1287  flip_view=DestroyCacheView(flip_view);
1288  image_view=DestroyCacheView(image_view);
1289  flip_image->type=image->type;
1290  if (page.height != 0)
1291  page.y=(ssize_t) (page.height-flip_image->rows-page.y);
1292  flip_image->page=page;
1293  if (status == MagickFalse)
1294  flip_image=DestroyImage(flip_image);
1295  return(flip_image);
1296 }
1297 
1298 /*
1299 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1300 % %
1301 % %
1302 % %
1303 % F l o p I m a g e %
1304 % %
1305 % %
1306 % %
1307 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1308 %
1309 % FlopImage() creates a horizontal mirror image by reflecting the pixels
1310 % around the central y-axis.
1311 %
1312 % The format of the FlopImage method is:
1313 %
1314 % Image *FlopImage(const Image *image,ExceptionInfo *exception)
1315 %
1316 % A description of each parameter follows:
1317 %
1318 % o image: the image.
1319 %
1320 % o exception: return any errors or warnings in this structure.
1321 %
1322 */
1324 {
1325 #define FlopImageTag "Flop/Image"
1326 
1327  CacheView
1328  *flop_view,
1329  *image_view;
1330 
1331  Image
1332  *flop_image;
1333 
1335  status;
1336 
1338  progress;
1339 
1341  page;
1342 
1343  ssize_t
1344  y;
1345 
1346  assert(image != (const Image *) NULL);
1347  assert(image->signature == MagickCoreSignature);
1348  if (image->debug != MagickFalse)
1349  (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
1350  assert(exception != (ExceptionInfo *) NULL);
1351  assert(exception->signature == MagickCoreSignature);
1352  flop_image=CloneImage(image,image->columns,image->rows,MagickTrue,exception);
1353  if (flop_image == (Image *) NULL)
1354  return((Image *) NULL);
1355  /*
1356  Flop each row.
1357  */
1358  status=MagickTrue;
1359  progress=0;
1360  page=image->page;
1361  image_view=AcquireVirtualCacheView(image,exception);
1362  flop_view=AcquireAuthenticCacheView(flop_image,exception);
1363 #if defined(MAGICKCORE_OPENMP_SUPPORT)
1364  #pragma omp parallel for schedule(static,4) shared(status) \
1365  magick_number_threads(image,flop_image,flop_image->rows,1)
1366 #endif
1367  for (y=0; y < (ssize_t) flop_image->rows; y++)
1368  {
1369  register const Quantum
1370  *magick_restrict p;
1371 
1372  register ssize_t
1373  x;
1374 
1375  register Quantum
1376  *magick_restrict q;
1377 
1378  if (status == MagickFalse)
1379  continue;
1380  p=GetCacheViewVirtualPixels(image_view,0,y,image->columns,1,exception);
1381  q=QueueCacheViewAuthenticPixels(flop_view,0,y,flop_image->columns,1,
1382  exception);
1383  if ((p == (const Quantum *) NULL) || (q == (Quantum *) NULL))
1384  {
1385  status=MagickFalse;
1386  continue;
1387  }
1388  q+=GetPixelChannels(flop_image)*flop_image->columns;
1389  for (x=0; x < (ssize_t) flop_image->columns; x++)
1390  {
1391  register ssize_t
1392  i;
1393 
1394  q-=GetPixelChannels(flop_image);
1395  if (GetPixelWriteMask(image,p) <= (QuantumRange/2))
1396  {
1397  p+=GetPixelChannels(image);
1398  continue;
1399  }
1400  for (i=0; i < (ssize_t) GetPixelChannels(image); i++)
1401  {
1402  PixelChannel channel = GetPixelChannelChannel(image,i);
1403  PixelTrait traits = GetPixelChannelTraits(image,channel);
1404  PixelTrait flop_traits=GetPixelChannelTraits(flop_image,channel);
1405  if ((traits == UndefinedPixelTrait) ||
1406  (flop_traits == UndefinedPixelTrait))
1407  continue;
1408  SetPixelChannel(flop_image,channel,p[i],q);
1409  }
1410  p+=GetPixelChannels(image);
1411  }
1412  if (SyncCacheViewAuthenticPixels(flop_view,exception) == MagickFalse)
1413  status=MagickFalse;
1414  if (image->progress_monitor != (MagickProgressMonitor) NULL)
1415  {
1417  proceed;
1418 
1419 #if defined(MAGICKCORE_OPENMP_SUPPORT)
1420  #pragma omp critical (MagickCore_FlopImage)
1421 #endif
1422  proceed=SetImageProgress(image,FlopImageTag,progress++,image->rows);
1423  if (proceed == MagickFalse)
1424  status=MagickFalse;
1425  }
1426  }
1427  flop_view=DestroyCacheView(flop_view);
1428  image_view=DestroyCacheView(image_view);
1429  flop_image->type=image->type;
1430  if (page.width != 0)
1431  page.x=(ssize_t) (page.width-flop_image->columns-page.x);
1432  flop_image->page=page;
1433  if (status == MagickFalse)
1434  flop_image=DestroyImage(flop_image);
1435  return(flop_image);
1436 }
1437 
1438 /*
1439 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1440 % %
1441 % %
1442 % %
1443 % R o l l I m a g e %
1444 % %
1445 % %
1446 % %
1447 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1448 %
1449 % RollImage() offsets an image as defined by x_offset and y_offset.
1450 %
1451 % The format of the RollImage method is:
1452 %
1453 % Image *RollImage(const Image *image,const ssize_t x_offset,
1454 % const ssize_t y_offset,ExceptionInfo *exception)
1455 %
1456 % A description of each parameter follows:
1457 %
1458 % o image: the image.
1459 %
1460 % o x_offset: the number of columns to roll in the horizontal direction.
1461 %
1462 % o y_offset: the number of rows to roll in the vertical direction.
1463 %
1464 % o exception: return any errors or warnings in this structure.
1465 %
1466 */
1467 
1468 static MagickBooleanType CopyImageRegion(Image *destination,const Image *source, const size_t columns,const size_t rows,const ssize_t sx,const ssize_t sy,
1469  const ssize_t dx,const ssize_t dy,ExceptionInfo *exception)
1470 {
1471  CacheView
1472  *source_view,
1473  *destination_view;
1474 
1476  status;
1477 
1478  ssize_t
1479  y;
1480 
1481  if (columns == 0)
1482  return(MagickTrue);
1483  status=MagickTrue;
1484  source_view=AcquireVirtualCacheView(source,exception);
1485  destination_view=AcquireAuthenticCacheView(destination,exception);
1486 #if defined(MAGICKCORE_OPENMP_SUPPORT)
1487  #pragma omp parallel for schedule(static,4) shared(status) \
1488  magick_number_threads(source,destination,rows,1)
1489 #endif
1490  for (y=0; y < (ssize_t) rows; y++)
1491  {
1493  sync;
1494 
1495  register const Quantum
1496  *magick_restrict p;
1497 
1498  register Quantum
1499  *magick_restrict q;
1500 
1501  register ssize_t
1502  x;
1503 
1504  /*
1505  Transfer scanline.
1506  */
1507  if (status == MagickFalse)
1508  continue;
1509  p=GetCacheViewVirtualPixels(source_view,sx,sy+y,columns,1,exception);
1510  q=GetCacheViewAuthenticPixels(destination_view,dx,dy+y,columns,1,exception);
1511  if ((p == (const Quantum *) NULL) || (q == (Quantum *) NULL))
1512  {
1513  status=MagickFalse;
1514  continue;
1515  }
1516  for (x=0; x < (ssize_t) columns; x++)
1517  {
1518  register ssize_t
1519  i;
1520 
1521  if (GetPixelWriteMask(source,p) <= (QuantumRange/2))
1522  {
1523  SetPixelBackgoundColor(destination,q);
1524  p+=GetPixelChannels(source);
1525  q+=GetPixelChannels(destination);
1526  continue;
1527  }
1528  for (i=0; i < (ssize_t) GetPixelChannels(source); i++)
1529  {
1530  PixelChannel channel = GetPixelChannelChannel(source,i);
1531  PixelTrait source_traits=GetPixelChannelTraits(source,channel);
1532  PixelTrait destination_traits=GetPixelChannelTraits(destination,
1533  channel);
1534  if ((source_traits == UndefinedPixelTrait) ||
1535  (destination_traits == UndefinedPixelTrait))
1536  continue;
1537  SetPixelChannel(destination,channel,p[i],q);
1538  }
1539  p+=GetPixelChannels(source);
1540  q+=GetPixelChannels(destination);
1541  }
1542  sync=SyncCacheViewAuthenticPixels(destination_view,exception);
1543  if (sync == MagickFalse)
1544  status=MagickFalse;
1545  }
1546  destination_view=DestroyCacheView(destination_view);
1547  source_view=DestroyCacheView(source_view);
1548  return(status);
1549 }
1550 
1551 MagickExport Image *RollImage(const Image *image,const ssize_t x_offset,
1552  const ssize_t y_offset,ExceptionInfo *exception)
1553 {
1554 #define RollImageTag "Roll/Image"
1555 
1556  Image
1557  *roll_image;
1558 
1560  status;
1561 
1563  offset;
1564 
1565  /*
1566  Initialize roll image attributes.
1567  */
1568  assert(image != (const Image *) NULL);
1569  assert(image->signature == MagickCoreSignature);
1570  if (image->debug != MagickFalse)
1571  (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
1572  assert(exception != (ExceptionInfo *) NULL);
1573  assert(exception->signature == MagickCoreSignature);
1574  roll_image=CloneImage(image,image->columns,image->rows,MagickTrue,exception);
1575  if (roll_image == (Image *) NULL)
1576  return((Image *) NULL);
1577  offset.x=x_offset;
1578  offset.y=y_offset;
1579  while (offset.x < 0)
1580  offset.x+=(ssize_t) image->columns;
1581  while (offset.x >= (ssize_t) image->columns)
1582  offset.x-=(ssize_t) image->columns;
1583  while (offset.y < 0)
1584  offset.y+=(ssize_t) image->rows;
1585  while (offset.y >= (ssize_t) image->rows)
1586  offset.y-=(ssize_t) image->rows;
1587  /*
1588  Roll image.
1589  */
1590  status=CopyImageRegion(roll_image,image,(size_t) offset.x,
1591  (size_t) offset.y,(ssize_t) image->columns-offset.x,(ssize_t) image->rows-
1592  offset.y,0,0,exception);
1593  (void) SetImageProgress(image,RollImageTag,0,3);
1594  status&=CopyImageRegion(roll_image,image,image->columns-offset.x,
1595  (size_t) offset.y,0,(ssize_t) image->rows-offset.y,offset.x,0,
1596  exception);
1597  (void) SetImageProgress(image,RollImageTag,1,3);
1598  status&=CopyImageRegion(roll_image,image,(size_t) offset.x,image->rows-
1599  offset.y,(ssize_t) image->columns-offset.x,0,0,offset.y,exception);
1600  (void) SetImageProgress(image,RollImageTag,2,3);
1601  status&=CopyImageRegion(roll_image,image,image->columns-offset.x,image->rows-
1602  offset.y,0,0,offset.x,offset.y,exception);
1603  (void) SetImageProgress(image,RollImageTag,3,3);
1604  roll_image->type=image->type;
1605  if (status == MagickFalse)
1606  roll_image=DestroyImage(roll_image);
1607  return(roll_image);
1608 }
1609 
1610 /*
1611 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1612 % %
1613 % %
1614 % %
1615 % S h a v e I m a g e %
1616 % %
1617 % %
1618 % %
1619 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1620 %
1621 % ShaveImage() shaves pixels from the image edges. It allocates the memory
1622 % necessary for the new Image structure and returns a pointer to the new
1623 % image.
1624 %
1625 % The format of the ShaveImage method is:
1626 %
1627 % Image *ShaveImage(const Image *image,const RectangleInfo *shave_info,
1628 % ExceptionInfo *exception)
1629 %
1630 % A description of each parameter follows:
1631 %
1632 % o shave_image: Method ShaveImage returns a pointer to the shaved
1633 % image. A null image is returned if there is a memory shortage or
1634 % if the image width or height is zero.
1635 %
1636 % o image: the image.
1637 %
1638 % o shave_info: Specifies a pointer to a RectangleInfo which defines the
1639 % region of the image to crop.
1640 %
1641 % o exception: return any errors or warnings in this structure.
1642 %
1643 */
1645  const RectangleInfo *shave_info,ExceptionInfo *exception)
1646 {
1647  Image
1648  *shave_image;
1649 
1651  geometry;
1652 
1653  assert(image != (const Image *) NULL);
1654  assert(image->signature == MagickCoreSignature);
1655  if (image->debug != MagickFalse)
1656  (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
1657  if (((2*shave_info->width) >= image->columns) ||
1658  ((2*shave_info->height) >= image->rows))
1659  ThrowImageException(OptionWarning,"GeometryDoesNotContainImage");
1660  SetGeometry(image,&geometry);
1661  geometry.width-=2*shave_info->width;
1662  geometry.height-=2*shave_info->height;
1663  geometry.x=(ssize_t) shave_info->width+image->page.x;
1664  geometry.y=(ssize_t) shave_info->height+image->page.y;
1665  shave_image=CropImage(image,&geometry,exception);
1666  if (shave_image == (Image *) NULL)
1667  return((Image *) NULL);
1668  shave_image->page.width-=2*shave_info->width;
1669  shave_image->page.height-=2*shave_info->height;
1670  shave_image->page.x-=(ssize_t) shave_info->width;
1671  shave_image->page.y-=(ssize_t) shave_info->height;
1672  return(shave_image);
1673 }
1674 
1675 /*
1676 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1677 % %
1678 % %
1679 % %
1680 % S p l i c e I m a g e %
1681 % %
1682 % %
1683 % %
1684 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1685 %
1686 % SpliceImage() splices a solid color into the image as defined by the
1687 % geometry.
1688 %
1689 % The format of the SpliceImage method is:
1690 %
1691 % Image *SpliceImage(const Image *image,const RectangleInfo *geometry,
1692 % ExceptionInfo *exception)
1693 %
1694 % A description of each parameter follows:
1695 %
1696 % o image: the image.
1697 %
1698 % o geometry: Define the region of the image to splice with members
1699 % x, y, width, and height.
1700 %
1701 % o exception: return any errors or warnings in this structure.
1702 %
1703 */
1705  const RectangleInfo *geometry,ExceptionInfo *exception)
1706 {
1707 #define SpliceImageTag "Splice/Image"
1708 
1709  CacheView
1710  *image_view,
1711  *splice_view;
1712 
1713  Image
1714  *splice_image;
1715 
1717  status;
1718 
1720  progress;
1721 
1723  splice_geometry;
1724 
1725  ssize_t
1726  columns,
1727  y;
1728 
1729  /*
1730  Allocate splice image.
1731  */
1732  assert(image != (const Image *) NULL);
1733  assert(image->signature == MagickCoreSignature);
1734  if (image->debug != MagickFalse)
1735  (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
1736  assert(geometry != (const RectangleInfo *) NULL);
1737  assert(exception != (ExceptionInfo *) NULL);
1738  assert(exception->signature == MagickCoreSignature);
1739  splice_geometry=(*geometry);
1740  splice_image=CloneImage(image,image->columns+splice_geometry.width,
1741  image->rows+splice_geometry.height,MagickTrue,exception);
1742  if (splice_image == (Image *) NULL)
1743  return((Image *) NULL);
1744  if (SetImageStorageClass(splice_image,DirectClass,exception) == MagickFalse)
1745  {
1746  splice_image=DestroyImage(splice_image);
1747  return((Image *) NULL);
1748  }
1749  if ((IsPixelInfoGray(&splice_image->background_color) == MagickFalse) &&
1750  (IsGrayColorspace(splice_image->colorspace) != MagickFalse))
1751  (void) SetImageColorspace(splice_image,sRGBColorspace,exception);
1752  if ((splice_image->background_color.alpha_trait != UndefinedPixelTrait) &&
1753  (splice_image->alpha_trait == UndefinedPixelTrait))
1754  (void) SetImageAlpha(splice_image,OpaqueAlpha,exception);
1755  (void) SetImageBackgroundColor(splice_image,exception);
1756  /*
1757  Respect image geometry.
1758  */
1759  switch (image->gravity)
1760  {
1761  default:
1762  case UndefinedGravity:
1763  case NorthWestGravity:
1764  break;
1765  case NorthGravity:
1766  {
1767  splice_geometry.x+=(ssize_t) splice_geometry.width/2;
1768  break;
1769  }
1770  case NorthEastGravity:
1771  {
1772  splice_geometry.x+=(ssize_t) splice_geometry.width;
1773  break;
1774  }
1775  case WestGravity:
1776  {
1777  splice_geometry.y+=(ssize_t) splice_geometry.width/2;
1778  break;
1779  }
1780  case CenterGravity:
1781  {
1782  splice_geometry.x+=(ssize_t) splice_geometry.width/2;
1783  splice_geometry.y+=(ssize_t) splice_geometry.height/2;
1784  break;
1785  }
1786  case EastGravity:
1787  {
1788  splice_geometry.x+=(ssize_t) splice_geometry.width;
1789  splice_geometry.y+=(ssize_t) splice_geometry.height/2;
1790  break;
1791  }
1792  case SouthWestGravity:
1793  {
1794  splice_geometry.y+=(ssize_t) splice_geometry.height;
1795  break;
1796  }
1797  case SouthGravity:
1798  {
1799  splice_geometry.x+=(ssize_t) splice_geometry.width/2;
1800  splice_geometry.y+=(ssize_t) splice_geometry.height;
1801  break;
1802  }
1803  case SouthEastGravity:
1804  {
1805  splice_geometry.x+=(ssize_t) splice_geometry.width;
1806  splice_geometry.y+=(ssize_t) splice_geometry.height;
1807  break;
1808  }
1809  }
1810  /*
1811  Splice image.
1812  */
1813  status=MagickTrue;
1814  progress=0;
1815  columns=MagickMin(splice_geometry.x,(ssize_t) splice_image->columns);
1816  image_view=AcquireVirtualCacheView(image,exception);
1817  splice_view=AcquireAuthenticCacheView(splice_image,exception);
1818 #if defined(MAGICKCORE_OPENMP_SUPPORT)
1819  #pragma omp parallel for schedule(static,4) shared(progress,status) \
1820  magick_number_threads(image,splice_image,splice_geometry.y,1)
1821 #endif
1822  for (y=0; y < (ssize_t) splice_geometry.y; y++)
1823  {
1824  register const Quantum
1825  *magick_restrict p;
1826 
1827  register ssize_t
1828  x;
1829 
1830  register Quantum
1831  *magick_restrict q;
1832 
1833  if (status == MagickFalse)
1834  continue;
1835  p=GetCacheViewVirtualPixels(image_view,0,y,splice_image->columns,1,
1836  exception);
1837  q=QueueCacheViewAuthenticPixels(splice_view,0,y,splice_image->columns,1,
1838  exception);
1839  if ((p == (const Quantum *) NULL) || (q == (Quantum *) NULL))
1840  {
1841  status=MagickFalse;
1842  continue;
1843  }
1844  for (x=0; x < columns; x++)
1845  {
1846  register ssize_t
1847  i;
1848 
1849  if (GetPixelWriteMask(image,p) <= (QuantumRange/2))
1850  {
1851  SetPixelBackgoundColor(splice_image,q);
1852  p+=GetPixelChannels(image);
1853  q+=GetPixelChannels(splice_image);
1854  continue;
1855  }
1856  for (i=0; i < (ssize_t) GetPixelChannels(image); i++)
1857  {
1858  PixelChannel channel = GetPixelChannelChannel(image,i);
1859  PixelTrait traits = GetPixelChannelTraits(image,channel);
1860  PixelTrait splice_traits=GetPixelChannelTraits(splice_image,channel);
1861  if ((traits == UndefinedPixelTrait) ||
1862  (splice_traits == UndefinedPixelTrait))
1863  continue;
1864  SetPixelChannel(splice_image,channel,p[i],q);
1865  }
1866  SetPixelRed(splice_image,GetPixelRed(image,p),q);
1867  SetPixelGreen(splice_image,GetPixelGreen(image,p),q);
1868  SetPixelBlue(splice_image,GetPixelBlue(image,p),q);
1869  SetPixelAlpha(splice_image,GetPixelAlpha(image,p),q);
1870  p+=GetPixelChannels(image);
1871  q+=GetPixelChannels(splice_image);
1872  }
1873  for ( ; x < (ssize_t) (splice_geometry.x+splice_geometry.width); x++)
1874  q+=GetPixelChannels(splice_image);
1875  for ( ; x < (ssize_t) splice_image->columns; x++)
1876  {
1877  register ssize_t
1878  i;
1879 
1880  if (GetPixelWriteMask(image,p) <= (QuantumRange/2))
1881  {
1882  SetPixelBackgoundColor(splice_image,q);
1883  p+=GetPixelChannels(image);
1884  q+=GetPixelChannels(splice_image);
1885  continue;
1886  }
1887  for (i=0; i < (ssize_t) GetPixelChannels(image); i++)
1888  {
1889  PixelChannel channel = GetPixelChannelChannel(image,i);
1890  PixelTrait traits = GetPixelChannelTraits(image,channel);
1891  PixelTrait splice_traits=GetPixelChannelTraits(splice_image,channel);
1892  if ((traits == UndefinedPixelTrait) ||
1893  (splice_traits == UndefinedPixelTrait))
1894  continue;
1895  SetPixelChannel(splice_image,channel,p[i],q);
1896  }
1897  SetPixelRed(splice_image,GetPixelRed(image,p),q);
1898  SetPixelGreen(splice_image,GetPixelGreen(image,p),q);
1899  SetPixelBlue(splice_image,GetPixelBlue(image,p),q);
1900  SetPixelAlpha(splice_image,GetPixelAlpha(image,p),q);
1901  p+=GetPixelChannels(image);
1902  q+=GetPixelChannels(splice_image);
1903  }
1904  if (SyncCacheViewAuthenticPixels(splice_view,exception) == MagickFalse)
1905  status=MagickFalse;
1906  if (image->progress_monitor != (MagickProgressMonitor) NULL)
1907  {
1909  proceed;
1910 
1911 #if defined(MAGICKCORE_OPENMP_SUPPORT)
1912  #pragma omp critical (MagickCore_TransposeImage)
1913 #endif
1914  proceed=SetImageProgress(image,SpliceImageTag,progress++,
1915  splice_image->rows);
1916  if (proceed == MagickFalse)
1917  status=MagickFalse;
1918  }
1919  }
1920 #if defined(MAGICKCORE_OPENMP_SUPPORT)
1921  #pragma omp parallel for schedule(static,4) shared(progress,status) \
1922  magick_number_threads(image,splice_image,splice_image->rows,2)
1923 #endif
1924  for (y=(ssize_t) (splice_geometry.y+splice_geometry.height);
1925  y < (ssize_t) splice_image->rows; y++)
1926  {
1927  register const Quantum
1928  *magick_restrict p;
1929 
1930  register ssize_t
1931  x;
1932 
1933  register Quantum
1934  *magick_restrict q;
1935 
1936  if (status == MagickFalse)
1937  continue;
1938  if ((y < 0) || (y >= (ssize_t)splice_image->rows))
1939  continue;
1940  p=GetCacheViewVirtualPixels(image_view,0,y-(ssize_t) splice_geometry.height,
1941  splice_image->columns,1,exception);
1942  q=QueueCacheViewAuthenticPixels(splice_view,0,y,splice_image->columns,1,
1943  exception);
1944  if ((p == (const Quantum *) NULL) || (q == (Quantum *) NULL))
1945  {
1946  status=MagickFalse;
1947  continue;
1948  }
1949  for (x=0; x < columns; x++)
1950  {
1951  register ssize_t
1952  i;
1953 
1954  if (GetPixelWriteMask(image,q) <= (QuantumRange/2))
1955  {
1956  SetPixelBackgoundColor(splice_image,q);
1957  p+=GetPixelChannels(image);
1958  q+=GetPixelChannels(splice_image);
1959  continue;
1960  }
1961  for (i=0; i < (ssize_t) GetPixelChannels(image); i++)
1962  {
1963  PixelChannel channel = GetPixelChannelChannel(image,i);
1964  PixelTrait traits = GetPixelChannelTraits(image,channel);
1965  PixelTrait splice_traits=GetPixelChannelTraits(splice_image,channel);
1966  if ((traits == UndefinedPixelTrait) ||
1967  (splice_traits == UndefinedPixelTrait))
1968  continue;
1969  SetPixelChannel(splice_image,channel,p[i],q);
1970  }
1971  SetPixelRed(splice_image,GetPixelRed(image,p),q);
1972  SetPixelGreen(splice_image,GetPixelGreen(image,p),q);
1973  SetPixelBlue(splice_image,GetPixelBlue(image,p),q);
1974  SetPixelAlpha(splice_image,GetPixelAlpha(image,p),q);
1975  p+=GetPixelChannels(image);
1976  q+=GetPixelChannels(splice_image);
1977  }
1978  for ( ; x < (ssize_t) (splice_geometry.x+splice_geometry.width); x++)
1979  q+=GetPixelChannels(splice_image);
1980  for ( ; x < (ssize_t) splice_image->columns; x++)
1981  {
1982  register ssize_t
1983  i;
1984 
1985  if (GetPixelWriteMask(image,q) <= (QuantumRange/2))
1986  {
1987  SetPixelBackgoundColor(splice_image,q);
1988  p+=GetPixelChannels(image);
1989  q+=GetPixelChannels(splice_image);
1990  continue;
1991  }
1992  for (i=0; i < (ssize_t) GetPixelChannels(image); i++)
1993  {
1994  PixelChannel channel = GetPixelChannelChannel(image,i);
1995  PixelTrait traits = GetPixelChannelTraits(image,channel);
1996  PixelTrait splice_traits=GetPixelChannelTraits(splice_image,channel);
1997  if ((traits == UndefinedPixelTrait) ||
1998  (splice_traits == UndefinedPixelTrait))
1999  continue;
2000  SetPixelChannel(splice_image,channel,p[i],q);
2001  }
2002  SetPixelRed(splice_image,GetPixelRed(image,p),q);
2003  SetPixelGreen(splice_image,GetPixelGreen(image,p),q);
2004  SetPixelBlue(splice_image,GetPixelBlue(image,p),q);
2005  SetPixelAlpha(splice_image,GetPixelAlpha(image,p),q);
2006  p+=GetPixelChannels(image);
2007  q+=GetPixelChannels(splice_image);
2008  }
2009  if (SyncCacheViewAuthenticPixels(splice_view,exception) == MagickFalse)
2010  status=MagickFalse;
2011  if (image->progress_monitor != (MagickProgressMonitor) NULL)
2012  {
2014  proceed;
2015 
2016 #if defined(MAGICKCORE_OPENMP_SUPPORT)
2017  #pragma omp critical (MagickCore_TransposeImage)
2018 #endif
2019  proceed=SetImageProgress(image,SpliceImageTag,progress++,
2020  splice_image->rows);
2021  if (proceed == MagickFalse)
2022  status=MagickFalse;
2023  }
2024  }
2025  splice_view=DestroyCacheView(splice_view);
2026  image_view=DestroyCacheView(image_view);
2027  if (status == MagickFalse)
2028  splice_image=DestroyImage(splice_image);
2029  return(splice_image);
2030 }
2031 
2032 /*
2033 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2034 % %
2035 % %
2036 % %
2037 % T r a n s f o r m I m a g e %
2038 % %
2039 % %
2040 % %
2041 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2042 %
2043 % TransformImage() is a convenience method that behaves like ResizeImage() or
2044 % CropImage() but accepts scaling and/or cropping information as a region
2045 % geometry specification. If the operation fails, the original image handle
2046 % is left as is.
2047 %
2048 % This should only be used for single images.
2049 %
2050 % This function destroys what it assumes to be a single image list.
2051 % If the input image is part of a larger list, all other images in that list
2052 % will be simply 'lost', not destroyed.
2053 %
2054 % Also if the crop generates a list of images only the first image is resized.
2055 % And finally if the crop succeeds and the resize failed, you will get a
2056 % cropped image, as well as a 'false' or 'failed' report.
2057 %
2058 % This function and should probably be deprecated in favor of direct calls
2059 % to CropImageToTiles() or ResizeImage(), as appropriate.
2060 %
2061 % The format of the TransformImage method is:
2062 %
2063 % MagickBooleanType TransformImage(Image **image,const char *crop_geometry,
2064 % const char *image_geometry,ExceptionInfo *exception)
2065 %
2066 % A description of each parameter follows:
2067 %
2068 % o image: the image The transformed image is returned as this parameter.
2069 %
2070 % o crop_geometry: A crop geometry string. This geometry defines a
2071 % subregion of the image to crop.
2072 %
2073 % o image_geometry: An image geometry string. This geometry defines the
2074 % final size of the image.
2075 %
2076 % o exception: return any errors or warnings in this structure.
2077 %
2078 */
2080  const char *crop_geometry,const char *image_geometry,ExceptionInfo *exception)
2081 {
2082  Image
2083  *resize_image,
2084  *transform_image;
2085 
2087  geometry;
2088 
2089  assert(image != (Image **) NULL);
2090  assert((*image)->signature == MagickCoreSignature);
2091  if ((*image)->debug != MagickFalse)
2092  (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",(*image)->filename);
2093  transform_image=(*image);
2094  if (crop_geometry != (const char *) NULL)
2095  {
2096  Image
2097  *crop_image;
2098 
2099  /*
2100  Crop image to a user specified size.
2101  */
2102  crop_image=CropImageToTiles(*image,crop_geometry,exception);
2103  if (crop_image == (Image *) NULL)
2104  transform_image=CloneImage(*image,0,0,MagickTrue,exception);
2105  else
2106  {
2107  transform_image=DestroyImage(transform_image);
2108  transform_image=GetFirstImageInList(crop_image);
2109  }
2110  *image=transform_image;
2111  }
2112  if (image_geometry == (const char *) NULL)
2113  return(MagickTrue);
2114  /*
2115  Scale image to a user specified size.
2116  */
2117  (void) ParseRegionGeometry(transform_image,image_geometry,&geometry,
2118  exception);
2119  if ((transform_image->columns == geometry.width) &&
2120  (transform_image->rows == geometry.height))
2121  return(MagickTrue);
2122  resize_image=ResizeImage(transform_image,geometry.width,geometry.height,
2123  transform_image->filter,exception);
2124  if (resize_image == (Image *) NULL)
2125  return(MagickFalse);
2126  transform_image=DestroyImage(transform_image);
2127  transform_image=resize_image;
2128  *image=transform_image;
2129  return(MagickTrue);
2130 }
2131 
2132 /*
2133 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2134 % %
2135 % %
2136 % %
2137 % T r a n s p o s e I m a g e %
2138 % %
2139 % %
2140 % %
2141 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2142 %
2143 % TransposeImage() creates a horizontal mirror image by reflecting the pixels
2144 % around the central y-axis while rotating them by 90 degrees.
2145 %
2146 % The format of the TransposeImage method is:
2147 %
2148 % Image *TransposeImage(const Image *image,ExceptionInfo *exception)
2149 %
2150 % A description of each parameter follows:
2151 %
2152 % o image: the image.
2153 %
2154 % o exception: return any errors or warnings in this structure.
2155 %
2156 */
2158 {
2159 #define TransposeImageTag "Transpose/Image"
2160 
2161  CacheView
2162  *image_view,
2163  *transpose_view;
2164 
2165  Image
2166  *transpose_image;
2167 
2169  status;
2170 
2172  progress;
2173 
2175  page;
2176 
2177  ssize_t
2178  y;
2179 
2180  assert(image != (const Image *) NULL);
2181  assert(image->signature == MagickCoreSignature);
2182  if (image->debug != MagickFalse)
2183  (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
2184  assert(exception != (ExceptionInfo *) NULL);
2185  assert(exception->signature == MagickCoreSignature);
2186  transpose_image=CloneImage(image,image->rows,image->columns,MagickTrue,
2187  exception);
2188  if (transpose_image == (Image *) NULL)
2189  return((Image *) NULL);
2190  /*
2191  Transpose image.
2192  */
2193  status=MagickTrue;
2194  progress=0;
2195  image_view=AcquireVirtualCacheView(image,exception);
2196  transpose_view=AcquireAuthenticCacheView(transpose_image,exception);
2197 #if defined(MAGICKCORE_OPENMP_SUPPORT)
2198  #pragma omp parallel for schedule(static,4) shared(progress,status) \
2199  magick_number_threads(image,transpose_image,image->rows,1)
2200 #endif
2201  for (y=0; y < (ssize_t) image->rows; y++)
2202  {
2203  register const Quantum
2204  *magick_restrict p;
2205 
2206  register Quantum
2207  *magick_restrict q;
2208 
2209  register ssize_t
2210  x;
2211 
2212  if (status == MagickFalse)
2213  continue;
2214  p=GetCacheViewVirtualPixels(image_view,0,(ssize_t) image->rows-y-1,
2215  image->columns,1,exception);
2216  q=QueueCacheViewAuthenticPixels(transpose_view,(ssize_t) (image->rows-y-1),
2217  0,1,transpose_image->rows,exception);
2218  if ((p == (const Quantum *) NULL) || (q == (Quantum *) NULL))
2219  {
2220  status=MagickFalse;
2221  continue;
2222  }
2223  for (x=0; x < (ssize_t) image->columns; x++)
2224  {
2225  register ssize_t
2226  i;
2227 
2228  if (GetPixelWriteMask(image,q) <= (QuantumRange/2))
2229  {
2230  SetPixelBackgoundColor(transpose_image,q);
2231  p+=GetPixelChannels(image);
2232  q+=GetPixelChannels(transpose_image);
2233  continue;
2234  }
2235  for (i=0; i < (ssize_t) GetPixelChannels(image); i++)
2236  {
2237  PixelChannel channel = GetPixelChannelChannel(image,i);
2238  PixelTrait traits = GetPixelChannelTraits(image,channel);
2239  PixelTrait transpose_traits=GetPixelChannelTraits(transpose_image,
2240  channel);
2241  if ((traits == UndefinedPixelTrait) ||
2242  (transpose_traits == UndefinedPixelTrait))
2243  continue;
2244  SetPixelChannel(transpose_image,channel,p[i],q);
2245  }
2246  p+=GetPixelChannels(image);
2247  q+=GetPixelChannels(transpose_image);
2248  }
2249  if (SyncCacheViewAuthenticPixels(transpose_view,exception) == MagickFalse)
2250  status=MagickFalse;
2251  if (image->progress_monitor != (MagickProgressMonitor) NULL)
2252  {
2254  proceed;
2255 
2256 #if defined(MAGICKCORE_OPENMP_SUPPORT)
2257  #pragma omp critical (MagickCore_TransposeImage)
2258 #endif
2259  proceed=SetImageProgress(image,TransposeImageTag,progress++,
2260  image->rows);
2261  if (proceed == MagickFalse)
2262  status=MagickFalse;
2263  }
2264  }
2265  transpose_view=DestroyCacheView(transpose_view);
2266  image_view=DestroyCacheView(image_view);
2267  transpose_image->type=image->type;
2268  page=transpose_image->page;
2269  Swap(page.width,page.height);
2270  Swap(page.x,page.y);
2271  transpose_image->page=page;
2272  if (status == MagickFalse)
2273  transpose_image=DestroyImage(transpose_image);
2274  return(transpose_image);
2275 }
2276 
2277 /*
2278 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2279 % %
2280 % %
2281 % %
2282 % T r a n s v e r s e I m a g e %
2283 % %
2284 % %
2285 % %
2286 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2287 %
2288 % TransverseImage() creates a vertical mirror image by reflecting the pixels
2289 % around the central x-axis while rotating them by 270 degrees.
2290 %
2291 % The format of the TransverseImage method is:
2292 %
2293 % Image *TransverseImage(const Image *image,ExceptionInfo *exception)
2294 %
2295 % A description of each parameter follows:
2296 %
2297 % o image: the image.
2298 %
2299 % o exception: return any errors or warnings in this structure.
2300 %
2301 */
2303 {
2304 #define TransverseImageTag "Transverse/Image"
2305 
2306  CacheView
2307  *image_view,
2308  *transverse_view;
2309 
2310  Image
2311  *transverse_image;
2312 
2314  status;
2315 
2317  progress;
2318 
2320  page;
2321 
2322  ssize_t
2323  y;
2324 
2325  assert(image != (const Image *) NULL);
2326  assert(image->signature == MagickCoreSignature);
2327  if (image->debug != MagickFalse)
2328  (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
2329  assert(exception != (ExceptionInfo *) NULL);
2330  assert(exception->signature == MagickCoreSignature);
2331  transverse_image=CloneImage(image,image->rows,image->columns,MagickTrue,
2332  exception);
2333  if (transverse_image == (Image *) NULL)
2334  return((Image *) NULL);
2335  /*
2336  Transverse image.
2337  */
2338  status=MagickTrue;
2339  progress=0;
2340  image_view=AcquireVirtualCacheView(image,exception);
2341  transverse_view=AcquireAuthenticCacheView(transverse_image,exception);
2342 #if defined(MAGICKCORE_OPENMP_SUPPORT)
2343  #pragma omp parallel for schedule(static,4) shared(progress,status) \
2344  magick_number_threads(image,transverse_image,image->rows,1)
2345 #endif
2346  for (y=0; y < (ssize_t) image->rows; y++)
2347  {
2349  sync;
2350 
2351  register const Quantum
2352  *magick_restrict p;
2353 
2354  register Quantum
2355  *magick_restrict q;
2356 
2357  register ssize_t
2358  x;
2359 
2360  if (status == MagickFalse)
2361  continue;
2362  p=GetCacheViewVirtualPixels(image_view,0,y,image->columns,1,exception);
2363  q=QueueCacheViewAuthenticPixels(transverse_view,(ssize_t) (image->rows-y-1),
2364  0,1,transverse_image->rows,exception);
2365  if ((p == (const Quantum *) NULL) || (q == (Quantum *) NULL))
2366  {
2367  status=MagickFalse;
2368  continue;
2369  }
2370  q+=GetPixelChannels(transverse_image)*image->columns;
2371  for (x=0; x < (ssize_t) image->columns; x++)
2372  {
2373  register ssize_t
2374  i;
2375 
2376  q-=GetPixelChannels(transverse_image);
2377  if (GetPixelWriteMask(image,p) <= (QuantumRange/2))
2378  {
2379  p+=GetPixelChannels(image);
2380  continue;
2381  }
2382  for (i=0; i < (ssize_t) GetPixelChannels(image); i++)
2383  {
2384  PixelChannel channel = GetPixelChannelChannel(image,i);
2385  PixelTrait traits = GetPixelChannelTraits(image,channel);
2386  PixelTrait transverse_traits=GetPixelChannelTraits(transverse_image,
2387  channel);
2388  if ((traits == UndefinedPixelTrait) ||
2389  (transverse_traits == UndefinedPixelTrait))
2390  continue;
2391  SetPixelChannel(transverse_image,channel,p[i],q);
2392  }
2393  p+=GetPixelChannels(image);
2394  }
2395  sync=SyncCacheViewAuthenticPixels(transverse_view,exception);
2396  if (sync == MagickFalse)
2397  status=MagickFalse;
2398  if (image->progress_monitor != (MagickProgressMonitor) NULL)
2399  {
2401  proceed;
2402 
2403 #if defined(MAGICKCORE_OPENMP_SUPPORT)
2404  #pragma omp critical (MagickCore_TransverseImage)
2405 #endif
2406  proceed=SetImageProgress(image,TransverseImageTag,progress++,
2407  image->rows);
2408  if (proceed == MagickFalse)
2409  status=MagickFalse;
2410  }
2411  }
2412  transverse_view=DestroyCacheView(transverse_view);
2413  image_view=DestroyCacheView(image_view);
2414  transverse_image->type=image->type;
2415  page=transverse_image->page;
2416  Swap(page.width,page.height);
2417  Swap(page.x,page.y);
2418  if (page.width != 0)
2419  page.x=(ssize_t) (page.width-transverse_image->columns-page.x);
2420  if (page.height != 0)
2421  page.y=(ssize_t) (page.height-transverse_image->rows-page.y);
2422  transverse_image->page=page;
2423  if (status == MagickFalse)
2424  transverse_image=DestroyImage(transverse_image);
2425  return(transverse_image);
2426 }
2427 
2428 /*
2429 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2430 % %
2431 % %
2432 % %
2433 % T r i m I m a g e %
2434 % %
2435 % %
2436 % %
2437 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2438 %
2439 % TrimImage() trims pixels from the image edges. It allocates the memory
2440 % necessary for the new Image structure and returns a pointer to the new
2441 % image.
2442 %
2443 % The format of the TrimImage method is:
2444 %
2445 % Image *TrimImage(const Image *image,ExceptionInfo *exception)
2446 %
2447 % A description of each parameter follows:
2448 %
2449 % o image: the image.
2450 %
2451 % o exception: return any errors or warnings in this structure.
2452 %
2453 */
2455 {
2457  geometry;
2458 
2459  assert(image != (const Image *) NULL);
2460  assert(image->signature == MagickCoreSignature);
2461  if (image->debug != MagickFalse)
2462  (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
2463  geometry=GetImageBoundingBox(image,exception);
2464  if ((geometry.width == 0) || (geometry.height == 0))
2465  {
2466  Image
2467  *crop_image;
2468 
2469  crop_image=CloneImage(image,1,1,MagickTrue,exception);
2470  if (crop_image == (Image *) NULL)
2471  return((Image *) NULL);
2473  crop_image->alpha_trait=BlendPixelTrait;
2474  (void) SetImageBackgroundColor(crop_image,exception);
2475  crop_image->page=image->page;
2476  crop_image->page.x=(-1);
2477  crop_image->page.y=(-1);
2478  return(crop_image);
2479  }
2480  geometry.x+=image->page.x;
2481  geometry.y+=image->page.y;
2482  return(CropImage(image,&geometry,exception));
2483 }
size_t rows
Definition: image.h:172
#define magick_restrict
Definition: MagickCore.h:41
MagickExport Image * ResizeImage(const Image *image, const size_t columns, const size_t rows, const FilterType filter, ExceptionInfo *exception)
Definition: resize.c:2859
MagickExport CacheView * DestroyCacheView(CacheView *cache_view)
Definition: cache-view.c:252
MagickExport Image * FlipImage(const Image *image, ExceptionInfo *exception)
Definition: transform.c:1182
#define TransparentAlpha
Definition: image.h:26
static MagickBooleanType SetImageProgress(const Image *image, const char *tag, const MagickOffsetType offset, const MagickSizeType extent)
DisposeType dispose
Definition: image.h:237
#define RollImageTag
MagickProgressMonitor progress_monitor
Definition: image.h:303
ImageType type
Definition: image.h:264
static void SetPixelBackgoundColor(const Image *magick_restrict image, Quantum *magick_restrict pixel)
static Quantum GetPixelAlpha(const Image *magick_restrict image, const Quantum *magick_restrict pixel)
FilterType filter
Definition: image.h:219
PixelTrait alpha_trait
Definition: pixel.h:176
ssize_t y
Definition: geometry.h:115
static Quantum GetPixelRed(const Image *magick_restrict image, const Quantum *magick_restrict pixel)
MagickExport Image * ConsolidateCMYKImages(const Image *images, ExceptionInfo *exception)
Definition: transform.c:412
OrientationType
Definition: image.h:76
MagickExport Image * FlopImage(const Image *image, ExceptionInfo *exception)
Definition: transform.c:1323
MagickExport Image * TransposeImage(const Image *image, ExceptionInfo *exception)
Definition: transform.c:2157
size_t signature
Definition: exception.h:123
MagickPrivate MagickBooleanType TransformImage(Image **image, const char *crop_geometry, const char *image_geometry, ExceptionInfo *exception)
Definition: transform.c:2079
#define OpaqueAlpha
Definition: image.h:25
MagickExport MagickBooleanType SetImageAlpha(Image *image, const Quantum alpha, ExceptionInfo *exception)
Definition: image.c:2229
static PixelTrait GetPixelChannelTraits(const Image *magick_restrict image, const PixelChannel channel)
static MagickBooleanType IsGrayColorspace(const ColorspaceType colorspace)
MagickExport Image * TransverseImage(const Image *image, ExceptionInfo *exception)
Definition: transform.c:2302
MagickExport const Quantum * GetCacheViewVirtualPixels(const CacheView *cache_view, const ssize_t x, const ssize_t y, const size_t columns, const size_t rows, ExceptionInfo *exception)
Definition: cache-view.c:651
ssize_t offset
Definition: token.c:68
MagickRealType alpha
Definition: pixel.h:188
#define TransposeImageTag
MagickExport MagickBooleanType CompositeImage(Image *image, const Image *composite, const CompositeOperator compose, const MagickBooleanType clip_to_self, const ssize_t x_offset, const ssize_t y_offset, ExceptionInfo *exception)
Definition: composite.c:539
size_t width
Definition: geometry.h:129
#define ChopImageTag
MagickExport Image * CropImageToTiles(const Image *image, const char *crop_geometry, ExceptionInfo *exception)
Definition: transform.c:782
Definition: log.h:52
ssize_t MagickOffsetType
Definition: magick-type.h:127
Definition: image.h:151
MagickExport Image * CropImage(const Image *image, const RectangleInfo *geometry, ExceptionInfo *exception)
Definition: transform.c:533
double x
Definition: geometry.h:122
#define MagickCoreSignature
MagickExport Quantum * GetCacheViewAuthenticPixels(CacheView *cache_view, const ssize_t x, const ssize_t y, const size_t columns, const size_t rows, ExceptionInfo *exception)
Definition: cache-view.c:299
MagickExport Image * GetFirstImageInList(const Image *images)
Definition: list.c:541
MagickBooleanType
Definition: magick-type.h:156
MagickExport Image * NewImageList(void)
Definition: list.c:916
unsigned int MagickStatusType
Definition: magick-type.h:119
static Quantum GetPixelWriteMask(const Image *magick_restrict image, const Quantum *magick_restrict pixel)
double y
Definition: geometry.h:122
MagickExport Image * SpliceImage(const Image *image, const RectangleInfo *geometry, ExceptionInfo *exception)
Definition: transform.c:1704
GravityType gravity
Definition: image.h:231
RectangleInfo page
Definition: image.h:212
MagickExport Image * RollImage(const Image *image, const ssize_t x_offset, const ssize_t y_offset, ExceptionInfo *exception)
Definition: transform.c:1551
static Quantum GetPixelGreen(const Image *magick_restrict image, const Quantum *magick_restrict pixel)
PixelTrait alpha_trait
Definition: image.h:280
MagickExport Quantum * QueueCacheViewAuthenticPixels(CacheView *cache_view, const ssize_t x, const ssize_t y, const size_t columns, const size_t rows, ExceptionInfo *exception)
Definition: cache-view.c:977
MagickExport MagickBooleanType ThrowMagickException(ExceptionInfo *exception, const char *module, const char *function, const size_t line, const ExceptionType severity, const char *tag, const char *format,...)
Definition: exception.c:1058
MagickExport MagickBooleanType LogMagickEvent(const LogEventType type, const char *module, const char *function, const size_t line, const char *format,...)
Definition: log.c:1397
MagickExport Image * RotateImage(const Image *image, const double degrees, ExceptionInfo *exception)
Definition: distort.c:2796
MagickExport MagickBooleanType SetImageBackgroundColor(Image *image, ExceptionInfo *exception)
Definition: image.c:2308
size_t signature
Definition: image.h:354
size_t columns
Definition: image.h:172
MagickExport Image * ExcerptImage(const Image *image, const RectangleInfo *geometry, ExceptionInfo *exception)
Definition: transform.c:981
MagickBooleanType(* MagickProgressMonitor)(const char *, const MagickOffsetType, const MagickSizeType, void *)
Definition: monitor.h:26
ssize_t x
Definition: geometry.h:133
size_t height
Definition: geometry.h:129
static void SetPixelMagenta(const Image *magick_restrict image, const Quantum magenta, Quantum *magick_restrict pixel)
#define FlipImageTag
static void SetPixelBlue(const Image *magick_restrict image, const Quantum blue, Quantum *magick_restrict pixel)
MagickExport MagickBooleanType SetImageStorageClass(Image *image, const ClassType storage_class, ExceptionInfo *exception)
Definition: image.c:2508
PixelChannel
Definition: pixel.h:66
#define SpliceImageTag
static size_t GetPixelChannels(const Image *magick_restrict image)
MagickExport Image * ChopImage(const Image *image, const RectangleInfo *chop_info, ExceptionInfo *exception)
Definition: transform.c:188
char filename[MagickPathExtent]
Definition: image.h:319
#define GetMagickModule()
Definition: log.h:28
static void SetPixelCyan(const Image *magick_restrict image, const Quantum cyan, Quantum *magick_restrict pixel)
#define ThrowImageException(severity, tag)
static PixelChannel GetPixelChannelChannel(const Image *magick_restrict image, const ssize_t offset)
MagickExport CacheView * AcquireVirtualCacheView(const Image *image, ExceptionInfo *exception)
Definition: cache-view.c:149
MagickExport void ClearMagickException(ExceptionInfo *exception)
Definition: exception.c:157
#define TransverseImageTag
unsigned short Quantum
Definition: magick-type.h:82
static MagickBooleanType IsPixelInfoGray(const PixelInfo *magick_restrict pixel)
#define FlopImageTag
MagickExport RectangleInfo GetImageBoundingBox(const Image *image, ExceptionInfo *exception)
Definition: attribute.c:125
MagickExport MagickBooleanType SetImageColorspace(Image *image, const ColorspaceType colorspace, ExceptionInfo *exception)
Definition: colorspace.c:1081
MagickExport Image * ExtentImage(const Image *image, const RectangleInfo *geometry, ExceptionInfo *exception)
Definition: transform.c:1127
MagickExport MagickStatusType ParseGravityGeometry(const Image *image, const char *geometry, RectangleInfo *region_info, ExceptionInfo *exception)
Definition: geometry.c:1180
MagickExport Image * GetNextImageInList(const Image *images)
Definition: list.c:752
MagickExport Image * ShaveImage(const Image *image, const RectangleInfo *shave_info, ExceptionInfo *exception)
Definition: transform.c:1644
#define CropImageTag
static void SetPixelChannel(const Image *magick_restrict image, const PixelChannel channel, const Quantum quantum, Quantum *magick_restrict pixel)
MagickExport void AppendImageToList(Image **images, const Image *append)
Definition: list.c:77
static void SetPixelYellow(const Image *magick_restrict image, const Quantum yellow, Quantum *magick_restrict pixel)
#define MagickMin(x, y)
Definition: image-private.h:27
static void SetPixelAlpha(const Image *magick_restrict image, const Quantum alpha, Quantum *magick_restrict pixel)
MagickExport void SetGeometry(const Image *image, RectangleInfo *geometry)
Definition: geometry.c:1571
ssize_t x
Definition: geometry.h:115
static double MagickRound(double x)
Definition: transform.c:772
#define Swap(x, y)
Definition: studio.h:339
CompositeOperator compose
Definition: image.h:234
MagickExport Image * AutoOrientImage(const Image *image, const OrientationType orientation, ExceptionInfo *exception)
Definition: transform.c:99
static void SetPixelRed(const Image *magick_restrict image, const Quantum red, Quantum *magick_restrict pixel)
#define MagickPrivate
MagickExport Image * TrimImage(const Image *image, ExceptionInfo *exception)
Definition: transform.c:2454
static MagickBooleanType CopyImageRegion(Image *destination, const Image *source, const size_t columns, const size_t rows, const ssize_t sx, const ssize_t sy, const ssize_t dx, const ssize_t dy, ExceptionInfo *exception)
Definition: transform.c:1468
#define MagickExport
MagickExport MagickBooleanType SyncCacheViewAuthenticPixels(CacheView *magick_restrict cache_view, ExceptionInfo *exception)
Definition: cache-view.c:1100
OrientationType orientation
Definition: image.h:166
ssize_t y
Definition: geometry.h:133
MagickExport CacheView * AcquireAuthenticCacheView(const Image *image, ExceptionInfo *exception)
Definition: cache-view.c:112
static void SetPixelBlack(const Image *magick_restrict image, const Quantum black, Quantum *magick_restrict pixel)
static Quantum GetPixelBlue(const Image *magick_restrict image, const Quantum *magick_restrict pixel)
PixelTrait
Definition: pixel.h:132
MagickExport MagickRealType GetPixelIntensity(const Image *magick_restrict image, const Quantum *magick_restrict pixel)
Definition: pixel.c:2355
PixelInfo background_color
Definition: image.h:179
MagickExport size_t GetImageListLength(const Image *images)
Definition: list.c:680
#define ExcerptImageTag
MagickExport Image * DestroyImage(Image *image)
Definition: image.c:1182
MagickExport Image * CloneImage(const Image *image, const size_t columns, const size_t rows, const MagickBooleanType detach, ExceptionInfo *exception)
Definition: image.c:799
ColorspaceType colorspace
Definition: image.h:157
MagickExport MagickStatusType ParseRegionGeometry(const Image *image, const char *geometry, RectangleInfo *region_info, ExceptionInfo *exception)
Definition: geometry.c:1532
#define QuantumRange
Definition: magick-type.h:83
MagickBooleanType debug
Definition: image.h:334
static void SetPixelGreen(const Image *magick_restrict image, const Quantum green, Quantum *magick_restrict pixel)