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