00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039
00040 #include "magick/studio.h"
00041 #include "magick/artifact.h"
00042 #include "magick/cache.h"
00043 #include "magick/color.h"
00044 #include "magick/color-private.h"
00045 #include "magick/composite.h"
00046 #include "magick/effect.h"
00047 #include "magick/exception.h"
00048 #include "magick/exception-private.h"
00049 #include "magick/geometry.h"
00050 #include "magick/image.h"
00051 #include "magick/layer.h"
00052 #include "magick/list.h"
00053 #include "magick/memory_.h"
00054 #include "magick/monitor.h"
00055 #include "magick/monitor-private.h"
00056 #include "magick/pixel-private.h"
00057 #include "magick/property.h"
00058 #include "magick/profile.h"
00059 #include "magick/resource_.h"
00060 #include "magick/resize.h"
00061 #include "magick/statistic.h"
00062 #include "magick/string_.h"
00063 #include "magick/transform.h"
00064
00065
00066
00067
00068
00069
00070
00071
00072
00073
00074
00075
00076
00077
00078
00079
00080
00081
00082
00083
00084
00085
00086
00087
00088
00089
00090
00091
00092
00093
00094
00095 static void ClearBounds(Image *image,RectangleInfo *bounds)
00096 {
00097 ExceptionInfo
00098 *exception;
00099
00100 long
00101 y;
00102
00103 register long
00104 x;
00105
00106 register PixelPacket
00107 *q;
00108
00109 if ( bounds->x < 0 ) return;
00110 if (image->matte == MagickFalse)
00111 (void) SetImageAlphaChannel(image,OpaqueAlphaChannel);
00112 exception=(&image->exception);
00113 for (y=0; y < (long) bounds->height; y++)
00114 {
00115 q=GetAuthenticPixels(image,bounds->x,bounds->y+y,bounds->width,1,exception);
00116 if (q == (PixelPacket *) NULL)
00117 break;
00118 for (x=0; x < (long) bounds->width; x++)
00119 {
00120 q->opacity=(Quantum) TransparentOpacity;
00121 q++;
00122 }
00123 if (SyncAuthenticPixels(image,exception) == MagickFalse)
00124 break;
00125 }
00126 }
00127
00128
00129
00130
00131
00132
00133
00134
00135
00136
00137
00138
00139
00140
00141
00142
00143
00144
00145
00146
00147
00148
00149
00150
00151
00152
00153
00154
00155
00156
00157
00158
00159
00160
00161
00162 static MagickBooleanType IsBoundsCleared(const Image *image1,
00163 const Image *image2,RectangleInfo *bounds,ExceptionInfo *exception)
00164 {
00165 long
00166 y;
00167
00168 register long
00169 x;
00170
00171 register const PixelPacket
00172 *p,
00173 *q;
00174
00175 if ( bounds->x< 0 ) return(MagickFalse);
00176
00177 for (y=0; y < (long) bounds->height; y++)
00178 {
00179 p=GetVirtualPixels(image1,bounds->x,bounds->y+y,bounds->width,1,
00180 exception);
00181 q=GetVirtualPixels(image2,bounds->x,bounds->y+y,bounds->width,1,
00182 exception);
00183 if ((p == (const PixelPacket *) NULL) || (q == (PixelPacket *) NULL))
00184 break;
00185 for (x=0; x < (long) bounds->width; x++)
00186 {
00187 if ((p->opacity <= (long) (QuantumRange/2)) &&
00188 (q->opacity > (long) (QuantumRange/2)))
00189 break;
00190 p++;
00191 q++;
00192 }
00193 if (x < (long) bounds->width)
00194 break;
00195 }
00196 return(y < (long) bounds->height ? MagickTrue : MagickFalse);
00197 }
00198
00199
00200
00201
00202
00203
00204
00205
00206
00207
00208
00209
00210
00211
00212
00213
00214
00215
00216
00217
00218
00219
00220
00221
00222
00223
00224
00225
00226
00227
00228 MagickExport Image *CoalesceImages(const Image *image,ExceptionInfo *exception)
00229 {
00230 Image
00231 *coalesce_image,
00232 *dispose_image,
00233 *previous;
00234
00235 register Image
00236 *next;
00237
00238 RectangleInfo
00239 bounds;
00240
00241
00242
00243
00244 assert(image != (Image *) NULL);
00245 assert(image->signature == MagickSignature);
00246 if (image->debug != MagickFalse)
00247 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
00248 assert(exception != (ExceptionInfo *) NULL);
00249 assert(exception->signature == MagickSignature);
00250
00251
00252 next=GetFirstImageInList(image);
00253 bounds=next->page;
00254 if (bounds.width == 0)
00255 {
00256 bounds.width=next->columns;
00257 if (bounds.x > 0)
00258 bounds.width+=bounds.x;
00259 }
00260 if (bounds.height == 0)
00261 {
00262 bounds.height=next->rows;
00263 if (bounds.y > 0)
00264 bounds.height+=bounds.y;
00265 }
00266 bounds.x=0;
00267 bounds.y=0;
00268 coalesce_image=CloneImage(next,bounds.width,bounds.height,MagickTrue,
00269 exception);
00270 if (coalesce_image == (Image *) NULL)
00271 return((Image *) NULL);
00272 coalesce_image->page=bounds;
00273 coalesce_image->dispose=NoneDispose;
00274 coalesce_image->background_color.opacity=(Quantum) TransparentOpacity;
00275 (void) SetImageBackgroundColor(coalesce_image);
00276
00277
00278
00279 dispose_image=CloneImage(coalesce_image,0,0,MagickTrue,exception);
00280 (void) CompositeImage(coalesce_image,CopyCompositeOp,next,next->page.x,
00281 next->page.y);
00282 next=GetNextImageInList(next);
00283 for ( ; next != (Image *) NULL; next=GetNextImageInList(next))
00284 {
00285
00286
00287
00288 previous=GetPreviousImageInList(next);
00289 bounds=previous->page;
00290 bounds.width=previous->columns;
00291 bounds.height=previous->rows;
00292 if (bounds.x < 0)
00293 {
00294 bounds.width+=bounds.x;
00295 bounds.x=0;
00296 }
00297 if ((long) (bounds.x+bounds.width) > (long) coalesce_image->columns)
00298 bounds.width=coalesce_image->columns-bounds.x;
00299 if (bounds.y < 0)
00300 {
00301 bounds.height+=bounds.y;
00302 bounds.y=0;
00303 }
00304 if ((long) (bounds.y+bounds.height) > (long) coalesce_image->rows)
00305 bounds.height=coalesce_image->rows-bounds.y;
00306
00307
00308
00309 if (GetPreviousImageInList(next)->dispose != PreviousDispose)
00310 {
00311 dispose_image=DestroyImage(dispose_image);
00312 dispose_image=CloneImage(coalesce_image,0,0,MagickTrue,exception);
00313 if (dispose_image == (Image *) NULL)
00314 {
00315 coalesce_image=DestroyImageList(coalesce_image);
00316 return((Image *) NULL);
00317 }
00318 }
00319
00320
00321
00322 if (next->previous->dispose == BackgroundDispose)
00323 ClearBounds(dispose_image, &bounds);
00324
00325
00326
00327 coalesce_image->next=CloneImage(dispose_image,0,0,MagickTrue,exception);
00328 coalesce_image->next->previous=coalesce_image;
00329 previous=coalesce_image;
00330 coalesce_image=GetNextImageInList(coalesce_image);
00331 coalesce_image->matte=MagickTrue;
00332 (void) CompositeImage(coalesce_image,next->matte != MagickFalse ?
00333 OverCompositeOp : CopyCompositeOp,next,next->page.x,next->page.y);
00334 (void) CloneImageProfiles(coalesce_image,next);
00335 (void) CloneImageProperties(coalesce_image,next);
00336 (void) CloneImageArtifacts(coalesce_image,next);
00337 coalesce_image->page=previous->page;
00338
00339
00340
00341 if (IsBoundsCleared(previous,coalesce_image,&bounds,exception))
00342 coalesce_image->dispose=BackgroundDispose;
00343 else
00344 coalesce_image->dispose=NoneDispose;
00345 previous->dispose=coalesce_image->dispose;
00346 }
00347 dispose_image=DestroyImage(dispose_image);
00348 return(GetFirstImageInList(coalesce_image));
00349 }
00350
00351
00352
00353
00354
00355
00356
00357
00358
00359
00360
00361
00362
00363
00364
00365
00366
00367
00368
00369
00370
00371
00372
00373
00374
00375
00376
00377 MagickExport Image *DisposeImages(const Image *image,ExceptionInfo *exception)
00378 {
00379 Image
00380 *dispose_image,
00381 *dispose_images;
00382
00383 register Image
00384 *next;
00385
00386
00387
00388
00389 assert(image != (Image *) NULL);
00390 assert(image->signature == MagickSignature);
00391 if (image->debug != MagickFalse)
00392 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
00393 assert(exception != (ExceptionInfo *) NULL);
00394 assert(exception->signature == MagickSignature);
00395 next=GetFirstImageInList(image);
00396 dispose_image=CloneImage(next,next->page.width,next->page.height,MagickTrue,
00397 exception);
00398 if (dispose_image == (Image *) NULL)
00399 return((Image *) NULL);
00400 dispose_image->page=next->page;
00401 dispose_image->page.x=0;
00402 dispose_image->page.y=0;
00403 dispose_image->dispose=NoneDispose;
00404 dispose_image->background_color.opacity=(Quantum) TransparentOpacity;
00405 (void) SetImageBackgroundColor(dispose_image);
00406 dispose_images=NewImageList();
00407 for ( ; next != (Image *) NULL; next=GetNextImageInList(next))
00408 {
00409 Image
00410 *current_image;
00411
00412
00413
00414
00415 current_image=CloneImage(dispose_image,0,0,MagickTrue,exception);
00416 if (current_image == (Image *) NULL)
00417 {
00418 dispose_images=DestroyImageList(dispose_images);
00419 dispose_image=DestroyImage(dispose_image);
00420 return((Image *) NULL);
00421 }
00422 (void) CompositeImage(current_image,next->matte != MagickFalse ?
00423 OverCompositeOp : CopyCompositeOp,next,next->page.x,next->page.y);
00424
00425
00426
00427 if (next->dispose == BackgroundDispose)
00428 {
00429 RectangleInfo
00430 bounds;
00431
00432 bounds=next->page;
00433 bounds.width=next->columns;
00434 bounds.height=next->rows;
00435 if (bounds.x < 0)
00436 {
00437 bounds.width+=bounds.x;
00438 bounds.x=0;
00439 }
00440 if ((long) (bounds.x+bounds.width) > (long) current_image->columns)
00441 bounds.width=current_image->columns-bounds.x;
00442 if (bounds.y < 0)
00443 {
00444 bounds.height+=bounds.y;
00445 bounds.y=0;
00446 }
00447 if ((long) (bounds.y+bounds.height) > (long) current_image->rows)
00448 bounds.height=current_image->rows-bounds.y;
00449 ClearBounds(current_image,&bounds);
00450 }
00451
00452
00453
00454 if (next->dispose == PreviousDispose)
00455 current_image=DestroyImage(current_image);
00456 else
00457 {
00458 dispose_image=DestroyImage(dispose_image);
00459 dispose_image=current_image;
00460 }
00461 {
00462 Image
00463 *dispose;
00464
00465
00466
00467
00468 dispose=CloneImage(dispose_image,0,0,MagickTrue,exception);
00469 if (dispose == (Image *) NULL)
00470 {
00471 dispose_images=DestroyImageList(dispose_images);
00472 dispose_image=DestroyImage(dispose_image);
00473 return((Image *) NULL);
00474 }
00475 (void) CloneImageProfiles(dispose,next);
00476 (void) CloneImageProperties(dispose,next);
00477 (void) CloneImageArtifacts(dispose,next);
00478 dispose->page.x=0;
00479 dispose->page.y=0;
00480 dispose->dispose=next->dispose;
00481 AppendImageToList(&dispose_images,dispose);
00482 }
00483 }
00484 dispose_image=DestroyImage(dispose_image);
00485 return(GetFirstImageInList(dispose_images));
00486 }
00487
00488
00489
00490
00491
00492
00493
00494
00495
00496
00497
00498
00499
00500
00501
00502
00503
00504
00505
00506
00507
00508
00509
00510
00511
00512
00513
00514
00515
00516
00517
00518
00519 static MagickBooleanType ComparePixels(const ImageLayerMethod method,
00520 const MagickPixelPacket *p,const MagickPixelPacket *q)
00521 {
00522 MagickRealType
00523 o1,
00524 o2;
00525
00526
00527
00528
00529 if (method == CompareAnyLayer)
00530 return(IsMagickColorSimilar(p,q) == MagickFalse ? MagickTrue : MagickFalse);
00531
00532 o1 = (p->matte != MagickFalse) ? p->opacity : OpaqueOpacity;
00533 o2 = (q->matte != MagickFalse) ? q->opacity : OpaqueOpacity;
00534
00535
00536
00537
00538 if (method == CompareClearLayer)
00539 return((MagickBooleanType) ( (o1 <= ((MagickRealType) QuantumRange/2.0)) &&
00540 (o2 > ((MagickRealType) QuantumRange/2.0)) ) );
00541
00542
00543
00544
00545 if (method == CompareOverlayLayer)
00546 {
00547 if (o2 > ((MagickRealType) QuantumRange/2.0))
00548 return MagickFalse;
00549 return((MagickBooleanType) (IsMagickColorSimilar(p,q) == MagickFalse));
00550 }
00551 return(MagickFalse);
00552 }
00553
00554
00555
00556
00557
00558
00559
00560
00561
00562
00563
00564
00565
00566
00567
00568
00569
00570
00571
00572
00573
00574
00575
00576
00577
00578
00579
00580
00581
00582
00583
00584
00585
00586
00587
00588
00589 static RectangleInfo CompareImageBounds(const Image *image1,const Image *image2,
00590 const ImageLayerMethod method,ExceptionInfo *exception)
00591 {
00592 RectangleInfo
00593 bounds;
00594
00595 MagickPixelPacket
00596 pixel1,
00597 pixel2;
00598
00599 register const IndexPacket
00600 *indexes1,
00601 *indexes2;
00602
00603 register const PixelPacket
00604 *p,
00605 *q;
00606
00607 long
00608 y;
00609
00610 register long
00611 x;
00612
00613
00614
00615
00616 GetMagickPixelPacket(image1,&pixel1);
00617 GetMagickPixelPacket(image2,&pixel2);
00618 for (x=0; x < (long) image1->columns; x++)
00619 {
00620 p=GetVirtualPixels(image1,x,0,1,image1->rows,exception);
00621 q=GetVirtualPixels(image2,x,0,1,image2->rows,exception);
00622 if ((p == (const PixelPacket *) NULL) ||
00623 (q == (const PixelPacket *) NULL))
00624 break;
00625 indexes1=GetVirtualIndexQueue(image1);
00626 indexes2=GetVirtualIndexQueue(image2);
00627 for (y=0; y < (long) image1->rows; y++)
00628 {
00629 SetMagickPixelPacket(image1,p,indexes1+x,&pixel1);
00630 SetMagickPixelPacket(image2,q,indexes2+x,&pixel2);
00631 if (ComparePixels(method,&pixel1,&pixel2))
00632 break;
00633 p++;
00634 q++;
00635 }
00636 if (y < (long) image1->rows)
00637 break;
00638 }
00639 if ( x >= (long) image1->columns) {
00640
00641
00642
00643
00644 bounds.x=-1;
00645 bounds.y=-1;
00646 bounds.width=1;
00647 bounds.height=1;
00648 return(bounds);
00649 }
00650 bounds.x=x;
00651 for (x=(long) image1->columns-1; x >= 0; x--)
00652 {
00653 p=GetVirtualPixels(image1,x,0,1,image1->rows,exception);
00654 q=GetVirtualPixels(image2,x,0,1,image2->rows,exception);
00655 if ((p == (const PixelPacket *) NULL) ||
00656 (q == (const PixelPacket *) NULL))
00657 break;
00658 indexes1=GetVirtualIndexQueue(image1);
00659 indexes2=GetVirtualIndexQueue(image2);
00660 for (y=0; y < (long) image1->rows; y++)
00661 {
00662 SetMagickPixelPacket(image1,p,indexes1+x,&pixel1);
00663 SetMagickPixelPacket(image2,q,indexes2+x,&pixel2);
00664 if (ComparePixels(method,&pixel1,&pixel2))
00665 break;
00666 p++;
00667 q++;
00668 }
00669 if (y < (long) image1->rows)
00670 break;
00671 }
00672 bounds.width=(unsigned long) (x-bounds.x+1);
00673 for (y=0; y < (long) image1->rows; y++)
00674 {
00675 p=GetVirtualPixels(image1,0,y,image1->columns,1,exception);
00676 q=GetVirtualPixels(image2,0,y,image2->columns,1,exception);
00677 if ((p == (const PixelPacket *) NULL) ||
00678 (q == (const PixelPacket *) NULL))
00679 break;
00680 indexes1=GetVirtualIndexQueue(image1);
00681 indexes2=GetVirtualIndexQueue(image2);
00682 for (x=0; x < (long) image1->columns; x++)
00683 {
00684 SetMagickPixelPacket(image1,p,indexes1+x,&pixel1);
00685 SetMagickPixelPacket(image2,q,indexes2+x,&pixel2);
00686 if (ComparePixels(method,&pixel1,&pixel2))
00687 break;
00688 p++;
00689 q++;
00690 }
00691 if (x < (long) image1->columns)
00692 break;
00693 }
00694 bounds.y=y;
00695 for (y=(long) image1->rows-1; y >= 0; y--)
00696 {
00697 p=GetVirtualPixels(image1,0,y,image1->columns,1,exception);
00698 q=GetVirtualPixels(image2,0,y,image2->columns,1,exception);
00699 if ((p == (const PixelPacket *) NULL) ||
00700 (q == (const PixelPacket *) NULL))
00701 break;
00702 indexes1=GetVirtualIndexQueue(image1);
00703 indexes2=GetVirtualIndexQueue(image2);
00704 for (x=0; x < (long) image1->columns; x++)
00705 {
00706 SetMagickPixelPacket(image1,p,indexes1+x,&pixel1);
00707 SetMagickPixelPacket(image2,q,indexes2+x,&pixel2);
00708 if (ComparePixels(method,&pixel1,&pixel2))
00709 break;
00710 p++;
00711 q++;
00712 }
00713 if (x < (long) image1->columns)
00714 break;
00715 }
00716 bounds.height=(unsigned long) (y-bounds.y+1);
00717 return(bounds);
00718 }
00719
00720
00721
00722
00723
00724
00725
00726
00727
00728
00729
00730
00731
00732
00733
00734
00735
00736
00737
00738
00739
00740
00741
00742
00743
00744
00745
00746
00747
00748
00749
00750
00751
00752
00753
00754
00755
00756
00757
00758 MagickExport Image *CompareImageLayers(const Image *image,
00759 const ImageLayerMethod method, ExceptionInfo *exception)
00760 {
00761 Image
00762 *image_a,
00763 *image_b,
00764 *layers;
00765
00766 RectangleInfo
00767 *bounds;
00768
00769 register const Image
00770 *next;
00771
00772 register long
00773 i;
00774
00775 assert(image != (const Image *) NULL);
00776 assert(image->signature == MagickSignature);
00777 if (image->debug != MagickFalse)
00778 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
00779 assert(exception != (ExceptionInfo *) NULL);
00780 assert(exception->signature == MagickSignature);
00781 assert((method == CompareAnyLayer) ||
00782 (method == CompareClearLayer) ||
00783 (method == CompareOverlayLayer));
00784
00785
00786
00787 next=GetFirstImageInList(image);
00788 bounds=(RectangleInfo *) AcquireQuantumMemory((size_t)
00789 GetImageListLength(next),sizeof(*bounds));
00790 if (bounds == (RectangleInfo *) NULL)
00791 ThrowImageException(ResourceLimitError,"MemoryAllocationFailed");
00792
00793
00794
00795 image_a=CloneImage(next,next->page.width,next->page.height,
00796 MagickTrue,exception);
00797 if (image_a == (Image *) NULL)
00798 {
00799 bounds=(RectangleInfo *) RelinquishMagickMemory(bounds);
00800 return((Image *) NULL);
00801 }
00802 image_a->background_color.opacity=(Quantum) TransparentOpacity;
00803 (void) SetImageBackgroundColor(image_a);
00804 image_a->page=next->page;
00805 image_a->page.x=0;
00806 image_a->page.y=0;
00807 (void) CompositeImage(image_a,CopyCompositeOp,next,next->page.x,next->page.y);
00808
00809
00810
00811 i=0;
00812 next=GetNextImageInList(next);
00813 for ( ; next != (const Image *) NULL; next=GetNextImageInList(next))
00814 {
00815 image_b=CloneImage(image_a,0,0,MagickTrue,exception);
00816 if (image_b == (Image *) NULL)
00817 {
00818 image_a=DestroyImage(image_a);
00819 bounds=(RectangleInfo *) RelinquishMagickMemory(bounds);
00820 return((Image *) NULL);
00821 }
00822 (void) CompositeImage(image_a,CopyCompositeOp,next,next->page.x,
00823 next->page.y);
00824 bounds[i]=CompareImageBounds(image_b,image_a,method,exception);
00825
00826 image_b=DestroyImage(image_b);
00827 i++;
00828 }
00829 image_a=DestroyImage(image_a);
00830
00831
00832
00833 next=GetFirstImageInList(image);
00834 layers=CloneImage(next,0,0,MagickTrue,exception);
00835 if (layers == (Image *) NULL)
00836 {
00837 bounds=(RectangleInfo *) RelinquishMagickMemory(bounds);
00838 return((Image *) NULL);
00839 }
00840
00841
00842
00843 i=0;
00844 next=GetNextImageInList(next);
00845 for ( ; next != (const Image *) NULL; next=GetNextImageInList(next))
00846 {
00847 image_a=CloneImage(next,0,0,MagickTrue,exception);
00848 if (image_a == (Image *) NULL)
00849 break;
00850 image_b=CropImage(image_a,&bounds[i],exception);
00851 image_a=DestroyImage(image_a);
00852 if (image_b == (Image *) NULL)
00853 break;
00854 AppendImageToList(&layers,image_b);
00855 i++;
00856 }
00857 bounds=(RectangleInfo *) RelinquishMagickMemory(bounds);
00858 if (next != (Image *) NULL)
00859 {
00860 layers=DestroyImageList(layers);
00861 return((Image *) NULL);
00862 }
00863 return(GetFirstImageInList(layers));
00864 }
00865
00866
00867
00868
00869
00870
00871
00872
00873
00874
00875
00876
00877
00878
00879
00880
00881
00882
00883
00884
00885
00886
00887
00888
00889
00890
00891
00892
00893
00894
00895 MagickExport Image *DeconstructImages(const Image *images,
00896 ExceptionInfo *exception)
00897 {
00898 return(CompareImageLayers(images,CompareAnyLayer,exception));
00899 }
00900
00901
00902
00903
00904
00905
00906
00907
00908
00909
00910
00911
00912
00913
00914
00915
00916
00917
00918
00919
00920
00921
00922
00923
00924
00925
00926
00927
00928
00929
00930
00931
00932
00933
00934
00935
00936
00937
00938
00939
00940
00941
00942
00943 #define DupDispose ((DisposeType)9)
00944
00945
00946
00947 #define DelDispose ((DisposeType)8)
00948
00949 static Image *OptimizeLayerFrames(const Image *image,
00950 const ImageLayerMethod method, ExceptionInfo *exception)
00951 {
00952 ExceptionInfo
00953 *sans_exception;
00954
00955 Image
00956 *prev_image,
00957 *dup_image,
00958 *bgnd_image,
00959 *optimized_image;
00960
00961 RectangleInfo
00962 try_bounds,
00963 bgnd_bounds,
00964 dup_bounds,
00965 *bounds;
00966
00967 MagickBooleanType
00968 add_frames,
00969 try_cleared,
00970 cleared;
00971
00972 DisposeType
00973 *disposals;
00974
00975 register const Image
00976 *next;
00977
00978 register long
00979 i;
00980
00981 assert(image != (const Image *) NULL);
00982 assert(image->signature == MagickSignature);
00983 if (image->debug != MagickFalse)
00984 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
00985 assert(exception != (ExceptionInfo *) NULL);
00986 assert(exception->signature == MagickSignature);
00987 assert(method == OptimizeLayer ||
00988 method == OptimizeImageLayer ||
00989 method == OptimizePlusLayer);
00990
00991
00992
00993
00994 add_frames=method == OptimizePlusLayer ? MagickTrue : MagickFalse;
00995
00996
00997
00998 next=GetFirstImageInList(image);
00999 for (; next != (Image *) NULL; next=GetNextImageInList(next))
01000 {
01001 if ((next->columns != image->columns) || (next->rows != image->rows))
01002 ThrowImageException(OptionError,"ImagesAreNotTheSameSize");
01003
01004
01005
01006 }
01007
01008
01009
01010 next=GetFirstImageInList(image);
01011 bounds=(RectangleInfo *) AcquireQuantumMemory((size_t)
01012 GetImageListLength(next),(add_frames != MagickFalse ? 2UL : 1UL)*
01013 sizeof(*bounds));
01014 if (bounds == (RectangleInfo *) NULL)
01015 ThrowImageException(ResourceLimitError,"MemoryAllocationFailed");
01016 disposals=(DisposeType *) AcquireQuantumMemory((size_t)
01017 GetImageListLength(image),(add_frames != MagickFalse ? 2UL : 1UL)*
01018 sizeof(*disposals));
01019 if (disposals == (DisposeType *) NULL)
01020 {
01021 bounds=(RectangleInfo *) RelinquishMagickMemory(bounds);
01022 ThrowImageException(ResourceLimitError,"MemoryAllocationFailed");
01023 }
01024
01025
01026
01027 prev_image=CloneImage(next,next->page.