MagickCore  7.1.1-43
Convert, Edit, Or Compose Bitmap Images
list.c
1 /*
2 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3 % %
4 % %
5 % %
6 % L IIIII SSSSS TTTTT %
7 % L I SS T %
8 % L I SSS T %
9 % L I SS T %
10 % LLLLL IIIII SSSSS T %
11 % %
12 % %
13 % MagickCore Image List Methods %
14 % %
15 % Software Design %
16 % Cristy %
17 % December 2002 %
18 % %
19 % %
20 % Copyright @ 1999 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://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 /*
41  Include declarations.
42 */
43 #include "MagickCore/studio.h"
44 #include "MagickCore/artifact.h"
45 #include "MagickCore/blob.h"
46 #include "MagickCore/blob-private.h"
47 #include "MagickCore/exception.h"
48 #include "MagickCore/exception-private.h"
49 #include "MagickCore/image-private.h"
50 #include "MagickCore/list.h"
51 #include "MagickCore/memory_.h"
52 #include "MagickCore/string_.h"
53 #include "MagickCore/string-private.h"
54 
55 /*
56 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
57 % %
58 % %
59 % %
60 % A p p e n d I m a g e T o L i s t %
61 % %
62 % %
63 % %
64 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
65 %
66 % AppendImageToList() appends the second image list to the end of the first
67 % list. The given image list pointer is left unchanged, unless it was empty.
68 %
69 % The format of the AppendImageToList method is:
70 %
71 % AppendImageToList(Image *images,const Image *image)
72 %
73 % A description of each parameter follows:
74 %
75 % o images: the image list to be appended to.
76 %
77 % o image: the appended image or image list.
78 %
79 */
80 MagickExport void AppendImageToList(Image **images,const Image *append)
81 {
82  Image
83  *p,
84  *q;
85 
86  assert(images != (Image **) NULL);
87  if (append == (Image *) NULL)
88  return;
89  assert(append->signature == MagickCoreSignature);
90  if (IsEventLogging() != MagickFalse)
91  (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",append->filename);
92  if ((*images) == (Image *) NULL)
93  {
94  *images=(Image *) append;
95  return;
96  }
97  assert((*images)->signature == MagickCoreSignature);
98  p=GetLastImageInList(*images);
99  q=GetFirstImageInList(append);
100  p->next=q;
101  q->previous=p;
102 }
103 
104 /*
105 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
106 % %
107 % %
108 % %
109 % C l o n e I m a g e L i s t %
110 % %
111 % %
112 % %
113 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
114 %
115 % CloneImageList() returns a duplicate of the image list.
116 %
117 % The format of the CloneImageList method is:
118 %
119 % Image *CloneImageList(const Image *images,ExceptionInfo *exception)
120 %
121 % A description of each parameter follows:
122 %
123 % o images: the image list.
124 %
125 % o exception: return any errors or warnings in this structure.
126 %
127 */
128 MagickExport Image *CloneImageList(const Image *images,ExceptionInfo *exception)
129 {
130  Image
131  *clone,
132  *image;
133 
134  Image
135  *p;
136 
137  if (images == (Image *) NULL)
138  return((Image *) NULL);
139  assert(images->signature == MagickCoreSignature);
140  while (images->previous != (Image *) NULL)
141  {
142  assert(images != images->previous);
143  images=images->previous;
144  }
145  image=(Image *) NULL;
146  for (p=(Image *) NULL; images != (Image *) NULL; images=images->next)
147  {
148  assert(images != images->next);
149  clone=CloneImage(images,0,0,MagickTrue,exception);
150  if (clone == (Image *) NULL)
151  {
152  if (image != (Image *) NULL)
153  image=DestroyImageList(image);
154  return((Image *) NULL);
155  }
156  if (image == (Image *) NULL)
157  {
158  image=clone;
159  p=image;
160  continue;
161  }
162  p->next=clone;
163  clone->previous=p;
164  p=p->next;
165  }
166  return(image);
167 }
168 
169 /*
170 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
171 % %
172 % %
173 % %
174 % C l o n e I m a g e s %
175 % %
176 % %
177 % %
178 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
179 %
180 % CloneImages() clones one or more images from an image sequence, using a
181 % comma separated list of image numbers or ranges.
182 %
183 % The numbers start at 0 for the first image in the list, while negative
184 % numbers refer to images starting counting from the end of the range. Images
185 % may be referred to multiple times to clone them multiple times. Images
186 % referred beyond the available number of images in list are ignored.
187 %
188 % Images referenced may be reversed, and results in a clone of those images
189 % also being made with a reversed order.
190 %
191 % The format of the CloneImages method is:
192 %
193 % Image *CloneImages(const Image *images,const char *scenes,
194 % ExceptionInfo *exception)
195 %
196 % A description of each parameter follows:
197 %
198 % o images: the image sequence.
199 %
200 % o scenes: This character string specifies which scenes to clone
201 % (e.g. 1,3-5,7-3,2).
202 %
203 % o exception: return any errors or warnings in this structure.
204 %
205 */
206 MagickExport Image *CloneImages(const Image *images,const char *scenes,
207  ExceptionInfo *exception)
208 {
209  char
210  *p;
211 
212  const char
213  *artifact;
214 
215  const Image
216  *next;
217 
218  Image
219  *clone_images,
220  *image;
221 
222  size_t
223  length;
224 
225  ssize_t
226  first,
227  i,
228  last,
229  offset,
230  step;
231 
232  assert(images != (const Image *) NULL);
233  assert(images->signature == MagickCoreSignature);
234  assert(scenes != (char *) NULL);
235  assert(exception != (ExceptionInfo *) NULL);
236  assert(exception->signature == MagickCoreSignature);
237  if (IsEventLogging() != MagickFalse)
238  (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",images->filename);
239  clone_images=NewImageList();
240  images=GetFirstImageInList(images);
241  artifact=GetImageArtifact(images,"frames:step");
242  length=GetImageListLength(images);
243  for (p=(char *) scenes; *p != '\0';)
244  {
245  MagickBooleanType
246  match;
247 
248  while ((isspace((int) ((unsigned char) *p)) != 0) || (*p == ','))
249  p++;
250  first=(ssize_t) strtol(p,&p,10);
251  offset=first;
252  if (first < 0)
253  first+=(ssize_t) length;
254  else
255  if (first > (ssize_t) length)
256  first=(ssize_t) length;
257  first%=(ssize_t) (length << 1);
258  last=first;
259  while (isspace((int) ((unsigned char) *p)) != 0)
260  p++;
261  if (*p == '-')
262  {
263  last=(ssize_t) strtol(p+1,&p,10);
264  if (last < 0)
265  last+=(ssize_t) length;
266  else
267  if (last > (ssize_t) length)
268  last=(ssize_t) length;
269  }
270  last%=(ssize_t) (length << 1);
271  match=MagickFalse;
272  step=1;
273  if (artifact != (const char *) NULL)
274  {
275  step=(ssize_t) StringToLong(artifact);
276  if (step == 0)
277  step=1;
278  }
279  step=(ssize_t) (first > last ? -step : step);
280  for ( ; step > 0 ? (last-first) >= 0 : (last-first) <= 0; first+=step)
281  {
282  i=0;
283  for (next=images; next != (Image *) NULL; next=GetNextImageInList(next))
284  {
285  if (i == (ssize_t) first)
286  {
287  image=CloneImage(next,0,0,MagickTrue,exception);
288  if (image == (Image *) NULL)
289  break;
290  AppendImageToList(&clone_images,image);
291  match=MagickTrue;
292  }
293  i++;
294  }
295  if (match == MagickFalse)
296  (void) ThrowMagickException(exception,GetMagickModule(),OptionError,
297  "InvalidImageIndex","%g `%s'",(double) offset,images->filename);
298  }
299  }
300  return(GetFirstImageInList(clone_images));
301 }
302 
303 /*
304 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
305 % %
306 % %
307 % %
308 % D e l e t e I m a g e F r o m L i s t %
309 % %
310 % %
311 % %
312 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
313 %
314 % DeleteImageFromList() deletes an image from the list. List pointer
315 % is moved to the next image, if one is present. See RemoveImageFromList().
316 %
317 % The format of the DeleteImageFromList method is:
318 %
319 % DeleteImageFromList(Image **images)
320 %
321 % A description of each parameter follows:
322 %
323 % o images: the image list.
324 %
325 */
326 MagickExport void DeleteImageFromList(Image **images)
327 {
328  Image
329  *image;
330 
331  image=RemoveImageFromList(images);
332  if (image != (Image *) NULL)
333  (void) DestroyImage(image);
334 }
335 
336 /*
337 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
338 % %
339 % %
340 % %
341 % D e l e t e I m a g e s %
342 % %
343 % %
344 % %
345 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
346 %
347 % DeleteImages() deletes one or more images from an image sequence, using a
348 % comma separated list of image numbers or ranges.
349 %
350 % The numbers start at 0 for the first image, while negative numbers refer to
351 % images starting counting from the end of the range. Images may be referred to
352 % multiple times without problems. Image referred beyond the available number
353 % of images in list are ignored.
354 %
355 % If the referenced images are in the reverse order, that range will be
356 % completely ignored, unlike CloneImages().
357 %
358 % The format of the DeleteImages method is:
359 %
360 % DeleteImages(Image **images,const char *scenes,ExceptionInfo *exception)
361 %
362 % A description of each parameter follows:
363 %
364 % o images: the image sequence.
365 %
366 % o scenes: This character string specifies which scenes to delete
367 % (e.g. 1,3-5,-2-6,2).
368 %
369 % o exception: return any errors or warnings in this structure.
370 %
371 */
372 MagickExport void DeleteImages(Image **images,const char *scenes,
373  ExceptionInfo *exception)
374 {
375  char
376  *p;
377 
378  Image
379  *image;
380 
381  long
382  first,
383  last;
384 
385  MagickBooleanType
386  *delete_list;
387 
388  ssize_t
389  i;
390 
391  size_t
392  length;
393 
394  assert(images != (Image **) NULL);
395  assert((*images)->signature == MagickCoreSignature);
396  assert(scenes != (char *) NULL);
397  assert(exception != (ExceptionInfo *) NULL);
398  assert(exception->signature == MagickCoreSignature);
399  if (IsEventLogging() != MagickFalse)
400  (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",
401  (*images)->filename);
402  *images=GetFirstImageInList(*images);
403  length=GetImageListLength(*images);
404  delete_list=(MagickBooleanType *) AcquireQuantumMemory(length,
405  sizeof(*delete_list));
406  if (delete_list == (MagickBooleanType *) NULL)
407  {
408  (void) ThrowMagickException(exception,GetMagickModule(),
409  ResourceLimitError,"MemoryAllocationFailed","`%s'",(*images)->filename);
410  return;
411  }
412  image=(*images);
413  for (i=0; i < (ssize_t) length; i++)
414  delete_list[i]=MagickFalse;
415  /*
416  Note which images will be deleted, avoid duplicates.
417  */
418  for (p=(char *) scenes; *p != '\0'; )
419  {
420  char
421  *q;
422 
423  while ((isspace((int) ((unsigned char) *p)) != 0) || (*p == ','))
424  p++;
425  first=strtol(p,&q,10);
426  if (p == q)
427  break;
428  p=q;
429  if (first < 0)
430  first+=(long) length;
431  last=first;
432  while (isspace((int) ((unsigned char) *p)) != 0)
433  p++;
434  if (*p == '-')
435  {
436  last=strtol(p+1,&q,10);
437  if ((p+1) == q)
438  break;
439  p=q;
440  if (last < 0)
441  last+=(long) length;
442  }
443  if (first > last)
444  continue;
445  for (i=(ssize_t) first; i <= (ssize_t) last; i++)
446  if ((i >= 0) && (i < (ssize_t) length))
447  delete_list[i]=MagickTrue;
448  }
449  /*
450  Delete images marked for deletion, once only.
451  */
452  image=(*images);
453  for (i=0; i < (ssize_t) length; i++)
454  {
455  *images=image;
456  image=GetNextImageInList(image);
457  if (delete_list[i] != MagickFalse)
458  DeleteImageFromList(images);
459  }
460  (void) RelinquishMagickMemory(delete_list);
461  *images=GetFirstImageInList(*images);
462 }
463 
464 /*
465 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
466 % %
467 % %
468 % %
469 % D e s t r o y I m a g e L i s t %
470 % %
471 % %
472 % %
473 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
474 %
475 % DestroyImageList() destroys an image list.
476 %
477 % The format of the DestroyImageList method is:
478 %
479 % Image *DestroyImageList(Image *image)
480 %
481 % A description of each parameter follows:
482 %
483 % o image: the image sequence.
484 %
485 */
486 MagickExport Image *DestroyImageList(Image *images)
487 {
488  if (images == (Image *) NULL)
489  return((Image *) NULL);
490  assert(images->signature == MagickCoreSignature);
491  if (IsEventLogging() != MagickFalse)
492  (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",images->filename);
493  while (images != (Image *) NULL)
494  DeleteImageFromList(&images);
495  return((Image *) NULL);
496 }
497 
498 /*
499 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
500 % %
501 % %
502 % %
503 % D u p l i c a t e I m a g e s %
504 % %
505 % %
506 % %
507 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
508 %
509 % DuplicateImages() duplicates one or more images from an image sequence,
510 % using a count and a comma separated list of image numbers or ranges.
511 %
512 % The numbers start at 0 for the first image, while negative numbers refer to
513 % images starting counting from the end of the range. Images may be referred to
514 % multiple times without problems. Image referred beyond the available number
515 % of images in list are ignored.
516 %
517 % The format of the DuplicateImages method is:
518 %
519 % Image *DuplicateImages(Image *images,const size_t number_duplicates,
520 % const char *scenes,ExceptionInfo *exception)
521 %
522 % A description of each parameter follows:
523 %
524 % o images: the image sequence.
525 %
526 % o number_duplicates: duplicate the image sequence this number of times.
527 %
528 % o scenes: This character string specifies which scenes to duplicate (e.g.
529 % 1,3-5,-2-6,2).
530 %
531 % o exception: return any errors or warnings in this structure.
532 %
533 */
534 MagickExport Image *DuplicateImages(Image *images,
535  const size_t number_duplicates,const char *scenes,ExceptionInfo *exception)
536 {
537  Image
538  *clone_images,
539  *duplicate_images;
540 
541  ssize_t
542  i;
543 
544  /*
545  Duplicate images.
546  */
547  assert(images != (Image *) NULL);
548  assert(images->signature == MagickCoreSignature);
549  assert(scenes != (char *) NULL);
550  assert(exception != (ExceptionInfo *) NULL);
551  assert(exception->signature == MagickCoreSignature);
552  if (IsEventLogging() != MagickFalse)
553  (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",images->filename);
554  duplicate_images=NewImageList();
555  for (i=0; i < (ssize_t) number_duplicates; i++)
556  {
557  clone_images=CloneImages(images,scenes,exception);
558  AppendImageToList(&duplicate_images,clone_images);
559  }
560  return(duplicate_images);
561 }
562 
563 /*
564 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
565 % %
566 % %
567 % %
568 % G e t F i r s t I m a g e I n L i s t %
569 % %
570 % %
571 % %
572 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
573 %
574 % GetFirstImageInList() returns a pointer to the first image in the list.
575 %
576 % The format of the GetFirstImageInList method is:
577 %
578 % Image *GetFirstImageInList(const Image *images)
579 %
580 % A description of each parameter follows:
581 %
582 % o images: the image list.
583 %
584 */
585 MagickExport Image *GetFirstImageInList(const Image *images)
586 {
587  const Image
588  *p;
589 
590  if (images == (Image *) NULL)
591  return((Image *) NULL);
592  assert(images->signature == MagickCoreSignature);
593  for (p=images; p->previous != (Image *) NULL; p=p->previous) ;
594  return((Image *) p);
595 }
596 
597 /*
598 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
599 % %
600 % %
601 % %
602 % G e t I m a g e F r o m L i s t %
603 % %
604 % %
605 % %
606 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
607 %
608 % GetImageFromList() returns an image at the specified index from the image
609 % list. Starting with 0 as the first image in the list.
610 %
611 % A negative offset will return the image from the end of the list, such that
612 % an index of -1 is the last image.
613 %
614 % If no such image exists at the specified offset a NULL image pointer is
615 % returned. This will only happen if index is less that the negative of
616 % the list length, or larger than list length -1. EG: ( -N to N-1 )
617 %
618 % The format of the GetImageFromList method is:
619 %
620 % Image *GetImageFromList(const Image *images,const ssize_t index)
621 %
622 % A description of each parameter follows:
623 %
624 % o images: the image list.
625 %
626 % o index: the position within the list.
627 %
628 */
629 MagickExport Image *GetImageFromList(const Image *images,const ssize_t index)
630 {
631  const Image
632  *p;
633 
634  ssize_t
635  i;
636 
637  if (images == (Image *) NULL)
638  return((Image *) NULL);
639  assert(images->signature == MagickCoreSignature);
640  if (IsEventLogging() != MagickFalse)
641  (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",images->filename);
642  if (index < 0)
643  {
644  p=GetLastImageInList(images);
645  for (i=(-1); p != (Image *) NULL; p=p->previous)
646  if (i-- == index)
647  break;
648  }
649  else
650  {
651  p=GetFirstImageInList(images);
652  for (i=0; p != (Image *) NULL; p=p->next)
653  if (i++ == index)
654  break;
655  }
656  return((Image *) p);
657 }
658 
659 /*
660 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
661 % %
662 % %
663 % %
664 % G e t I m a g e I n d e x I n L i s t %
665 % %
666 % %
667 % %
668 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
669 %
670 % GetImageIndexInList() returns the offset in the list of the specified image.
671 %
672 % The format of the GetImageIndexInList method is:
673 %
674 % ssize_t GetImageIndexInList(const Image *images)
675 %
676 % A description of each parameter follows:
677 %
678 % o images: the image list.
679 %
680 */
681 MagickExport ssize_t GetImageIndexInList(const Image *images)
682 {
683  ssize_t
684  i;
685 
686  if (images == (const Image *) NULL)
687  return(-1);
688  assert(images->signature == MagickCoreSignature);
689  for (i=0; images->previous != (Image *) NULL; i++)
690  {
691  assert(images != images->previous);
692  images=images->previous;
693  }
694  return(i);
695 }
696 
697 /*
698 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
699 % %
700 % %
701 % %
702 % G e t I m a g e L i s t L e n g t h %
703 % %
704 % %
705 % %
706 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
707 %
708 % GetImageListLength() returns the length of the list (the number of images in
709 % the list).
710 %
711 % The format of the GetImageListLength method is:
712 %
713 % size_t GetImageListLength(const Image *images)
714 %
715 % A description of each parameter follows:
716 %
717 % o images: the image list.
718 %
719 */
720 MagickExport size_t GetImageListLength(const Image *images)
721 {
722  size_t
723  i;
724 
725  if (images == (Image *) NULL)
726  return(0);
727  assert(images->signature == MagickCoreSignature);
728  if (IsEventLogging() != MagickFalse)
729  (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",images->filename);
730  images=GetLastImageInList(images);
731  for (i=0; images != (Image *) NULL; images=images->previous)
732  {
733  assert(images != images->previous);
734  i++;
735  }
736  return(i);
737 }
738 
739 /*
740 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
741 % %
742 % %
743 % %
744 % G e t L a s t I m a g e I n L i s t %
745 % %
746 % %
747 % %
748 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
749 %
750 % GetLastImageInList() returns a pointer to the last image in the list.
751 %
752 % The format of the GetLastImageInList method is:
753 %
754 % Image *GetLastImageInList(const Image *images)
755 %
756 % A description of each parameter follows:
757 %
758 % o images: the image list.
759 %
760 */
761 MagickExport Image *GetLastImageInList(const Image *images)
762 {
763  const Image
764  *p;
765 
766  if (images == (Image *) NULL)
767  return((Image *) NULL);
768  assert(images->signature == MagickCoreSignature);
769  for (p=images; p->next != (Image *) NULL; p=p->next) ;
770  return((Image *) p);
771 }
772 
773 /*
774 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
775 % %
776 % %
777 % %
778 % G e t N e x t I m a g e I n L i s t %
779 % %
780 % %
781 % %
782 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
783 %
784 % GetNextImageInList() returns the next image in the list.
785 %
786 % The format of the GetNextImageInList method is:
787 %
788 % Image *GetNextImageInList(const Image *images)
789 %
790 % A description of each parameter follows:
791 %
792 % o images: the image list.
793 %
794 */
795 MagickExport Image *GetNextImageInList(const Image *images)
796 {
797  if (images == (Image *) NULL)
798  return((Image *) NULL);
799  assert(images->signature == MagickCoreSignature);
800  if (IsEventLogging() != MagickFalse)
801  (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",images->filename);
802  return(images->next);
803 }
804 
805 /*
806 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
807 % %
808 % %
809 % %
810 % G e t P r e v i o u s I m a g e I n L i s t %
811 % %
812 % %
813 % %
814 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
815 %
816 % GetPreviousImageInList() returns the previous image in the list.
817 %
818 % The format of the GetPreviousImageInList method is:
819 %
820 % Image *GetPreviousImageInList(const Image *images)
821 %
822 % A description of each parameter follows:
823 %
824 % o images: the image list.
825 %
826 */
827 MagickExport Image *GetPreviousImageInList(const Image *images)
828 {
829  if (images == (Image *) NULL)
830  return((Image *) NULL);
831  assert(images->signature == MagickCoreSignature);
832  return(images->previous);
833 }
834 
835 /*
836 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
837 % %
838 % %
839 % I m a g e L i s t T o A r r a y %
840 % %
841 % %
842 % %
843 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
844 %
845 % ImageListToArray() is a convenience method that converts an image list to
846 % a sequential array, with a NULL image pointer at the end of the array.
847 %
848 % The images remain part of the original image list, with the array providing
849 % an alternative means of indexing the image array.
850 %
851 % group = ImageListToArray(images, exception);
852 % while (i = 0; group[i] != (Image *) NULL; i++)
853 % printf("%s\n", group[i]->filename);
854 % printf("%d images\n", i);
855 % group = RelinquishMagickMemory(group);
856 %
857 % The format of the ImageListToArray method is:
858 %
859 % Image **ImageListToArray(const Image *images,ExceptionInfo *exception)
860 %
861 % A description of each parameter follows:
862 %
863 % o image: the image list.
864 %
865 % o exception: return any errors or warnings in this structure.
866 %
867 */
868 MagickExport Image **ImageListToArray(const Image *images,
869  ExceptionInfo *exception)
870 {
871  Image
872  **group;
873 
874  ssize_t
875  i;
876 
877  if (images == (Image *) NULL)
878  return((Image **) NULL);
879  assert(images->signature == MagickCoreSignature);
880  if (IsEventLogging() != MagickFalse)
881  (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",images->filename);
882  group=(Image **) AcquireQuantumMemory((size_t) GetImageListLength(images)+1UL,
883  sizeof(*group));
884  if (group == (Image **) NULL)
885  {
886  (void) ThrowMagickException(exception,GetMagickModule(),
887  ResourceLimitError,"MemoryAllocationFailed","`%s'",images->filename);
888  return((Image **) NULL);
889  }
890  images=GetFirstImageInList(images);
891  for (i=0; images != (Image *) NULL; images=images->next)
892  {
893  assert(images != images->next);
894  group[i++]=(Image *) images;
895  }
896  group[i]=(Image *) NULL;
897  return(group);
898 }
899 
900 /*
901 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
902 % %
903 % %
904 % %
905 % I n s e r t I m a g e I n L i s t %
906 % %
907 % %
908 % %
909 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
910 %
911 % InsertImageInList() insert the given image or image list, into the first
912 % image list, immediately AFTER the image pointed to. The given image list
913 % pointer is left unchanged unless previously empty.
914 %
915 % The format of the InsertImageInList method is:
916 %
917 % InsertImageInList(Image **images,Image *insert)
918 %
919 % A description of each parameter follows:
920 %
921 % o images: the image list to insert into.
922 %
923 % o insert: the image list to insert.
924 %
925 */
926 MagickExport void InsertImageInList(Image **images,Image *insert)
927 {
928  Image
929  *split;
930 
931  assert(images != (Image **) NULL);
932  assert(insert != (Image *) NULL);
933  assert(insert->signature == MagickCoreSignature);
934  if (IsEventLogging() != MagickFalse)
935  (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",insert->filename);
936  if ((*images) == (Image *) NULL)
937  return;
938  assert((*images)->signature == MagickCoreSignature);
939  split=SplitImageList(*images);
940  AppendImageToList(images,insert);
941  AppendImageToList(images,split);
942 }
943 
944 /*
945 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
946 % %
947 % %
948 % %
949 % N e w I m a g e L i s t %
950 % %
951 % %
952 % %
953 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
954 %
955 % NewImageList() creates an empty image list.
956 %
957 % The format of the NewImageList method is:
958 %
959 % Image *NewImageList(void)
960 %
961 */
962 MagickExport Image *NewImageList(void)
963 {
964  return((Image *) NULL);
965 }
966 
967 /*
968 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
969 % %
970 % %
971 % %
972 % P r e p e n d I m a g e T o L i s t %
973 % %
974 % %
975 % %
976 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
977 %
978 % PrependImageToList() prepends the image to the beginning of the list.
979 %
980 % The format of the PrependImageToList method is:
981 %
982 % PrependImageToList(Image *images,Image *image)
983 %
984 % A description of each parameter follows:
985 %
986 % o images: the image list.
987 %
988 % o image: the image.
989 %
990 */
991 MagickExport void PrependImageToList(Image **images,Image *prepend)
992 {
993  if (*images == (Image *) NULL)
994  {
995  *images=prepend;
996  return;
997  }
998  AppendImageToList(&prepend,*images);
999 }
1000 
1001 /*
1002 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1003 % %
1004 % %
1005 % %
1006 % R e m o v e I m a g e F r o m L i s t %
1007 % %
1008 % %
1009 % %
1010 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1011 %
1012 % RemoveImageFromList() removes and returns the image pointed to.
1013 %
1014 % The given image list pointer is set to point to the next image in list
1015 % if it exists, otherwise it is set to the previous image, or NULL if list
1016 % was emptied.
1017 %
1018 % The format of the RemoveImageFromList method is:
1019 %
1020 % Image *RemoveImageFromList(Image **images)
1021 %
1022 % A description of each parameter follows:
1023 %
1024 % o images: the image list.
1025 %
1026 */
1027 MagickExport Image *RemoveImageFromList(Image **images)
1028 {
1029  Image
1030  *p;
1031 
1032  assert(images != (Image **) NULL);
1033  if ((*images) == (Image *) NULL)
1034  return((Image *) NULL);
1035  assert((*images)->signature == MagickCoreSignature);
1036  if (IsEventLogging() != MagickFalse)
1037  (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",
1038  (*images)->filename);
1039  p=(*images);
1040  if ((p->previous == (Image *) NULL) && (p->next == (Image *) NULL))
1041  *images=(Image *) NULL;
1042  else
1043  {
1044  if (p->previous != (Image *) NULL)
1045  {
1046  p->previous->next=p->next;
1047  *images=p->previous;
1048  }
1049  if (p->next != (Image *) NULL)
1050  {
1051  p->next->previous=p->previous;
1052  *images=p->next;
1053  }
1054  p->previous=(Image *) NULL;
1055  p->next=(Image *) NULL;
1056  }
1057  return(p);
1058 }
1059 
1060 /*
1061 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1062 % %
1063 % %
1064 % %
1065 % R e m o v e F i r s t I m a g e F r o m L i s t %
1066 % %
1067 % %
1068 % %
1069 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1070 %
1071 % RemoveFirstImageFromList() removes and returns the first image in the list.
1072 %
1073 % If the given image list pointer pointed to the removed first image, it is
1074 % set to the new first image of list, or NULL if list was emptied, otherwise
1075 % it is left as is.
1076 %
1077 % The format of the RemoveFirstImageFromList method is:
1078 %
1079 % Image *RemoveFirstImageFromList(Image **images)
1080 %
1081 % A description of each parameter follows:
1082 %
1083 % o images: the image list.
1084 %
1085 */
1086 MagickExport Image *RemoveFirstImageFromList(Image **images)
1087 {
1088  Image
1089  *image;
1090 
1091  assert(images != (Image **) NULL);
1092  if ((*images) == (Image *) NULL)
1093  return((Image *) NULL);
1094  assert((*images)->signature == MagickCoreSignature);
1095  if (IsEventLogging() != MagickFalse)
1096  (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",
1097  (*images)->filename);
1098  image=(*images);
1099  while (image->previous != (Image *) NULL)
1100  image=image->previous;
1101  if (image == *images)
1102  *images=(*images)->next;
1103  if (image->next != (Image *) NULL)
1104  {
1105  image->next->previous=(Image *) NULL;
1106  image->next=(Image *) NULL;
1107  }
1108  return(image);
1109 }
1110 
1111 /*
1112 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1113 % %
1114 % %
1115 % %
1116 % R e m o v e L a s t I m a g e F r o m L i s t %
1117 % %
1118 % %
1119 % %
1120 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1121 %
1122 % RemoveLastImageFromList() removes and returns the last image from the list.
1123 %
1124 % If the given image list pointer pointed to the removed last image, it is
1125 % set to the new last image of list, or NULL if list was emptied, otherwise
1126 % it is left as is.
1127 %
1128 % The format of the RemoveLastImageFromList method is:
1129 %
1130 % Image *RemoveLastImageFromList(Image **images)
1131 %
1132 % A description of each parameter follows:
1133 %
1134 % o images: the image list.
1135 %
1136 */
1137 MagickExport Image *RemoveLastImageFromList(Image **images)
1138 {
1139  Image
1140  *image;
1141 
1142  assert(images != (Image **) NULL);
1143  if ((*images) == (Image *) NULL)
1144  return((Image *) NULL);
1145  assert((*images)->signature == MagickCoreSignature);
1146  if (IsEventLogging() != MagickFalse)
1147  (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",
1148  (*images)->filename);
1149  image=(*images);
1150  while (image->next != (Image *) NULL)
1151  image=image->next;
1152  if (image == *images)
1153  *images=(*images)->previous;
1154  if (image->previous != (Image *) NULL)
1155  {
1156  image->previous->next=(Image *) NULL;
1157  image->previous=(Image *) NULL;
1158  }
1159  return(image);
1160 }
1161 
1162 /*
1163 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1164 % %
1165 % %
1166 % %
1167 % R e p l a c e I m a g e I n L i s t %
1168 % %
1169 % %
1170 % %
1171 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1172 %
1173 % ReplaceImageInList() replaces an image in the list with the given image, or
1174 % list of images. Old image is destroyed.
1175 %
1176 % The images list pointer is set to point to the first image of the inserted
1177 % list of images.
1178 %
1179 % The format of the ReplaceImageInList method is:
1180 %
1181 % ReplaceImageInList(Image **images,Image *replace)
1182 %
1183 % A description of each parameter follows:
1184 %
1185 % o images: the list and pointer to image to replace
1186 %
1187 % o replace: the image or image list replacing the original
1188 %
1189 */
1190 MagickExport void ReplaceImageInList(Image **images,Image *replace)
1191 {
1192  assert(images != (Image **) NULL);
1193  assert(replace != (Image *) NULL);
1194  assert(replace->signature == MagickCoreSignature);
1195  if (IsEventLogging() != MagickFalse)
1196  (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",replace->filename);
1197  if ((*images) == (Image *) NULL)
1198  return;
1199  assert((*images)->signature == MagickCoreSignature);
1200  /*
1201  Link next pointer.
1202  */
1203  replace=GetLastImageInList(replace);
1204  replace->next=(*images)->next;
1205  if (replace->next != (Image *) NULL)
1206  replace->next->previous=replace;
1207  /*
1208  Link previous pointer - set images position to first replacement image.
1209  */
1210  replace=GetFirstImageInList(replace);
1211  replace->previous=(*images)->previous;
1212  if (replace->previous != (Image *) NULL)
1213  replace->previous->next=replace;
1214  /*
1215  Destroy the replaced image that was in images.
1216  */
1217  (void) DestroyImage(*images);
1218  (*images)=replace;
1219 }
1220 
1221 /*
1222 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1223 % %
1224 % %
1225 % %
1226 % R e p l a c e I m a g e I n L i s t R e t u r n L a s t %
1227 % %
1228 % %
1229 % %
1230 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1231 %
1232 % ReplaceImageInListReturnLast() is exactly as ReplaceImageInList() except
1233 % the images pointer is set to the last image in the list of replacement
1234 % images.
1235 %
1236 % This allows you to simply use GetNextImageInList() to go to the image
1237 % that follows the just replaced image, even if a list of replacement images
1238 % was inserted.
1239 %
1240 % The format of the ReplaceImageInList method is:
1241 %
1242 % ReplaceImageInListReturnLast(Image **images,Image *replace)
1243 %
1244 % A description of each parameter follows:
1245 %
1246 % o images: the list and pointer to image to replace
1247 %
1248 % o replace: the image or image list replacing the original
1249 %
1250 */
1251 MagickExport void ReplaceImageInListReturnLast(Image **images,Image *replace)
1252 {
1253  assert(images != (Image **) NULL);
1254  assert(replace != (Image *) NULL);
1255  assert(replace->signature == MagickCoreSignature);
1256  if (IsEventLogging() != MagickFalse)
1257  (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",replace->filename);
1258  if ((*images) == (Image *) NULL)
1259  return;
1260  assert((*images)->signature == MagickCoreSignature);
1261  /*
1262  Link previous pointer.
1263  */
1264  replace=GetFirstImageInList(replace);
1265  replace->previous=(*images)->previous;
1266  if (replace->previous != (Image *) NULL)
1267  replace->previous->next=replace;
1268  /*
1269  Link next pointer - set images position to last replacement image.
1270  */
1271  replace=GetLastImageInList(replace);
1272  replace->next=(*images)->next;
1273  if (replace->next != (Image *) NULL)
1274  replace->next->previous=replace;
1275  /*
1276  Destroy the replaced image that was in images.
1277  */
1278  (void) DestroyImage(*images);
1279  (*images)=replace;
1280 }
1281 
1282 /*
1283 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1284 % %
1285 % %
1286 % %
1287 % R e v e r s e I m a g e L i s t %
1288 % %
1289 % %
1290 % %
1291 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1292 %
1293 % ReverseImageList() reverses the order of an image list.
1294 % The list pointer is reset to that start of the re-ordered list.
1295 %
1296 % The format of the ReverseImageList method is:
1297 %
1298 % void ReverseImageList(Image **images)
1299 %
1300 % A description of each parameter follows:
1301 %
1302 % o images: the image list.
1303 %
1304 */
1305 MagickExport void ReverseImageList(Image **images)
1306 {
1307  Image
1308  *next;
1309 
1310  Image
1311  *p;
1312 
1313  assert(images != (Image **) NULL);
1314  if ((*images) == (Image *) NULL)
1315  return;
1316  assert((*images)->signature == MagickCoreSignature);
1317  if (IsEventLogging() != MagickFalse)
1318  (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",
1319  (*images)->filename);
1320  for (p=(*images); p->next != (Image *) NULL; p=p->next) ;
1321  *images=p;
1322  for ( ; p != (Image *) NULL; p=p->next)
1323  {
1324  next=p->next;
1325  p->next=p->previous;
1326  p->previous=next;
1327  }
1328 }
1329 
1330 /*
1331 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1332 % %
1333 % %
1334 % %
1335 % S p l i c e I m a g e I n t o L i s t %
1336 % %
1337 % %
1338 % %
1339 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1340 %
1341 % SpliceImageIntoList() removes 'length' images from the list and replaces
1342 % them with the specified splice. Removed images are returned.
1343 %
1344 % The format of the SpliceImageIntoList method is:
1345 %
1346 % SpliceImageIntoList(Image **images,const size_t,
1347 % const Image *splice)
1348 %
1349 % A description of each parameter follows:
1350 %
1351 % o images: the image list.
1352 %
1353 % o length: the length of the image list to remove.
1354 %
1355 % o splice: Replace the removed image list with this list.
1356 %
1357 */
1358 MagickExport Image *SpliceImageIntoList(Image **images,
1359  const size_t length,const Image *splice)
1360 {
1361  Image
1362  *image,
1363  *split;
1364 
1365  size_t
1366  i;
1367 
1368  assert(images != (Image **) NULL);
1369  assert(splice != (Image *) NULL);
1370  assert(splice->signature == MagickCoreSignature);
1371  if ((*images) == (Image *) NULL)
1372  return((Image *) NULL);
1373  assert((*images)->signature == MagickCoreSignature);
1374  if (IsEventLogging() != MagickFalse)
1375  (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",
1376  (*images)->filename);
1377  split=SplitImageList(*images);
1378  AppendImageToList(images,splice);
1379  image=(Image *) NULL;
1380  for (i=0; (i < length) && (split != (Image *) NULL); i++)
1381  AppendImageToList(&image,RemoveImageFromList(&split));
1382  AppendImageToList(images,split);
1383  return(image);
1384 }
1385 
1386 /*
1387 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1388 % %
1389 % %
1390 % %
1391 % S p l i t I m a g e L i s t %
1392 % %
1393 % %
1394 % %
1395 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1396 %
1397 % SplitImageList() splits an image into two lists, after given image
1398 % The list that was split off is returned, which may be empty.
1399 %
1400 % The format of the SplitImageList method is:
1401 %
1402 % Image *SplitImageList(Image *images)
1403 %
1404 % A description of each parameter follows:
1405 %
1406 % o images: the image list.
1407 %
1408 */
1409 MagickExport Image *SplitImageList(Image *images)
1410 {
1411  if ((images == (Image *) NULL) || (images->next == (Image *) NULL))
1412  return((Image *) NULL);
1413  images=images->next;
1414  images->previous->next=(Image *) NULL;
1415  images->previous=(Image *) NULL;
1416  return(images);
1417 }
1418 
1419 /*
1420 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1421 % %
1422 % %
1423 % %
1424 + S y n c I m a g e L i s t %
1425 % %
1426 % %
1427 % %
1428 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1429 %
1430 % SyncImageList() synchronizes the scene numbers in an image list.
1431 %
1432 % The format of the SyncImageList method is:
1433 %
1434 % void SyncImageList(Image *images)
1435 %
1436 % A description of each parameter follows:
1437 %
1438 % o images: the image list.
1439 %
1440 */
1441 MagickExport void SyncImageList(Image *images)
1442 {
1443  Image
1444  *p,
1445  *q;
1446 
1447  if (images == (Image *) NULL)
1448  return;
1449  assert(images->signature == MagickCoreSignature);
1450  for (p=images; p != (Image *) NULL; p=p->next)
1451  {
1452  for (q=p->next; q != (Image *) NULL; q=q->next)
1453  if (p->scene == q->scene)
1454  break;
1455  if (q != (Image *) NULL)
1456  break;
1457  }
1458  if (p == (Image *) NULL)
1459  return;
1460  for (p=images->next; p != (Image *) NULL; p=p->next)
1461  p->scene=p->previous->scene+1;
1462 }
1463 
1464 /*
1465 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1466 % %
1467 % %
1468 % %
1469 + S y n c N e x t I m a g e I n L i s t %
1470 % %
1471 % %
1472 % %
1473 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1474 %
1475 % SyncNextImageInList() returns the next image in the list after the blob
1476 % referenced is synchronized with the current image.
1477 %
1478 % The format of the SyncNextImageInList method is:
1479 %
1480 % Image *SyncNextImageInList(const Image *images)
1481 %
1482 % A description of each parameter follows:
1483 %
1484 % o images: the image list.
1485 %
1486 */
1487 MagickExport Image *SyncNextImageInList(const Image *images)
1488 {
1489  if (images == (Image *) NULL)
1490  return((Image *) NULL);
1491  assert(images->signature == MagickCoreSignature);
1492  if (images->next == (Image *) NULL)
1493  return((Image *) NULL);
1494  if (images->blob != images->next->blob)
1495  {
1496  DestroyBlob(images->next);
1497  images->next->blob=ReferenceBlob(images->blob);
1498  }
1499  if (images->next->compression == UndefinedCompression)
1500  images->next->compression=images->compression;
1501  if (images->next->endian == UndefinedEndian)
1502  images->next->endian=images->endian;
1503  return(images->next);
1504 }
_Image
Definition: image.h:131
_ExceptionInfo
Definition: exception.h:101