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