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
00041
00042 #include "magick/studio.h"
00043 #include "magick/cache.h"
00044 #include "magick/cache-view.h"
00045 #include "magick/color.h"
00046 #include "magick/color-private.h"
00047 #include "magick/composite.h"
00048 #include "magick/effect.h"
00049 #include "magick/exception.h"
00050 #include "magick/exception-private.h"
00051 #include "magick/geometry.h"
00052 #include "magick/image.h"
00053 #include "magick/memory_.h"
00054 #include "magick/layer.h"
00055 #include "magick/list.h"
00056 #include "magick/monitor.h"
00057 #include "magick/monitor-private.h"
00058 #include "magick/pixel-private.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 MagickExport Image *ChopImage(const Image *image,const RectangleInfo *chop_info,
00094 ExceptionInfo *exception)
00095 {
00096 #define ChopImageTag "Chop/Image"
00097
00098 Image
00099 *chop_image;
00100
00101 long
00102 j,
00103 y;
00104
00105 MagickBooleanType
00106 proceed;
00107
00108 RectangleInfo
00109 extent;
00110
00111 register long
00112 i;
00113
00114 ViewInfo
00115 *chop_view,
00116 *image_view;
00117
00118
00119
00120
00121 assert(image != (const Image *) NULL);
00122 assert(image->signature == MagickSignature);
00123 if (image->debug != MagickFalse)
00124 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
00125 assert(exception != (ExceptionInfo *) NULL);
00126 assert(exception->signature == MagickSignature);
00127 assert(chop_info != (RectangleInfo *) NULL);
00128 if (((chop_info->x+(long) chop_info->width) < 0) ||
00129 ((chop_info->y+(long) chop_info->height) < 0) ||
00130 (chop_info->x > (long) image->columns) ||
00131 (chop_info->y > (long) image->rows))
00132 ThrowImageException(OptionWarning,"GeometryDoesNotContainImage");
00133 extent=(*chop_info);
00134 if ((extent.x+(long) extent.width) > (long) image->columns)
00135 extent.width=(unsigned long) ((long) image->columns-extent.x);
00136 if ((extent.y+(long) extent.height) > (long) image->rows)
00137 extent.height=(unsigned long) ((long) image->rows-extent.y);
00138 if (extent.x < 0)
00139 {
00140 extent.width-=(unsigned long) (-extent.x);
00141 extent.x=0;
00142 }
00143 if (extent.y < 0)
00144 {
00145 extent.height-=(unsigned long) (-extent.y);
00146 extent.y=0;
00147 }
00148 chop_image=CloneImage(image,image->columns-extent.width,image->rows-
00149 extent.height,MagickTrue,exception);
00150 if (chop_image == (Image *) NULL)
00151 return((Image *) NULL);
00152
00153
00154
00155 i=0;
00156 j=0;
00157 image_view=AcquireCacheView(image);
00158 chop_view=AcquireCacheView(chop_image);
00159 for (y=0; y < (long) extent.y; y++)
00160 {
00161 register const PixelPacket
00162 *__restrict p;
00163
00164 register IndexPacket
00165 *__restrict chop_indexes,
00166 *__restrict indexes;
00167
00168 register long
00169 x;
00170
00171 register PixelPacket
00172 *__restrict q;
00173
00174 p=GetCacheViewVirtualPixels(image_view,0,i++,image->columns,1,exception);
00175 q=QueueCacheViewAuthenticPixels(chop_view,0,j++,chop_image->columns,1,
00176 exception);
00177 if ((p == (const PixelPacket *) NULL) || (q == (PixelPacket *) NULL))
00178 break;
00179 indexes=GetCacheViewAuthenticIndexQueue(image_view);
00180 chop_indexes=GetCacheViewAuthenticIndexQueue(chop_view);
00181 for (x=0; x < (long) image->columns; x++)
00182 {
00183 if ((x < extent.x) || (x >= (long) (extent.x+extent.width)))
00184 {
00185 *q=(*p);
00186 if (indexes != (IndexPacket *) NULL)
00187 {
00188 if (chop_indexes != (IndexPacket *) NULL)
00189 *chop_indexes++=indexes[x];
00190 }
00191 q++;
00192 }
00193 p++;
00194 }
00195 if (SyncCacheViewAuthenticPixels(chop_view,exception) == MagickFalse)
00196 break;
00197 proceed=SetImageProgress(image,ChopImageTag,y,chop_image->rows);
00198 if (proceed == MagickFalse)
00199 break;
00200 }
00201
00202
00203
00204 i+=extent.height;
00205 for (y=0; y < (long) (image->rows-(extent.y+extent.height)); y++)
00206 {
00207 register const PixelPacket
00208 *__restrict p;
00209
00210 register IndexPacket
00211 *__restrict chop_indexes,
00212 *__restrict indexes;
00213
00214 register long
00215 x;
00216
00217 register PixelPacket
00218 *__restrict q;
00219
00220 p=GetCacheViewVirtualPixels(image_view,0,i++,image->columns,1,exception);
00221 q=QueueCacheViewAuthenticPixels(chop_view,0,j++,chop_image->columns,1,
00222 exception);
00223 if ((p == (PixelPacket *) NULL) || (q == (PixelPacket *) NULL))
00224 break;
00225 indexes=GetCacheViewAuthenticIndexQueue(image_view);
00226 chop_indexes=GetCacheViewAuthenticIndexQueue(chop_view);
00227 for (x=0; x < (long) image->columns; x++)
00228 {
00229 if ((x < extent.x) || (x >= (long) (extent.x+extent.width)))
00230 {
00231 *q=(*p);
00232 if (indexes != (IndexPacket *) NULL)
00233 {
00234 if (chop_indexes != (IndexPacket *) NULL)
00235 *chop_indexes++=indexes[x];
00236 }
00237 q++;
00238 }
00239 p++;
00240 }
00241 if (SyncCacheViewAuthenticPixels(chop_view,exception) == MagickFalse)
00242 break;
00243 proceed=SetImageProgress(image,ChopImageTag,y,chop_image->rows);
00244 if (proceed == MagickFalse)
00245 break;
00246 }
00247 chop_view=DestroyCacheView(chop_view);
00248 image_view=DestroyCacheView(image_view);
00249 chop_image->type=image->type;
00250 return(chop_image);
00251 }
00252
00253
00254
00255
00256
00257
00258
00259
00260
00261
00262
00263
00264
00265
00266
00267
00268
00269
00270
00271
00272
00273
00274
00275
00276
00277
00278 MagickExport Image *ConsolidateCMYKImages(const Image *images,
00279 ExceptionInfo *exception)
00280 {
00281 Image
00282 *cmyk_image,
00283 *cmyk_images;
00284
00285 long
00286 y;
00287
00288 register long
00289 i;
00290
00291
00292
00293
00294 assert(images != (Image *) NULL);
00295 assert(images->signature == MagickSignature);
00296 if (images->debug != MagickFalse)
00297 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",images->filename);
00298 assert(exception != (ExceptionInfo *) NULL);
00299 assert(exception->signature == MagickSignature);
00300 cmyk_images=NewImageList();
00301 for (i=0; i < (long) GetImageListLength(images); i+=4)
00302 {
00303 cmyk_image=CloneImage(images,images->columns,images->rows,MagickTrue,
00304 exception);
00305 if (cmyk_image == (Image *) NULL)
00306 break;
00307 if (SetImageStorageClass(cmyk_image,DirectClass) == MagickFalse)
00308 break;
00309 (void) SetImageColorspace(cmyk_image,CMYKColorspace);
00310 for (y=0; y < (long) images->rows; y++)
00311 {
00312 register const PixelPacket
00313 *__restrict p;
00314
00315 register long
00316 x;
00317
00318 register PixelPacket
00319 *__restrict q;
00320
00321 p=GetVirtualPixels(images,0,y,images->columns,1,exception);
00322 q=QueueAuthenticPixels(cmyk_image,0,y,cmyk_image->columns,1,exception);
00323 if ((p == (const PixelPacket *) NULL) || (q == (PixelPacket *) NULL))
00324 break;
00325 for (x=0; x < (long) images->columns; x++)
00326 {
00327 q->red=(Quantum) (QuantumRange-PixelIntensityToQuantum(p));
00328 p++;
00329 q++;
00330 }
00331 if (SyncAuthenticPixels(cmyk_image,exception) == MagickFalse)
00332 break;
00333 }
00334 images=GetNextImageInList(images);
00335 if (images == (Image *) NULL)
00336 break;
00337 for (y=0; y < (long) images->rows; y++)
00338 {
00339 register const PixelPacket
00340 *__restrict p;
00341
00342 register long
00343 x;
00344
00345 register PixelPacket
00346 *__restrict q;
00347
00348 p=GetVirtualPixels(images,0,y,images->columns,1,exception);
00349 q=GetAuthenticPixels(cmyk_image,0,y,cmyk_image->columns,1,exception);
00350 if ((p == (const PixelPacket *) NULL) || (q == (PixelPacket *) NULL))
00351 break;
00352 for (x=0; x < (long) images->columns; x++)
00353 {
00354 q->green=(Quantum) (QuantumRange-PixelIntensityToQuantum(p));
00355 p++;
00356 q++;
00357 }
00358 if (SyncAuthenticPixels(cmyk_image,exception) == MagickFalse)
00359 break;
00360 }
00361 images=GetNextImageInList(images);
00362 if (images == (Image *) NULL)
00363 break;
00364 for (y=0; y < (long) images->rows; y++)
00365 {
00366 register const PixelPacket
00367 *__restrict p;
00368
00369 register long
00370 x;
00371
00372 register PixelPacket
00373 *__restrict q;
00374
00375 p=GetVirtualPixels(images,0,y,images->columns,1,exception);
00376 q=GetAuthenticPixels(cmyk_image,0,y,cmyk_image->columns,1,exception);
00377 if ((p == (const PixelPacket *) NULL) || (q == (PixelPacket *) NULL))
00378 break;
00379 for (x=0; x < (long) images->columns; x++)
00380 {
00381 q->blue=(Quantum) (QuantumRange-PixelIntensityToQuantum(p));
00382 p++;
00383 q++;
00384 }
00385 if (SyncAuthenticPixels(cmyk_image,exception) == MagickFalse)
00386 break;
00387 }
00388 images=GetNextImageInList(images);
00389 if (images == (Image *) NULL)
00390 break;
00391 for (y=0; y < (long) images->rows; y++)
00392 {
00393 register const PixelPacket
00394 *__restrict p;
00395
00396 register IndexPacket
00397 *__restrict indexes;
00398
00399 register long
00400 x;
00401
00402 register PixelPacket
00403 *__restrict q;
00404
00405 p=GetVirtualPixels(images,0,y,images->columns,1,exception);
00406 q=GetAuthenticPixels(cmyk_image,0,y,cmyk_image->columns,1,exception);
00407 if ((p == (const PixelPacket *) NULL) || (q == (PixelPacket *) NULL))
00408 break;
00409 indexes=GetAuthenticIndexQueue(cmyk_image);
00410 for (x=0; x < (long) images->columns; x++)
00411 {
00412 indexes[x]=(IndexPacket) (QuantumRange-PixelIntensityToQuantum(p));
00413 p++;
00414 }
00415 if (SyncAuthenticPixels(cmyk_image,exception) == MagickFalse)
00416 break;
00417 }
00418 AppendImageToList(&cmyk_images,cmyk_image);
00419 images=GetNextImageInList(images);
00420 if (images == (Image *) NULL)
00421 break;
00422 }
00423 return(cmyk_images);
00424 }
00425
00426
00427
00428
00429
00430
00431
00432
00433
00434
00435
00436
00437
00438
00439
00440
00441
00442
00443
00444
00445
00446
00447
00448
00449
00450
00451
00452
00453
00454
00455 MagickExport Image *CropImage(const Image *image,const RectangleInfo *geometry,
00456 ExceptionInfo *exception)
00457 {
00458 #define CropImageTag "Crop/Image"
00459
00460 Image
00461 *crop_image;
00462
00463 long
00464 progress,
00465 y;
00466
00467 MagickBooleanType
00468 status;
00469
00470 RectangleInfo
00471 bounding_box,
00472 page;
00473
00474 ViewInfo
00475 *crop_view,
00476 *image_view;
00477
00478
00479
00480
00481 assert(image != (const Image *) NULL);
00482 assert(image->signature == MagickSignature);
00483 if (image->debug != MagickFalse)
00484 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
00485 assert(geometry != (const RectangleInfo *) NULL);
00486 assert(exception != (ExceptionInfo *) NULL);
00487 assert(exception->signature == MagickSignature);
00488 bounding_box=image->page;
00489 if ((bounding_box.width == 0) || (bounding_box.height == 0))
00490 {
00491 bounding_box.width=image->columns;
00492 bounding_box.height=image->rows;
00493 }
00494 page=(*geometry);
00495 if (page.width == 0)
00496 page.width=bounding_box.width;
00497 if (page.height == 0)
00498 page.height=bounding_box.height;
00499 if (((bounding_box.x-page.x) >= (long) page.width) ||
00500 ((bounding_box.y-page.y) >= (long) page.height) ||
00501 ((page.x-bounding_box.x) > (long) image->columns) ||
00502 ((page.y-bounding_box.y) > (long) image->rows))
00503 {
00504
00505
00506
00507 (void) ThrowMagickException(exception,GetMagickModule(),OptionWarning,
00508 "GeometryDoesNotContainImage","`%s'",image->filename);
00509 crop_image=CloneImage(image,1,1,MagickTrue,exception);
00510 if (crop_image == (Image *) NULL)
00511 return((Image *) NULL);
00512 crop_image->background_color.opacity=(Quantum) TransparentOpacity;
00513 (void) SetImageBackgroundColor(crop_image);
00514 crop_image->page=bounding_box;
00515 crop_image->page.x=(-1);
00516 crop_image->page.y=(-1);
00517 if (crop_image->dispose == BackgroundDispose)
00518 crop_image->dispose=NoneDispose;
00519 return(crop_image);
00520 }
00521 if ((page.x < 0) && (bounding_box.x >= 0))
00522 {
00523 page.width+=page.x-bounding_box.x;
00524 page.x=0;
00525 }
00526 else
00527 {
00528 page.width-=bounding_box.x-page.x;
00529 page.x-=bounding_box.x;
00530 if (page.x < 0)
00531 page.x=0;
00532 }
00533 if ((page.y < 0) && (bounding_box.y >= 0))
00534 {
00535 page.height+=page.y-bounding_box.y;
00536 page.y=0;
00537 }
00538 else
00539 {
00540 page.height-=bounding_box.y-page.y;
00541 page.y-=bounding_box.y;
00542 if (page.y < 0)
00543 page.y=0;
00544 }
00545 if ((unsigned long) (page.x+page.width) > image->columns)
00546 page.width=image->columns-page.x;
00547 if (geometry->width != 0)
00548 if (page.width > geometry->width)
00549 page.width=geometry->width;
00550 if ((unsigned long) (page.y+page.height) > image->rows)
00551 page.height=image->rows-page.y;
00552 if (geometry->height != 0)
00553 if (page.height > geometry->height)
00554 page.height=geometry->height;
00555 bounding_box.x+=page.x;
00556 bounding_box.y+=page.y;
00557 if ((page.width == 0) || (page.height == 0))
00558 {
00559 (void) ThrowMagickException(exception,GetMagickModule(),OptionWarning,
00560 "GeometryDoesNotContainImage","`%s'",image->filename);
00561 return((Image *) NULL);
00562 }
00563
00564
00565
00566 crop_image=CloneImage(image,page.width,page.height,MagickTrue,exception);
00567 if (crop_image == (Image *) NULL)
00568 return((Image *) NULL);
00569 crop_image->page.width=image->page.width;
00570 crop_image->page.height=image->page.height;
00571 if (((long) (bounding_box.x+bounding_box.width) > (long) image->page.width) ||
00572 ((long) (bounding_box.y+bounding_box.height) > (long) image->page.height))
00573 {
00574 crop_image->page.width=bounding_box.width;
00575 crop_image->page.height=bounding_box.height;
00576 }
00577 crop_image->page.x=bounding_box.x;
00578 crop_image->page.y=bounding_box.y;
00579
00580
00581
00582 status=MagickTrue;
00583 progress=0;
00584 image_view=AcquireCacheView(image);
00585 crop_view=AcquireCacheView(crop_image);
00586 #if defined(MAGICKCORE_OPENMP_SUPPORT)
00587 #pragma omp parallel for schedule(dynamic,4) shared(progress,status)
00588 #endif
00589 for (y=0; y < (long) crop_image->rows; y++)
00590 {
00591 register const IndexPacket
00592 *__restrict indexes;
00593
00594 register const PixelPacket
00595 *__restrict p;
00596
00597 register IndexPacket
00598 *__restrict crop_indexes;
00599
00600 register PixelPacket
00601 *__restrict q;
00602
00603 if (status == MagickFalse)
00604 continue;
00605 p=GetCacheViewVirtualPixels(image_view,page.x,page.y+y,crop_image->columns,
00606 1,exception);
00607 q=QueueCacheViewAuthenticPixels(crop_view,0,y,crop_image->columns,1,
00608 exception);
00609 if ((p == (const PixelPacket *) NULL) || (q == (PixelPacket *) NULL))
00610 {
00611 status=MagickFalse;
00612 continue;
00613 }
00614 (void) CopyMagickMemory(q,p,(size_t) crop_image->columns*sizeof(*q));
00615 indexes=GetCacheViewVirtualIndexQueue(image_view);
00616 if (indexes != (IndexPacket *) NULL)
00617 {
00618 crop_indexes=GetCacheViewAuthenticIndexQueue(crop_view);
00619 if (crop_indexes != (IndexPacket *) NULL)
00620 (void) CopyMagickMemory(crop_indexes,indexes,(size_t)
00621 crop_image->columns*sizeof(*crop_indexes));
00622 }
00623 if (SyncCacheViewAuthenticPixels(crop_view,exception) == MagickFalse)
00624 status=MagickFalse;
00625 if (image->progress_monitor != (MagickProgressMonitor) NULL)
00626 {
00627 MagickBooleanType
00628 proceed;
00629
00630 #if defined(MAGICKCORE_OPENMP_SUPPORT)
00631 #pragma omp critical (MagickCore_CropImage)
00632 #endif
00633 proceed=SetImageProgress(image,CropImageTag,progress++,image->rows);
00634 if (proceed == MagickFalse)
00635 status=MagickFalse;
00636 }
00637 }
00638 crop_view=DestroyCacheView(crop_view);
00639 image_view=DestroyCacheView(image_view);
00640 crop_image->type=image->type;
00641 if (status == MagickFalse)
00642 crop_image=DestroyImage(crop_image);
00643 return(crop_image);
00644 }
00645
00646
00647
00648
00649
00650
00651
00652
00653
00654
00655
00656
00657
00658
00659
00660
00661
00662
00663
00664
00665
00666
00667
00668
00669
00670
00671
00672
00673
00674 MagickExport Image *ExcerptImage(const Image *image,
00675 const RectangleInfo *geometry,ExceptionInfo *exception)
00676 {
00677 #define ExcerptImageTag "Excerpt/Image"
00678
00679 Image
00680 *excerpt_image;
00681
00682 long
00683 progress,
00684 y;
00685
00686 MagickBooleanType
00687 status;
00688
00689 ViewInfo
00690 *excerpt_view,
00691 *image_view;
00692
00693
00694
00695
00696 assert(image != (const Image *) NULL);
00697 assert(image->signature == MagickSignature);
00698 if (image->debug != MagickFalse)
00699 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
00700 assert(geometry != (const RectangleInfo *) NULL);
00701 assert(exception != (ExceptionInfo *) NULL);
00702 assert(exception->signature == MagickSignature);
00703 excerpt_image=CloneImage(image,geometry->width,geometry->height,MagickTrue,
00704 exception);
00705 if (excerpt_image == (Image *) NULL)
00706 return((Image *) NULL);
00707
00708
00709
00710 status=MagickTrue;
00711 progress=0;
00712 image_view=AcquireCacheView(image);
00713 excerpt_view=AcquireCacheView(excerpt_image);
00714 #if defined(MAGICKCORE_OPENMP_SUPPORT)
00715 #pragma omp parallel for schedule(dynamic,4) shared(progress,status)
00716 #endif
00717 for (y=0; y < (long) excerpt_image->rows; y++)
00718 {
00719 register const PixelPacket
00720 *__restrict p;
00721
00722 register IndexPacket
00723 *__restrict excerpt_indexes,
00724 *__restrict indexes;
00725
00726 register PixelPacket
00727 *__restrict q;
00728
00729 if (status == MagickFalse)
00730 continue;
00731 p=GetCacheViewVirtualPixels(image_view,geometry->x,geometry->y+y,
00732 geometry->width,1,exception);
00733 q=GetCacheViewAuthenticPixels(excerpt_view,0,y,excerpt_image->columns,1,
00734 exception);
00735 if ((p == (const PixelPacket *) NULL) || (q == (PixelPacket *) NULL))
00736 {
00737 status=MagickFalse;
00738 continue;
00739 }
00740 (void) CopyMagickMemory(q,p,(size_t) excerpt_image->columns*sizeof(*q));
00741 indexes=GetCacheViewAuthenticIndexQueue(image_view);
00742 if (indexes != (IndexPacket *) NULL)
00743 {
00744 excerpt_indexes=GetCacheViewAuthenticIndexQueue(excerpt_view);
00745 if (excerpt_indexes != (IndexPacket *) NULL)
00746 (void) CopyMagickMemory(excerpt_indexes,indexes,(size_t)
00747 excerpt_image->columns*sizeof(*excerpt_indexes));
00748 }
00749 if (SyncCacheViewAuthenticPixels(excerpt_view,exception) == MagickFalse)
00750 status=MagickFalse;
00751 if (image->progress_monitor != (MagickProgressMonitor) NULL)
00752 {
00753 MagickBooleanType
00754 proceed;
00755
00756 #if defined(MAGICKCORE_OPENMP_SUPPORT)
00757 #pragma omp critical (MagickCore_ExcerptImage)
00758 #endif
00759 proceed=SetImageProgress(image,ExcerptImageTag,progress++,image->rows);
00760 if (proceed == MagickFalse)
00761 status=MagickFalse;
00762 }
00763 }
00764 excerpt_view=DestroyCacheView(excerpt_view);
00765 image_view=DestroyCacheView(image_view);
00766 excerpt_image->type=image->type;
00767 if (status == MagickFalse)
00768 excerpt_image=DestroyImage(excerpt_image);
00769 return(excerpt_image);
00770 }
00771
00772
00773
00774
00775
00776
00777
00778
00779
00780
00781
00782
00783
00784
00785
00786
00787
00788
00789
00790
00791
00792
00793
00794
00795
00796
00797
00798
00799
00800
00801
00802 MagickExport Image *ExtentImage(const Image *image,
00803 const RectangleInfo *geometry,ExceptionInfo *exception)
00804 {
00805 Image
00806 *extent_image;
00807
00808
00809
00810
00811 assert(image != (const Image *) NULL);
00812 assert(image->signature == MagickSignature);
00813 if (image->debug != MagickFalse)
00814 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
00815 assert(geometry != (const RectangleInfo *) NULL);
00816 assert(exception != (ExceptionInfo *) NULL);
00817 assert(exception->signature == MagickSignature);
00818 extent_image=CloneImage(image,geometry->width,geometry->height,MagickTrue,
00819 exception);
00820 if (extent_image == (Image *) NULL)
00821 return((Image *) NULL);
00822 if (SetImageStorageClass(extent_image,DirectClass) == MagickFalse)
00823 {
00824 InheritException(exception,&extent_image->exception);
00825 extent_image=DestroyImage(extent_image);
00826 return((Image *) NULL);
00827 }
00828 if (image->background_color.opacity != OpaqueOpacity)
00829 extent_image->matte=MagickTrue;
00830 (void) SetImageBackgroundColor(extent_image);
00831 (void) CompositeImage(extent_image,image->compose,image,-geometry->x,
00832 -geometry->y);
00833 return(extent_image);
00834 }
00835
00836
00837
00838
00839
00840
00841
00842
00843
00844
00845
00846
00847
00848
00849
00850
00851
00852
00853
00854
00855
00856
00857
00858
00859
00860
00861 MagickExport Image *FlipImage(const Image *image,ExceptionInfo *exception)
00862 {
00863 #define FlipImageTag "Flip/Image"
00864
00865 Image
00866 *flip_image;
00867
00868 long
00869 progress,
00870 y;
00871
00872 MagickBooleanType
00873 status;
00874
00875 ViewInfo
00876 *flip_view,
00877 *image_view;
00878
00879 assert(image != (const Image *) NULL);
00880 assert(image->signature == MagickSignature);
00881 if (image->debug != MagickFalse)
00882 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
00883 assert(exception != (ExceptionInfo *) NULL);
00884 assert(exception->signature == MagickSignature);
00885 flip_image=CloneImage(image,image->columns,image->rows,MagickTrue,exception);
00886 if (flip_image == (Image *) NULL)
00887 return((Image *) NULL);
00888
00889
00890
00891 status=MagickTrue;
00892 progress=0;
00893 image_view=AcquireCacheView(image);
00894 flip_view=AcquireCacheView(flip_image);
00895 #if defined(MAGICKCORE_OPENMP_SUPPORT)
00896 #pragma omp parallel for schedule(dynamic,4) shared(progress,status)
00897 #endif
00898 for (y=0; y < (long) flip_image->rows; y++)
00899 {
00900 register const IndexPacket
00901 *__restrict indexes;
00902
00903 register const PixelPacket
00904 *__restrict p;
00905
00906 register IndexPacket
00907 *__restrict flip_indexes;
00908
00909 register PixelPacket
00910 *__restrict q;
00911
00912 if (status == MagickFalse)
00913 continue;
00914 p=GetCacheViewVirtualPixels(image_view,0,y,image->columns,1,exception);
00915 q=QueueCacheViewAuthenticPixels(flip_view,0,(long) (flip_image->rows-y-1),
00916 flip_image->columns,1,exception);
00917 if ((p == (const PixelPacket *) NULL) || (q == (PixelPacket *) NULL))
00918 {
00919 status=MagickFalse;
00920 continue;
00921 }
00922 (void) CopyMagickMemory(q,p,(size_t) image->columns*sizeof(*q));
00923 indexes=GetCacheViewVirtualIndexQueue(image_view);
00924 if (indexes != (const IndexPacket *) NULL)
00925 {
00926 flip_indexes=GetCacheViewAuthenticIndexQueue(flip_view);
00927 if (flip_indexes != (IndexPacket *) NULL)
00928 (void) CopyMagickMemory(flip_indexes,indexes,(size_t) image->columns*
00929 sizeof(*flip_indexes));
00930 }
00931 if (SyncCacheViewAuthenticPixels(flip_view,exception) == MagickFalse)
00932 status=MagickFalse;
00933 if (image->progress_monitor != (MagickProgressMonitor) NULL)
00934 {
00935 MagickBooleanType
00936 proceed;
00937
00938 #if defined(MAGICKCORE_OPENMP_SUPPORT)
00939 #pragma omp critical (MagickCore_FlipImage)
00940 #endif
00941 proceed=SetImageProgress(image,FlipImageTag,progress++,image->rows);
00942 if (proceed == MagickFalse)
00943 status=MagickFalse;
00944 }
00945 }
00946 flip_view=DestroyCacheView(flip_view);
00947 image_view=DestroyCacheView(image_view);
00948 flip_image->type=image->type;
00949 if (status == MagickFalse)
00950 flip_image=DestroyImage(flip_image);
00951 return(flip_image);
00952 }
00953
00954
00955
00956
00957
00958
00959
00960
00961
00962
00963
00964
00965
00966
00967
00968
00969
00970
00971
00972
00973
00974
00975
00976
00977
00978
00979 MagickExport Image *FlopImage(const Image *image,ExceptionInfo *exception)
00980 {
00981 #define FlopImageTag "Flop/Image"
00982
00983 Image
00984 *flop_image;
00985
00986 long
00987 progress,
00988 y;
00989
00990 MagickBooleanType
00991 status;
00992
00993 ViewInfo
00994 *flop_view,
00995 *image_view;
00996
00997 assert(image != (const Image *) NULL);
00998 assert(image->signature == MagickSignature);
00999 if (image->debug != MagickFalse)
01000 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
01001 assert(exception != (ExceptionInfo *) NULL);
01002 assert(exception->signature == MagickSignature);
01003 flop_image=CloneImage(image,image->columns,image->rows,MagickTrue,exception);
01004 if (flop_image == (Image *) NULL)
01005 return((Image *) NULL);
01006
01007
01008
01009 status=MagickTrue;
01010 progress=0;
01011 image_view=AcquireCacheView(image);
01012 flop_view=AcquireCacheView(flop_image);
01013 #if defined(MAGICKCORE_OPENMP_SUPPORT)
01014 #pragma omp parallel for schedule(dynamic,4) shared(progress,status)
01015 #endif
01016 for (y=0; y < (long) flop_image->rows; y++)
01017 {
01018 register const IndexPacket
01019 *__restrict indexes;
01020
01021 register const PixelPacket
01022 *__restrict p;
01023
01024 register IndexPacket
01025 *__restrict flop_indexes;
01026
01027 register long
01028 x;
01029
01030 register PixelPacket
01031 *__restrict q;
01032
01033 if (status == MagickFalse)
01034 continue;
01035 p=GetCacheViewVirtualPixels(image_view,0,y,image->columns,1,exception);
01036 q=QueueCacheViewAuthenticPixels(flop_view,0,y,flop_image->columns,1,
01037 exception);
01038 if ((p == (PixelPacket *) NULL) || (q == (PixelPacket *) NULL))
01039 {
01040 status=MagickFalse;
01041 continue;
01042 }
01043 q+=flop_image->columns;
01044 indexes=GetCacheViewVirtualIndexQueue(image_view);
01045 flop_indexes=GetCacheViewAuthenticIndexQueue(flop_view);
01046 for (x=0; x < (long) flop_image->columns; x++)
01047 {
01048 (*--q)=(*p++);
01049 if ((indexes != (const IndexPacket *) NULL) &&
01050 (flop_indexes != (IndexPacket *) NULL))
01051 flop_indexes[flop_image->columns-x-1]=indexes[x];
01052 }
01053 if (SyncCacheViewAuthenticPixels(flop_view,exception) == MagickFalse)
01054 status=MagickFalse;
01055 if (image->progress_monitor != (MagickProgressMonitor) NULL)
01056 {
01057 MagickBooleanType
01058 proceed;
01059
01060 #if defined(MAGICKCORE_OPENMP_SUPPORT)
01061 #pragma omp critical (MagickCore_FlopImage)
01062 #endif
01063 proceed=SetImageProgress(image,FlopImageTag,progress++,image->rows);
01064 if (proceed == MagickFalse)
01065 status=MagickFalse;
01066 }
01067 }
01068 flop_view=DestroyCacheView(flop_view);
01069 image_view=DestroyCacheView(image_view);
01070 flop_image->type=image->type;
01071 if (status == MagickFalse)
01072 flop_image=DestroyImage(flop_image);
01073 return(flop_image);
01074 }
01075
01076
01077
01078
01079
01080
01081
01082
01083
01084
01085
01086
01087
01088
01089
01090
01091
01092
01093
01094
01095
01096
01097
01098
01099
01100
01101
01102
01103
01104
01105
01106 static inline MagickBooleanType CopyImageRegion(Image *destination,
01107 const Image *source,const unsigned long columns,const unsigned long rows,
01108 const long sx,const long sy,const long dx,const long dy,
01109 ExceptionInfo *exception)
01110 {
01111 long
01112 y;
01113
01114 MagickBooleanType
01115 status;
01116
01117 ViewInfo
01118 *source_view,
01119 *destination_view;
01120
01121 status=MagickTrue;
01122 source_view=AcquireCacheView(source);
01123 destination_view=AcquireCacheView(destination);
01124 #if defined(MAGICKCORE_OPENMP_SUPPORT)
01125 #pragma omp parallel for schedule(dynamic,4) shared(status)
01126 #endif
01127 for (y=0; y < (long) rows; y++)
01128 {
01129 MagickBooleanType
01130 sync;
01131
01132 register const PixelPacket
01133 *__restrict p;
01134
01135 register IndexPacket
01136 *__restrict indexes,
01137 *__restrict destination_indexes;
01138
01139 register long
01140 x;
01141
01142 register PixelPacket
01143 *__restrict q;
01144
01145
01146
01147
01148 if (status == MagickFalse)
01149 continue;
01150 p=GetCacheViewVirtualPixels(source_view,sx,sy+y,columns,1,exception);
01151 q=GetCacheViewAuthenticPixels(destination_view,dx,dy+y,columns,1,exception);
01152 if ((p == (const PixelPacket *) NULL) || (q == (PixelPacket *) NULL))
01153 {
01154 status=MagickFalse;
01155 continue;
01156 }
01157 indexes=GetCacheViewAuthenticIndexQueue(source_view);
01158 for (x=0; x < (long) columns; x++)
01159 *q++=(*p++);
01160 if (indexes != (IndexPacket *) NULL)
01161 {
01162 destination_indexes=GetCacheViewAuthenticIndexQueue(destination_view);
01163 for (x=0; x < (long) columns; x++)
01164 destination_indexes[x]=indexes[x];
01165 }
01166 sync=SyncCacheViewAuthenticPixels(destination_view,exception);
01167 if (sync == MagickFalse)
01168 status=MagickFalse;
01169 }
01170 destination_view=DestroyCacheView(destination_view);
01171 source_view=DestroyCacheView(source_view);
01172 return(status);
01173 }
01174
01175 MagickExport Image *RollImage(const Image *image,const long x_offset,
01176 const long y_offset,ExceptionInfo *exception)
01177 {
01178 #define RollImageTag "Roll/Image"
01179
01180 Image
01181 *roll_image;
01182
01183 MagickStatusType
01184 status;
01185
01186 RectangleInfo
01187 offset;
01188
01189
01190
01191
01192 assert(image != (const Image *) NULL);
01193 assert(image->signature == MagickSignature);
01194 if (image->debug != MagickFalse)
01195 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
01196 assert(exception != (ExceptionInfo *) NULL);
01197 assert(exception->signature == MagickSignature);
01198 roll_image=CloneImage(image,image->columns,image->rows,MagickTrue,exception);
01199 if (roll_image == (Image *) NULL)
01200 return((Image *) NULL);
01201 offset.x=x_offset;
01202 offset.y=y_offset;
01203 while (offset.x < 0)
01204 offset.x+=image->columns;
01205 while (offset.x >= (long) image->columns)
01206 offset.x-=image->columns;
01207 while (offset.y < 0)
01208 offset.y+=image->rows;
01209 while (offset.y >= (long) image->rows)
01210 offset.y-=image->rows;
01211
01212
01213
01214 status=CopyImageRegion(roll_image,image,(unsigned long) offset.x,
01215 (unsigned long) offset.y,(long) image->columns-offset.x,(long) image->rows-
01216 offset.y,0,0,exception);
01217 (void) SetImageProgress(image,RollImageTag,0,3);
01218 status|=CopyImageRegion(roll_image,image,image->columns-offset.x,
01219 (unsigned long) offset.y,0,(long) image->rows-offset.y,offset.x,0,
01220 exception);
01221 (void) SetImageProgress(image,RollImageTag,1,3);
01222 status|=CopyImageRegion(roll_image,image,(unsigned long) offset.x,image->rows-
01223 offset.y,(long) image->columns-offset.x,0,0,offset.y,exception);
01224 (void) SetImageProgress(image,RollImageTag,2,3);
01225 status|=CopyImageRegion(roll_image,image,image->columns-offset.x,image->rows-
01226 offset.y,0,0,offset.x,offset.y,exception);
01227 (void) SetImageProgress(image,RollImageTag,3,3);
01228 roll_image->type=image->type;
01229 if (status == MagickFalse)
01230 roll_image=DestroyImage(roll_image);
01231 return(roll_image);
01232 }
01233
01234
01235
01236
01237
01238
01239
01240
01241
01242
01243
01244
01245
01246
01247
01248
01249
01250
01251
01252
01253
01254
01255
01256
01257
01258
01259
01260
01261
01262
01263
01264
01265
01266
01267
01268 MagickExport Image *ShaveImage(const Image *image,
01269 const RectangleInfo *shave_info,ExceptionInfo *exception)
01270 {
01271 Image
01272 *shave_image;
01273
01274 RectangleInfo
01275 geometry;
01276
01277 assert(image != (const Image *) NULL);
01278 assert(image->signature == MagickSignature);
01279 if (image->debug != MagickFalse)
01280 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
01281 if (((2*shave_info->width) >= image->columns) ||
01282 ((2*shave_info->height) >= image->rows))
01283 ThrowImageException(OptionWarning,"GeometryDoesNotContainImage");
01284 SetGeometry(image,&geometry);
01285 geometry.width-=2*shave_info->width;
01286 geometry.height-=2*shave_info->height;
01287 geometry.x=(long) shave_info->width+image->page.x;
01288 geometry.y=(long) shave_info->height+image->page.y;
01289 shave_image=CropImage(image,&geometry,exception);
01290 if (shave_image == (Image *) NULL)
01291 return((Image *) NULL);
01292 shave_image->page.width-=2*shave_info->width;
01293 shave_image->page.height-=2*shave_info->height;
01294 shave_image->page.x-=shave_info->width;
01295 shave_image->page.y-=shave_info->height;
01296 return(shave_image);
01297 }
01298
01299
01300
01301
01302
01303
01304
01305
01306
01307
01308
01309
01310
01311
01312
01313
01314
01315
01316
01317
01318
01319
01320
01321
01322
01323
01324
01325
01326
01327
01328 MagickExport Image *SpliceImage(const Image *image,
01329 const RectangleInfo *geometry,ExceptionInfo *exception)
01330 {
01331 #define SpliceImageTag "Splice/Image"
01332
01333 Image
01334 *splice_image;
01335
01336 long
01337 progress,
01338 y;
01339
01340 MagickBooleanType
01341 proceed,
01342 status;
01343
01344 RectangleInfo
01345 splice_geometry;
01346
01347 register long
01348 i;
01349
01350 ViewInfo
01351 *image_view,
01352 *splice_view;
01353
01354
01355
01356
01357 assert(image != (const Image *) NULL);
01358 assert(image->signature == MagickSignature);
01359 if (image->debug != MagickFalse)
01360 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
01361 assert(geometry != (const RectangleInfo *) NULL);
01362 assert(exception != (ExceptionInfo *) NULL);
01363 assert(exception->signature == MagickSignature);
01364 splice_geometry=(*geometry);
01365 splice_image=CloneImage(image,image->columns+splice_geometry.width,
01366 image->rows+splice_geometry.height,MagickTrue,exception);
01367 if (splice_image == (Image *) NULL)
01368 return((Image *) NULL);
01369 if (SetImageStorageClass(splice_image,DirectClass) == MagickFalse)
01370 {
01371 InheritException(exception,&splice_image->exception);
01372 splice_image=DestroyImage(splice_image);
01373 return((Image *) NULL);
01374 }
01375 (void) SetImageBackgroundColor(splice_image);
01376
01377
01378
01379 switch (image->gravity)
01380 {
01381 default:
01382 case UndefinedGravity:
01383 case NorthWestGravity:
01384 break;
01385 case NorthGravity:
01386 {
01387 splice_geometry.x+=splice_geometry.width/2;
01388 break;
01389 }
01390 case NorthEastGravity:
01391 {
01392 splice_geometry.x+=splice_geometry.width;
01393 break;
01394 }
01395 case WestGravity:
01396 {
01397 splice_geometry.y+=splice_geometry.width/2;
01398 break;
01399 }
01400 case StaticGravity:
01401 case CenterGravity:
01402 {
01403 splice_geometry.x+=splice_geometry.width/2;
01404 splice_geometry.y+=splice_geometry.height/2;
01405 break;
01406 }
01407 case EastGravity:
01408 {
01409 splice_geometry.x+=splice_geometry.width;
01410 splice_geometry.y+=splice_geometry.height/2;
01411 break;
01412 }
01413 case SouthWestGravity:
01414 {
01415 splice_geometry.y+=splice_geometry.height;
01416 break;
01417 }
01418 case SouthGravity:
01419 {
01420 splice_geometry.x+=splice_geometry.width/2;
01421 splice_geometry.y+=splice_geometry.height;
01422 break;
01423 }
01424 case SouthEastGravity:
01425 {
01426 splice_geometry.x+=splice_geometry.width;
01427 splice_geometry.y+=splice_geometry.height;
01428 break;
01429 }
01430 }
01431
01432
01433
01434 status=MagickTrue;
01435 i=0;
01436 progress=0;
01437 image_view=AcquireCacheView(image);
01438 splice_view=AcquireCacheView(splice_image);
01439 #if defined(MAGICKCORE_OPENMP_SUPPORT)
01440 #pragma omp parallel for schedule(dynamic,4) shared(progress,status)
01441 #endif
01442 for (y=0; y < (long) splice_geometry.y; y++)
01443 {
01444 register const PixelPacket
01445 *__restrict p;
01446
01447 register IndexPacket
01448 *__restrict indexes,
01449 *__restrict splice_indexes;
01450
01451 register long
01452 x;
01453
01454 register PixelPacket
01455 *__restrict q;
01456
01457 if (status == MagickFalse)
01458 continue;
01459 p=GetCacheViewVirtualPixels(image_view,0,y,image->columns,1,exception);
01460 q=QueueCacheViewAuthenticPixels(splice_view,0,y,splice_image->columns,1,
01461 exception);
01462 if ((p == (const PixelPacket *) NULL) || (q == (PixelPacket *) NULL))
01463 {
01464 status=MagickFalse;
01465 continue;
01466 }
01467 indexes=GetCacheViewAuthenticIndexQueue(image_view);
01468 splice_indexes=GetCacheViewAuthenticIndexQueue(splice_view);
01469 for (x=0; x < splice_geometry.x; x++)
01470 {
01471 q->red=p->red;
01472 q->green=p->green;
01473 q->blue=p->blue;
01474 q->opacity=OpaqueOpacity;
01475 if (image->matte != MagickFalse)
01476 q->opacity=p->opacity;
01477 if (image->colorspace == CMYKColorspace)
01478 splice_indexes[x]=(*indexes++);
01479 p++;
01480 q++;
01481 }
01482 for ( ; x < (long) (splice_geometry.x+splice_geometry.width); x++)
01483 q++;
01484 for ( ; x < (long) splice_image->columns; x++)
01485 {
01486 q->red=p->red;
01487 q->green=p->green;
01488 q->blue=p->blue;
01489 q->opacity=OpaqueOpacity;
01490 if (image->matte != MagickFalse)
01491 q->opacity=p->opacity;
01492 if (image->colorspace == CMYKColorspace)
01493 splice_indexes[x]=(*indexes++);
01494 p++;
01495 q++;
01496 }
01497 if (SyncCacheViewAuthenticPixels(splice_view,exception) == MagickFalse)
01498 status=MagickFalse;
01499 proceed=SetImageProgress(image,SpliceImageTag,y,splice_image->rows);
01500 if (image->progress_monitor != (MagickProgressMonitor) NULL)
01501 {
01502 MagickBooleanType
01503 proceed;
01504
01505 #if defined(MAGICKCORE_OPENMP_SUPPORT)
01506 #pragma omp critical (MagickCore_TransposeImage)
01507 #endif
01508 proceed=SetImageProgress(image,SpliceImageTag,progress++,
01509 splice_image->rows);
01510 if (proceed == MagickFalse)
01511 status=MagickFalse;
01512 }
01513 }
01514 #if defined(MAGICKCORE_OPENMP_SUPPORT)
01515 #pragma omp parallel for schedule(dynamic,4) shared(progress,status)
01516 #endif
01517 for (y=(long) (splice_geometry.y+splice_geometry.height);
01518 y < (long) splice_image->rows; y++)
01519 {
01520 register const PixelPacket
01521 *__restrict p;
01522
01523 register IndexPacket
01524 *__restrict indexes,
01525 *__restrict splice_indexes;
01526
01527 register long
01528 x;
01529
01530 register PixelPacket
01531 *__restrict q;
01532
01533 if (status == MagickFalse)
01534 continue;
01535 p=GetCacheViewVirtualPixels(image_view,0,y-splice_geometry.height,
01536 image->columns,1,exception);
01537 q=QueueCacheViewAuthenticPixels(splice_view,0,y,splice_image->columns,1,
01538 exception);
01539 if ((p == (const PixelPacket *) NULL) || (q == (PixelPacket *) NULL))
01540 {
01541 status=MagickFalse;
01542 continue;
01543 }
01544 indexes=GetCacheViewAuthenticIndexQueue(image_view);
01545 splice_indexes=GetCacheViewAuthenticIndexQueue(splice_view);
01546 for (x=0; x < splice_geometry.x; x++)
01547 {
01548 q->red=p->red;
01549 q->green=p->green;
01550 q->blue=p->blue;
01551 q->opacity=OpaqueOpacity;
01552 if (image->matte != MagickFalse)
01553 q->opacity=p->opacity;
01554 if (image->colorspace == CMYKColorspace)
01555 splice_indexes[x]=(*indexes++);
01556 p++;
01557 q++;
01558 }
01559 for ( ; x < (long) (splice_geometry.x+splice_geometry.width); x++)
01560 q++;
01561 for ( ; x < (long) splice_image->columns; x++)
01562 {
01563 q->red=p->red;
01564 q->green=p->green;
01565 q->blue=p->blue;
01566 q->opacity=OpaqueOpacity;
01567 if (image->matte != MagickFalse)
01568 q->opacity=p->opacity;
01569 if (image->colorspace == CMYKColorspace)
01570 splice_indexes[x]=(*indexes++);
01571 p++;
01572 q++;
01573 }
01574 if (SyncCacheViewAuthenticPixels(splice_view,exception) == MagickFalse)
01575 status=MagickFalse;
01576 if (image->progress_monitor != (MagickProgressMonitor) NULL)
01577 {
01578 MagickBooleanType
01579 proceed;
01580
01581 #if defined(MAGICKCORE_OPENMP_SUPPORT)
01582 #pragma omp critical (MagickCore_TransposeImage)
01583 #endif
01584 proceed=SetImageProgress(image,SpliceImageTag,progress++,
01585 splice_image->rows);
01586 if (proceed == MagickFalse)
01587 status=MagickFalse;
01588 }
01589 }
01590 splice_view=DestroyCacheView(splice_view);
01591 image_view=DestroyCacheView(image_view);
01592 if (status == MagickFalse)
01593 splice_image=DestroyImage(splice_image);
01594 return(splice_image);
01595 }
01596
01597
01598
01599
01600
01601
01602
01603
01604
01605
01606
01607
01608
01609
01610
01611
01612
01613
01614
01615
01616
01617
01618
01619
01620
01621
01622
01623
01624
01625
01626
01627
01628
01629 MagickExport MagickBooleanType TransformImage(Image **image,
01630 const char *crop_geometry,const char *image_geometry)
01631 {
01632 Image
01633 *resize_image,
01634 *transform_image;
01635
01636 MagickStatusType
01637 flags;
01638
01639 RectangleInfo
01640 geometry;
01641
01642 assert(image != (Image **) NULL);
01643 assert((*image)->signature == MagickSignature);
01644 if ((*image)->debug != MagickFalse)
01645 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",(*image)->filename);
01646 transform_image=(*image);
01647 if (crop_geometry != (const char *) NULL)
01648 {
01649 Image
01650 *crop_image;
01651
01652 RectangleInfo
01653 geometry;
01654
01655
01656
01657
01658 crop_image=NewImageList();
01659 flags=ParseGravityGeometry(transform_image,crop_geometry,&geometry,
01660 &(*image)->exception);
01661 if (((geometry.width == 0) && (geometry.height == 0)) ||
01662 ((flags & XValue) != 0) || ((flags & YValue) != 0))
01663 {
01664 crop_image=CropImage(transform_image,&geometry,&(*image)->exception);
01665 if ((crop_image != (Image *) NULL) && ((flags & AspectValue) != 0))
01666 {
01667 crop_image->page.width=geometry.width;
01668 crop_image->page.height=geometry.height;
01669 crop_image->page.x-=geometry.x;
01670 crop_image->page.y-=geometry.y;
01671 }
01672 }
01673 else
01674 if ((transform_image->columns > geometry.width) ||
01675 (transform_image->rows > geometry.height))
01676 {
01677 Image
01678 *next;
01679
01680 long
01681 y;
01682
01683 register long
01684 x;
01685
01686 unsigned long
01687 height,
01688 width;
01689
01690
01691
01692
01693 if (transform_image->page.width == 0)
01694 transform_image->page.width=transform_image->columns;
01695 if (transform_image->page.height == 0)
01696 transform_image->page.height=transform_image->rows;
01697 width=geometry.width;
01698 if (width == 0)
01699 width=transform_image->page.width;
01700 height=geometry.height;
01701 if (height == 0)
01702 height=transform_image->page.height;
01703 next=NewImageList();
01704 for (y=0; y < (long) transform_image->page.height; y+=height)
01705 {
01706 for (x=0; x < (long) transform_image->page.width; x+=width)
01707 {
01708 geometry.width=width;
01709 geometry.height=height;
01710 geometry.x=x;
01711 geometry.y=y;
01712 next=CropImage(transform_image,&geometry,&(*image)->exception);
01713 if (next == (Image *) NULL)
01714 break;
01715 AppendImageToList(&crop_image,next);
01716 }
01717 if (next == (Image *) NULL)
01718 break;
01719 }
01720 }
01721 if (crop_image == (Image *) NULL)
01722 transform_image=CloneImage(*image,0,0,MagickTrue,&(*image)->exception);
01723 else
01724 {
01725 transform_image=DestroyImage(transform_image);
01726 transform_image=GetFirstImageInList(crop_image);
01727 }
01728 *image=transform_image;
01729 }
01730 if (image_geometry == (const char *) NULL)
01731 return(MagickTrue);
01732
01733
01734
01735 flags=ParseRegionGeometry(transform_image,image_geometry,&geometry,
01736 &(*image)->exception);
01737 if ((transform_image->columns == geometry.width) &&
01738 (transform_image->rows == geometry.height))
01739 return(MagickTrue);
01740 resize_image=ZoomImage(transform_image,geometry.width,geometry.height,
01741 &(*image)->exception);
01742 if (resize_image == (Image *) NULL)
01743 return(MagickFalse);
01744 transform_image=DestroyImage(transform_image);
01745 transform_image=resize_image;
01746 *image=transform_image;
01747 return(MagickTrue);
01748 }
01749
01750
01751
01752
01753
01754
01755
01756
01757
01758
01759
01760
01761
01762
01763
01764
01765
01766
01767
01768
01769
01770
01771
01772
01773
01774
01775
01776
01777
01778 MagickExport MagickBooleanType TransformImages(Image **images,
01779 const char *crop_geometry,const char *image_geometry)
01780 {
01781 Image
01782 *image,
01783 **image_list,
01784 *transform_images;
01785
01786 MagickStatusType
01787 status;
01788
01789 register long
01790 i;
01791
01792 assert(images != (Image **) NULL);
01793 assert((*images)->signature == MagickSignature);
01794 if ((*images)->debug != MagickFalse)
01795 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",
01796 (*images)->filename);
01797 image_list=ImageListToArray(*images,&(*images)->exception);
01798 if (image_list == (Image **) NULL)
01799 return(MagickFalse);
01800 status=MagickTrue;
01801 transform_images=NewImageList();
01802 for (i=0; image_list[i] != (Image *) NULL; i++)
01803 {
01804 image=image_list[i];
01805 status|=TransformImage(&image,crop_geometry,image_geometry);
01806 AppendImageToList(&transform_images,image);
01807 }
01808 *images=transform_images;
01809 image_list=(Image **) RelinquishMagickMemory(image_list);
01810 return(status != 0 ? MagickTrue : MagickFalse);
01811 }
01812
01813
01814
01815
01816
01817
01818
01819
01820
01821
01822
01823
01824
01825
01826
01827
01828
01829
01830
01831
01832
01833
01834
01835
01836
01837
01838 MagickExport Image *TransposeImage(const Image *image,ExceptionInfo *exception)
01839 {
01840 #define TransposeImageTag "Transpose/Image"
01841
01842 Image
01843 *transpose_image;
01844
01845 long
01846 progress,
01847 y;
01848
01849 MagickBooleanType
01850 status;
01851
01852 RectangleInfo
01853 page;
01854
01855 ViewInfo
01856 *image_view,
01857 *transpose_view;
01858
01859 assert(image != (const Image *) NULL);
01860 assert(image->signature == MagickSignature);
01861 if (image->debug != MagickFalse)
01862 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
01863 assert(exception != (ExceptionInfo *) NULL);
01864 assert(exception->signature == MagickSignature);
01865 transpose_image=CloneImage(image,image->rows,image->columns,MagickTrue,
01866 exception);
01867 if (transpose_image == (Image *) NULL)
01868 return((Image *) NULL);
01869
01870
01871
01872 status=MagickTrue;
01873 progress=0;
01874 image_view=AcquireCacheView(image);
01875 transpose_view=AcquireCacheView(transpose_image);
01876 #if defined(MAGICKCORE_OPENMP_SUPPORT)
01877 #pragma omp parallel for schedule(dynamic,4) shared(progress,status)
01878 #endif
01879 for (y=0; y < (long) image->rows; y++)
01880 {
01881 register const PixelPacket
01882 *__restrict p;
01883
01884 register IndexPacket
01885 *__restrict transpose_indexes,
01886 *__restrict indexes;
01887
01888 register PixelPacket
01889 *__restrict q;
01890
01891 if (status == MagickFalse)
01892 continue;
01893 p=GetCacheViewVirtualPixels(image_view,0,(long) image->rows-y-1,
01894 image->columns,1,exception);
01895 q=QueueCacheViewAuthenticPixels(transpose_view,(long) (image->rows-y-1),0,
01896 1,transpose_image->rows,exception);
01897 if ((p == (const PixelPacket *) NULL) || (q == (PixelPacket *) NULL))
01898 {
01899 status=MagickFalse;
01900 continue;
01901 }
01902 (void) CopyMagickMemory(q,p,(size_t) image->columns*sizeof(*q));
01903 indexes=GetCacheViewAuthenticIndexQueue(image_view);
01904 if (indexes != (IndexPacket *) NULL)
01905 {
01906 transpose_indexes=GetCacheViewAuthenticIndexQueue(transpose_view);
01907 if (transpose_indexes != (IndexPacket *) NULL)
01908 (void) CopyMagickMemory(transpose_indexes,indexes,(size_t)
01909 image->columns*sizeof(*transpose_indexes));
01910 }
01911 if (SyncCacheViewAuthenticPixels(transpose_view,exception) == MagickFalse)
01912 status=MagickFalse;
01913 if (image->progress_monitor != (MagickProgressMonitor) NULL)
01914 {
01915 MagickBooleanType
01916 proceed;
01917
01918 #if defined(MAGICKCORE_OPENMP_SUPPORT)
01919 #pragma omp critical (MagickCore_TransposeImage)
01920 #endif
01921 proceed=SetImageProgress(image,TransposeImageTag,progress++,
01922 image->rows);
01923 if (proceed == MagickFalse)
01924 status=MagickFalse;
01925 }
01926 }
01927 transpose_view=DestroyCacheView(transpose_view);
01928 image_view=DestroyCacheView(image_view);
01929 transpose_image->type=image->type;
01930 page=transpose_image->page;
01931 Swap(page.width,page.height);
01932 Swap(page.x,page.y);
01933 if (page.width != 0)
01934 page.x=(long) (page.width-transpose_image->columns-page.x);
01935 transpose_image->page=page;
01936 if (status == MagickFalse)
01937 transpose_image=DestroyImage(transpose_image);
01938 return(transpose_image);
01939 }
01940
01941
01942
01943
01944
01945
01946
01947
01948
01949
01950
01951
01952
01953
01954
01955
01956
01957
01958
01959
01960
01961
01962
01963
01964
01965
01966 MagickExport Image *TransverseImage(const Image *image,ExceptionInfo *exception)
01967 {
01968 #define TransverseImageTag "Transverse/Image"
01969
01970 Image
01971 *transverse_image;
01972
01973 long
01974 progress,
01975 y;
01976
01977 MagickBooleanType
01978 status;
01979
01980 RectangleInfo
01981 page;
01982
01983 ViewInfo
01984 *image_view,
01985 *transverse_view;
01986
01987 assert(image != (const Image *) NULL);
01988 assert(image->signature == MagickSignature);
01989 if (image->debug != MagickFalse)
01990 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
01991 assert(exception != (ExceptionInfo *) NULL);
01992 assert(exception->signature == MagickSignature);
01993 transverse_image=CloneImage(image,image->rows,image->columns,MagickTrue,
01994 exception);
01995 if (transverse_image == (Image *) NULL)
01996 return((Image *) NULL);
01997
01998
01999
02000 status=MagickTrue;
02001 progress=0;
02002 image_view=AcquireCacheView(image);
02003 transverse_view=AcquireCacheView(transverse_image);
02004 #if defined(MAGICKCORE_OPENMP_SUPPORT)
02005 #pragma omp parallel for schedule(dynamic,4) shared(progress,status)
02006 #endif
02007 for (y=0; y < (long) image->rows; y++)
02008 {
02009 MagickBooleanType
02010 sync;
02011
02012 register const PixelPacket
02013 *__restrict p;
02014
02015 register IndexPacket
02016 *__restrict transverse_indexes,
02017 *__restrict indexes;
02018
02019 register long
02020 x;
02021
02022 register PixelPacket
02023 *__restrict q;
02024
02025 if (status == MagickFalse)
02026 continue;
02027 p=GetCacheViewVirtualPixels(image_view,0,y,image->columns,1,exception);
02028 q=QueueCacheViewAuthenticPixels(transverse_view,(long) (image->rows-y-
02029 1),0,1,transverse_image->rows,exception);
02030 if ((p == (const PixelPacket *) NULL) || (q == (PixelPacket *) NULL))
02031 {
02032 status=MagickFalse;
02033 continue;
02034 }
02035 q+=image->columns;
02036 for (x=0; x < (long) image->columns; x++)
02037 *--q=(*p++);
02038 indexes=GetCacheViewAuthenticIndexQueue(image_view);
02039 if (indexes != (IndexPacket *) NULL)
02040 {
02041 transverse_indexes=GetCacheViewAuthenticIndexQueue(transverse_view);
02042 if (transverse_indexes != (IndexPacket *) NULL)
02043 for (x=0; x < (long) image->columns; x++)
02044 transverse_indexes[image->columns-x-1]=indexes[x];
02045 }
02046 sync=SyncCacheViewAuthenticPixels(transverse_view,exception);
02047 if (sync == MagickFalse)
02048 status=MagickFalse;
02049 if (image->progress_monitor != (MagickProgressMonitor) NULL)
02050 {
02051 MagickBooleanType
02052 proceed;
02053
02054 #if defined(MAGICKCORE_OPENMP_SUPPORT)
02055 #pragma omp critical (MagickCore_TransverseImage)
02056 #endif
02057 proceed=SetImageProgress(image,TransverseImageTag,progress++,
02058 image->rows);
02059 if (proceed == MagickFalse)
02060 status=MagickFalse;
02061 }
02062 }
02063 transverse_view=DestroyCacheView(transverse_view);
02064 image_view=DestroyCacheView(image_view);
02065 transverse_image->type=image->type;
02066 page=transverse_image->page;
02067 Swap(page.width,page.height);
02068 Swap(page.x,page.y);
02069 if (page.height != 0)
02070 page.y=(long) (page.height-transverse_image->rows-page.y);
02071 transverse_image->page=page;
02072 if (status == MagickFalse)
02073 transverse_image=DestroyImage(transverse_image);
02074 return(transverse_image);
02075 }
02076
02077
02078
02079
02080
02081
02082
02083
02084
02085
02086
02087
02088
02089
02090
02091
02092
02093
02094
02095
02096
02097
02098
02099
02100
02101
02102
02103 MagickExport Image *TrimImage(const Image *image,ExceptionInfo *exception)
02104 {
02105 RectangleInfo
02106 geometry;
02107
02108 assert(image != (const Image *) NULL);
02109 assert(image->signature == MagickSignature);
02110 if (image->debug != MagickFalse)
02111 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
02112 geometry=GetImageBoundingBox(image,exception);
02113 if ((geometry.width == 0) || (geometry.height == 0))
02114 {
02115 Image
02116 *crop_image;
02117
02118 crop_image=CloneImage(image,1,1,MagickTrue,exception);
02119 if (crop_image == (Image *) NULL)
02120 return((Image *) NULL);
02121 crop_image->background_color.opacity=(Quantum) TransparentOpacity;
02122 (void) SetImageBackgroundColor(crop_image);
02123 crop_image->page=image->page;
02124 crop_image->page.x=(-1);
02125 crop_image->page.y=(-1);
02126 return(crop_image);
02127 }
02128 geometry.x+=image->page.x;
02129 geometry.y+=image->page.y;
02130 return(CropImage(image,&geometry,exception));
02131 }