|
MagickCore
6.7.5
|
00001 /* 00002 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 00003 % % 00004 % % 00005 % % 00006 % IIIII M M AAA GGGG EEEEE % 00007 % I MM MM A A G E % 00008 % I M M M AAAAA G GG EEE % 00009 % I M M A A G G E % 00010 % IIIII M M A A GGGG EEEEE % 00011 % % 00012 % % 00013 % MagickCore Image Methods % 00014 % % 00015 % Software Design % 00016 % John Cristy % 00017 % July 1992 % 00018 % % 00019 % % 00020 % Copyright 1999-2012 ImageMagick Studio LLC, a non-profit organization % 00021 % dedicated to making software imaging solutions freely available. % 00022 % % 00023 % You may not use this file except in compliance with the License. You may % 00024 % obtain a copy of the License at % 00025 % % 00026 % http://www.imagemagick.org/script/license.php % 00027 % % 00028 % Unless required by applicable law or agreed to in writing, software % 00029 % distributed under the License is distributed on an "AS IS" BASIS, % 00030 % WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. % 00031 % See the License for the specific language governing permissions and % 00032 % limitations under the License. % 00033 % % 00034 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 00035 % 00036 % 00037 % 00038 */ 00039 00040 /* 00041 Include declarations. 00042 */ 00043 #include "MagickCore/studio.h" 00044 #include "MagickCore/animate.h" 00045 #include "MagickCore/artifact.h" 00046 #include "MagickCore/attribute.h" 00047 #include "MagickCore/blob.h" 00048 #include "MagickCore/blob-private.h" 00049 #include "MagickCore/cache.h" 00050 #include "MagickCore/cache-private.h" 00051 #include "MagickCore/cache-view.h" 00052 #include "MagickCore/client.h" 00053 #include "MagickCore/color.h" 00054 #include "MagickCore/color-private.h" 00055 #include "MagickCore/colormap.h" 00056 #include "MagickCore/colorspace.h" 00057 #include "MagickCore/colorspace-private.h" 00058 #include "MagickCore/composite.h" 00059 #include "MagickCore/composite-private.h" 00060 #include "MagickCore/compress.h" 00061 #include "MagickCore/constitute.h" 00062 #include "MagickCore/display.h" 00063 #include "MagickCore/draw.h" 00064 #include "MagickCore/enhance.h" 00065 #include "MagickCore/exception.h" 00066 #include "MagickCore/exception-private.h" 00067 #include "MagickCore/gem.h" 00068 #include "MagickCore/geometry.h" 00069 #include "MagickCore/histogram.h" 00070 #include "MagickCore/image-private.h" 00071 #include "MagickCore/list.h" 00072 #include "MagickCore/magic.h" 00073 #include "MagickCore/magick.h" 00074 #include "MagickCore/magick-private.h" 00075 #include "MagickCore/memory_.h" 00076 #include "MagickCore/module.h" 00077 #include "MagickCore/monitor.h" 00078 #include "MagickCore/monitor-private.h" 00079 #include "MagickCore/option.h" 00080 #include "MagickCore/paint.h" 00081 #include "MagickCore/pixel-accessor.h" 00082 #include "MagickCore/profile.h" 00083 #include "MagickCore/property.h" 00084 #include "MagickCore/quantize.h" 00085 #include "MagickCore/random_.h" 00086 #include "MagickCore/segment.h" 00087 #include "MagickCore/semaphore.h" 00088 #include "MagickCore/signature-private.h" 00089 #include "MagickCore/statistic.h" 00090 #include "MagickCore/string_.h" 00091 #include "MagickCore/string-private.h" 00092 #include "MagickCore/thread-private.h" 00093 #include "MagickCore/threshold.h" 00094 #include "MagickCore/timer.h" 00095 #include "MagickCore/utility.h" 00096 #include "MagickCore/utility-private.h" 00097 #include "MagickCore/version.h" 00098 #include "MagickCore/xwindow-private.h" 00099 00100 /* 00101 Constant declaration. 00102 */ 00103 const char 00104 BackgroundColor[] = "#ffffff", /* white */ 00105 BorderColor[] = "#dfdfdf", /* gray */ 00106 DefaultTileFrame[] = "15x15+3+3", 00107 DefaultTileGeometry[] = "120x120+4+3>", 00108 DefaultTileLabel[] = "%f\n%G\n%b", 00109 ForegroundColor[] = "#000", /* black */ 00110 LoadImageTag[] = "Load/Image", 00111 LoadImagesTag[] = "Load/Images", 00112 MatteColor[] = "#bdbdbd", /* gray */ 00113 PSDensityGeometry[] = "72.0x72.0", 00114 PSPageGeometry[] = "612x792", 00115 SaveImageTag[] = "Save/Image", 00116 SaveImagesTag[] = "Save/Images", 00117 TransparentColor[] = "#00000000"; /* transparent black */ 00118 00119 const double 00120 DefaultResolution = 72.0; 00121 00122 /* 00123 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 00124 % % 00125 % % 00126 % % 00127 % A c q u i r e I m a g e % 00128 % % 00129 % % 00130 % % 00131 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 00132 % 00133 % AcquireImage() returns a pointer to an image structure initialized to 00134 % default values. 00135 % 00136 % The format of the AcquireImage method is: 00137 % 00138 % Image *AcquireImage(const ImageInfo *image_info,ExceptionInfo *exception) 00139 % 00140 % A description of each parameter follows: 00141 % 00142 % o image_info: Many of the image default values are set from this 00143 % structure. For example, filename, compression, depth, background color, 00144 % and others. 00145 % 00146 % o exception: return any errors or warnings in this structure. 00147 % 00148 */ 00149 MagickExport Image *AcquireImage(const ImageInfo *image_info, 00150 ExceptionInfo *exception) 00151 { 00152 const char 00153 *option; 00154 00155 Image 00156 *image; 00157 00158 MagickStatusType 00159 flags; 00160 00161 /* 00162 Allocate image structure. 00163 */ 00164 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"..."); 00165 image=(Image *) AcquireMagickMemory(sizeof(*image)); 00166 if (image == (Image *) NULL) 00167 ThrowFatalException(ResourceLimitFatalError,"MemoryAllocationFailed"); 00168 (void) ResetMagickMemory(image,0,sizeof(*image)); 00169 /* 00170 Initialize Image structure. 00171 */ 00172 (void) CopyMagickString(image->magick,"MIFF",MaxTextExtent); 00173 image->storage_class=DirectClass; 00174 image->depth=MAGICKCORE_QUANTUM_DEPTH; 00175 image->colorspace=RGBColorspace; 00176 image->interlace=NoInterlace; 00177 image->ticks_per_second=UndefinedTicksPerSecond; 00178 image->compose=OverCompositeOp; 00179 image->blur=1.0; 00180 (void) QueryColorCompliance(BackgroundColor,AllCompliance, 00181 &image->background_color,exception); 00182 (void) QueryColorCompliance(BorderColor,AllCompliance,&image->border_color, 00183 exception); 00184 (void) QueryColorCompliance(MatteColor,AllCompliance,&image->matte_color, 00185 exception); 00186 (void) QueryColorCompliance(TransparentColor,AllCompliance, 00187 &image->transparent_color,exception); 00188 image->resolution.x=DefaultResolution; 00189 image->resolution.y=DefaultResolution; 00190 image->units=PixelsPerInchResolution; 00191 GetTimerInfo(&image->timer); 00192 image->cache=AcquirePixelCache(0); 00193 image->channel_mask=DefaultChannels; 00194 image->channel_map=AcquirePixelChannelMap(); 00195 image->blob=CloneBlobInfo((BlobInfo *) NULL); 00196 image->debug=IsEventLogging(); 00197 image->reference_count=1; 00198 image->semaphore=AllocateSemaphoreInfo(); 00199 image->signature=MagickSignature; 00200 if (image_info == (ImageInfo *) NULL) 00201 return(image); 00202 /* 00203 Transfer image info. 00204 */ 00205 SetBlobExempt(image,image_info->file != (FILE *) NULL ? MagickTrue : 00206 MagickFalse); 00207 (void) CopyMagickString(image->filename,image_info->filename,MaxTextExtent); 00208 (void) CopyMagickString(image->magick_filename,image_info->filename, 00209 MaxTextExtent); 00210 (void) CopyMagickString(image->magick,image_info->magick,MaxTextExtent); 00211 if (image_info->size != (char *) NULL) 00212 { 00213 (void) ParseAbsoluteGeometry(image_info->size,&image->extract_info); 00214 image->columns=image->extract_info.width; 00215 image->rows=image->extract_info.height; 00216 image->offset=image->extract_info.x; 00217 image->extract_info.x=0; 00218 image->extract_info.y=0; 00219 } 00220 if (image_info->extract != (char *) NULL) 00221 { 00222 RectangleInfo 00223 geometry; 00224 00225 flags=ParseAbsoluteGeometry(image_info->extract,&geometry); 00226 if (((flags & XValue) != 0) || ((flags & YValue) != 0)) 00227 { 00228 image->extract_info=geometry; 00229 Swap(image->columns,image->extract_info.width); 00230 Swap(image->rows,image->extract_info.height); 00231 } 00232 } 00233 image->compression=image_info->compression; 00234 image->quality=image_info->quality; 00235 image->endian=image_info->endian; 00236 image->interlace=image_info->interlace; 00237 image->units=image_info->units; 00238 if (image_info->density != (char *) NULL) 00239 { 00240 GeometryInfo 00241 geometry_info; 00242 00243 flags=ParseGeometry(image_info->density,&geometry_info); 00244 image->resolution.x=geometry_info.rho; 00245 image->resolution.y=geometry_info.sigma; 00246 if ((flags & SigmaValue) == 0) 00247 image->resolution.y=image->resolution.x; 00248 } 00249 if (image_info->page != (char *) NULL) 00250 { 00251 char 00252 *geometry; 00253 00254 image->page=image->extract_info; 00255 geometry=GetPageGeometry(image_info->page); 00256 (void) ParseAbsoluteGeometry(geometry,&image->page); 00257 geometry=DestroyString(geometry); 00258 } 00259 if (image_info->depth != 0) 00260 image->depth=image_info->depth; 00261 image->dither=image_info->dither; 00262 image->background_color=image_info->background_color; 00263 image->border_color=image_info->border_color; 00264 image->matte_color=image_info->matte_color; 00265 image->transparent_color=image_info->transparent_color; 00266 image->ping=image_info->ping; 00267 image->progress_monitor=image_info->progress_monitor; 00268 image->client_data=image_info->client_data; 00269 if (image_info->cache != (void *) NULL) 00270 ClonePixelCacheMethods(image->cache,image_info->cache); 00271 (void) SyncImageSettings(image_info,image,exception); 00272 option=GetImageOption(image_info,"delay"); 00273 if (option != (const char *) NULL) 00274 { 00275 GeometryInfo 00276 geometry_info; 00277 00278 flags=ParseGeometry(option,&geometry_info); 00279 if ((flags & GreaterValue) != 0) 00280 { 00281 if (image->delay > (size_t) floor(geometry_info.rho+0.5)) 00282 image->delay=(size_t) floor(geometry_info.rho+0.5); 00283 } 00284 else 00285 if ((flags & LessValue) != 0) 00286 { 00287 if (image->delay < (size_t) floor(geometry_info.rho+0.5)) 00288 image->ticks_per_second=(ssize_t) floor(geometry_info.sigma+0.5); 00289 } 00290 else 00291 image->delay=(size_t) floor(geometry_info.rho+0.5); 00292 if ((flags & SigmaValue) != 0) 00293 image->ticks_per_second=(ssize_t) floor(geometry_info.sigma+0.5); 00294 } 00295 option=GetImageOption(image_info,"dispose"); 00296 if (option != (const char *) NULL) 00297 image->dispose=(DisposeType) ParseCommandOption(MagickDisposeOptions, 00298 MagickFalse,option); 00299 return(image); 00300 } 00301 00302 /* 00303 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 00304 % % 00305 % % 00306 % % 00307 % A c q u i r e I m a g e I n f o % 00308 % % 00309 % % 00310 % % 00311 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 00312 % 00313 % AcquireImageInfo() allocates the ImageInfo structure. 00314 % 00315 % The format of the AcquireImageInfo method is: 00316 % 00317 % ImageInfo *AcquireImageInfo(void) 00318 % 00319 */ 00320 MagickExport ImageInfo *AcquireImageInfo(void) 00321 { 00322 ImageInfo 00323 *image_info; 00324 00325 image_info=(ImageInfo *) AcquireMagickMemory(sizeof(*image_info)); 00326 if (image_info == (ImageInfo *) NULL) 00327 ThrowFatalException(ResourceLimitFatalError,"MemoryAllocationFailed"); 00328 GetImageInfo(image_info); 00329 return(image_info); 00330 } 00331 00332 /* 00333 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 00334 % % 00335 % % 00336 % % 00337 % A c q u i r e N e x t I m a g e % 00338 % % 00339 % % 00340 % % 00341 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 00342 % 00343 % AcquireNextImage() initializes the next image in a sequence to 00344 % default values. The next member of image points to the newly allocated 00345 % image. If there is a memory shortage, next is assigned NULL. 00346 % 00347 % The format of the AcquireNextImage method is: 00348 % 00349 % void AcquireNextImage(const ImageInfo *image_info,Image *image, 00350 % ExceptionInfo *exception) 00351 % 00352 % A description of each parameter follows: 00353 % 00354 % o image_info: Many of the image default values are set from this 00355 % structure. For example, filename, compression, depth, background color, 00356 % and others. 00357 % 00358 % o image: the image. 00359 % 00360 % o exception: return any errors or warnings in this structure. 00361 % 00362 */ 00363 MagickExport void AcquireNextImage(const ImageInfo *image_info,Image *image, 00364 ExceptionInfo *exception) 00365 { 00366 /* 00367 Allocate image structure. 00368 */ 00369 assert(image != (Image *) NULL); 00370 assert(image->signature == MagickSignature); 00371 if (image->debug != MagickFalse) 00372 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename); 00373 image->next=AcquireImage(image_info,exception); 00374 if (GetNextImageInList(image) == (Image *) NULL) 00375 return; 00376 (void) CopyMagickString(GetNextImageInList(image)->filename,image->filename, 00377 MaxTextExtent); 00378 if (image_info != (ImageInfo *) NULL) 00379 (void) CopyMagickString(GetNextImageInList(image)->filename, 00380 image_info->filename,MaxTextExtent); 00381 DestroyBlob(GetNextImageInList(image)); 00382 image->next->blob=ReferenceBlob(image->blob); 00383 image->next->endian=image->endian; 00384 image->next->scene=image->scene+1; 00385 image->next->previous=image; 00386 } 00387 00388 /* 00389 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 00390 % % 00391 % % 00392 % % 00393 % A p p e n d I m a g e s % 00394 % % 00395 % % 00396 % % 00397 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 00398 % 00399 % AppendImages() takes all images from the current image pointer to the end 00400 % of the image list and appends them to each other top-to-bottom if the 00401 % stack parameter is true, otherwise left-to-right. 00402 % 00403 % The current gravity setting now effects how the image is justified in the 00404 % final image. 00405 % 00406 % The format of the AppendImages method is: 00407 % 00408 % Image *AppendImages(const Image *images,const MagickBooleanType stack, 00409 % ExceptionInfo *exception) 00410 % 00411 % A description of each parameter follows: 00412 % 00413 % o images: the image sequence. 00414 % 00415 % o stack: A value other than 0 stacks the images top-to-bottom. 00416 % 00417 % o exception: return any errors or warnings in this structure. 00418 % 00419 */ 00420 MagickExport Image *AppendImages(const Image *images, 00421 const MagickBooleanType stack,ExceptionInfo *exception) 00422 { 00423 #define AppendImageTag "Append/Image" 00424 00425 CacheView 00426 *append_view, 00427 *image_view; 00428 00429 const Image 00430 *image; 00431 00432 Image 00433 *append_image; 00434 00435 MagickBooleanType 00436 matte, 00437 proceed, 00438 status; 00439 00440 MagickOffsetType 00441 n; 00442 00443 RectangleInfo 00444 geometry; 00445 00446 register const Image 00447 *next; 00448 00449 size_t 00450 height, 00451 number_images, 00452 width; 00453 00454 ssize_t 00455 x_offset, 00456 y, 00457 y_offset; 00458 00459 /* 00460 Compute maximum area of appended area. 00461 */ 00462 assert(images != (Image *) NULL); 00463 assert(images->signature == MagickSignature); 00464 if (images->debug != MagickFalse) 00465 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",images->filename); 00466 assert(exception != (ExceptionInfo *) NULL); 00467 assert(exception->signature == MagickSignature); 00468 image=images; 00469 matte=image->matte; 00470 number_images=1; 00471 width=image->columns; 00472 height=image->rows; 00473 next=GetNextImageInList(image); 00474 for ( ; next != (Image *) NULL; next=GetNextImageInList(next)) 00475 { 00476 if (next->matte != MagickFalse) 00477 matte=MagickTrue; 00478 number_images++; 00479 if (stack != MagickFalse) 00480 { 00481 if (next->columns > width) 00482 width=next->columns; 00483 height+=next->rows; 00484 continue; 00485 } 00486 width+=next->columns; 00487 if (next->rows > height) 00488 height=next->rows; 00489 } 00490 /* 00491 Append images. 00492 */ 00493 append_image=CloneImage(image,width,height,MagickTrue,exception); 00494 if (append_image == (Image *) NULL) 00495 return((Image *) NULL); 00496 if (SetImageStorageClass(append_image,DirectClass,exception) == MagickFalse) 00497 { 00498 append_image=DestroyImage(append_image); 00499 return((Image *) NULL); 00500 } 00501 append_image->matte=matte; 00502 (void) SetImageBackgroundColor(append_image,exception); 00503 status=MagickTrue; 00504 x_offset=0; 00505 y_offset=0; 00506 append_view=AcquireCacheView(append_image); 00507 for (n=0; n < (MagickOffsetType) number_images; n++) 00508 { 00509 SetGeometry(append_image,&geometry); 00510 GravityAdjustGeometry(image->columns,image->rows,image->gravity,&geometry); 00511 if (stack != MagickFalse) 00512 x_offset-=geometry.x; 00513 else 00514 y_offset-=geometry.y; 00515 image_view=AcquireCacheView(image); 00516 #if defined(MAGICKCORE_OPENMP_SUPPORT) 00517 #pragma omp parallel for schedule(static) shared(status) 00518 #endif 00519 for (y=0; y < (ssize_t) image->rows; y++) 00520 { 00521 MagickBooleanType 00522 sync; 00523 00524 register const Quantum 00525 *restrict p; 00526 00527 register Quantum 00528 *restrict q; 00529 00530 register ssize_t 00531 x; 00532 00533 if (status == MagickFalse) 00534 continue; 00535 p=GetCacheViewVirtualPixels(image_view,0,y,image->columns,1,exception); 00536 q=QueueCacheViewAuthenticPixels(append_view,x_offset,y+y_offset, 00537 image->columns,1,exception); 00538 if ((p == (const Quantum *) NULL) || (q == (Quantum *) NULL)) 00539 { 00540 status=MagickFalse; 00541 continue; 00542 } 00543 for (x=0; x < (ssize_t) image->columns; x++) 00544 { 00545 register ssize_t 00546 i; 00547 00548 if (GetPixelMask(image,p) != 0) 00549 { 00550 p+=GetPixelChannels(image); 00551 q+=GetPixelChannels(append_image); 00552 continue; 00553 } 00554 for (i=0; i < (ssize_t) GetPixelChannels(image); i++) 00555 { 00556 PixelChannel 00557 channel; 00558 00559 PixelTrait 00560 append_traits, 00561 traits; 00562 00563 channel=GetPixelChannelMapChannel(image,i); 00564 traits=GetPixelChannelMapTraits(image,channel); 00565 append_traits=GetPixelChannelMapTraits(append_image,channel); 00566 if ((traits == UndefinedPixelTrait) || 00567 (append_traits == UndefinedPixelTrait)) 00568 continue; 00569 SetPixelChannel(append_image,channel,p[i],q); 00570 } 00571 p+=GetPixelChannels(image); 00572 q+=GetPixelChannels(append_image); 00573 } 00574 sync=SyncCacheViewAuthenticPixels(append_view,exception); 00575 if (sync == MagickFalse) 00576 status=MagickFalse; 00577 } 00578 image_view=DestroyCacheView(image_view); 00579 proceed=SetImageProgress(image,AppendImageTag,n,number_images); 00580 if (proceed == MagickFalse) 00581 break; 00582 if (stack == MagickFalse) 00583 { 00584 x_offset+=(ssize_t) image->columns; 00585 y_offset=0; 00586 } 00587 else 00588 { 00589 x_offset=0; 00590 y_offset+=(ssize_t) image->rows; 00591 } 00592 image=GetNextImageInList(image); 00593 } 00594 append_view=DestroyCacheView(append_view); 00595 if (status == MagickFalse) 00596 append_image=DestroyImage(append_image); 00597 return(append_image); 00598 } 00599 00600 /* 00601 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 00602 % % 00603 % % 00604 % % 00605 % C a t c h I m a g e E x c e p t i o n % 00606 % % 00607 % % 00608 % % 00609 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 00610 % 00611 % CatchImageException() returns if no exceptions are found in the image 00612 % sequence, otherwise it determines the most severe exception and reports 00613 % it as a warning or error depending on the severity. 00614 % 00615 % The format of the CatchImageException method is: 00616 % 00617 % ExceptionType CatchImageException(Image *image) 00618 % 00619 % A description of each parameter follows: 00620 % 00621 % o image: An image sequence. 00622 % 00623 */ 00624 MagickExport ExceptionType CatchImageException(Image *image) 00625 { 00626 ExceptionInfo 00627 *exception; 00628 00629 ExceptionType 00630 severity; 00631 00632 assert(image != (const Image *) NULL); 00633 assert(image->signature == MagickSignature); 00634 if (image->debug != MagickFalse) 00635 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename); 00636 exception=AcquireExceptionInfo(); 00637 CatchException(exception); 00638 severity=exception->severity; 00639 exception=DestroyExceptionInfo(exception); 00640 return(severity); 00641 } 00642 00643 /* 00644 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 00645 % % 00646 % % 00647 % % 00648 % C l i p I m a g e P a t h % 00649 % % 00650 % % 00651 % % 00652 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 00653 % 00654 % ClipImagePath() sets the image clip mask based any clipping path information 00655 % if it exists. 00656 % 00657 % The format of the ClipImagePath method is: 00658 % 00659 % MagickBooleanType ClipImagePath(Image *image,const char *pathname, 00660 % const MagickBooleanType inside,ExceptionInfo *exception) 00661 % 00662 % A description of each parameter follows: 00663 % 00664 % o image: the image. 00665 % 00666 % o pathname: name of clipping path resource. If name is preceded by #, use 00667 % clipping path numbered by name. 00668 % 00669 % o inside: if non-zero, later operations take effect inside clipping path. 00670 % Otherwise later operations take effect outside clipping path. 00671 % 00672 % o exception: return any errors or warnings in this structure. 00673 % 00674 */ 00675 00676 MagickExport MagickBooleanType ClipImage(Image *image,ExceptionInfo *exception) 00677 { 00678 return(ClipImagePath(image,"#1",MagickTrue,exception)); 00679 } 00680 00681 MagickExport MagickBooleanType ClipImagePath(Image *image,const char *pathname, 00682 const MagickBooleanType inside,ExceptionInfo *exception) 00683 { 00684 #define ClipImagePathTag "ClipPath/Image" 00685 00686 char 00687 *property; 00688 00689 const char 00690 *value; 00691 00692 Image 00693 *clip_mask; 00694 00695 ImageInfo 00696 *image_info; 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(pathname != NULL); 00703 property=AcquireString(pathname); 00704 (void) FormatLocaleString(property,MaxTextExtent,"8BIM:1999,2998:%s", 00705 pathname); 00706 value=GetImageProperty(image,property,exception); 00707 property=DestroyString(property); 00708 if (value == (const char *) NULL) 00709 { 00710 ThrowFileException(exception,OptionError,"NoClipPathDefined", 00711 image->filename); 00712 return(MagickFalse); 00713 } 00714 image_info=AcquireImageInfo(); 00715 (void) CopyMagickString(image_info->filename,image->filename,MaxTextExtent); 00716 (void) ConcatenateMagickString(image_info->filename,pathname,MaxTextExtent); 00717 clip_mask=BlobToImage(image_info,value,strlen(value),exception); 00718 image_info=DestroyImageInfo(image_info); 00719 if (clip_mask == (Image *) NULL) 00720 return(MagickFalse); 00721 if (clip_mask->storage_class == PseudoClass) 00722 { 00723 (void) SyncImage(clip_mask,exception); 00724 if (SetImageStorageClass(clip_mask,DirectClass,exception) == MagickFalse) 00725 return(MagickFalse); 00726 } 00727 if (inside == MagickFalse) 00728 (void) NegateImage(clip_mask,MagickFalse,exception); 00729 (void) FormatLocaleString(clip_mask->magick_filename,MaxTextExtent, 00730 "8BIM:1999,2998:%s\nPS",pathname); 00731 (void) SetImageMask(image,clip_mask,exception); 00732 clip_mask=DestroyImage(clip_mask); 00733 return(MagickTrue); 00734 } 00735 00736 /* 00737 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 00738 % % 00739 % % 00740 % % 00741 % C l o n e I m a g e % 00742 % % 00743 % % 00744 % % 00745 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 00746 % 00747 % CloneImage() copies an image and returns the copy as a new image object. 00748 % 00749 % If the specified columns and rows is 0, an exact copy of the image is 00750 % returned, otherwise the pixel data is undefined and must be initialized 00751 % with the QueueAuthenticPixels() and SyncAuthenticPixels() methods. On 00752 % failure, a NULL image is returned and exception describes the reason for the 00753 % failure. 00754 % 00755 % The format of the CloneImage method is: 00756 % 00757 % Image *CloneImage(const Image *image,const size_t columns, 00758 % const size_t rows,const MagickBooleanType orphan, 00759 % ExceptionInfo *exception) 00760 % 00761 % A description of each parameter follows: 00762 % 00763 % o image: the image. 00764 % 00765 % o columns: the number of columns in the cloned image. 00766 % 00767 % o rows: the number of rows in the cloned image. 00768 % 00769 % o detach: With a value other than 0, the cloned image is detached from 00770 % its parent I/O stream. 00771 % 00772 % o exception: return any errors or warnings in this structure. 00773 % 00774 */ 00775 MagickExport Image *CloneImage(const Image *image,const size_t columns, 00776 const size_t rows,const MagickBooleanType detach,ExceptionInfo *exception) 00777 { 00778 Image 00779 *clone_image; 00780 00781 MagickRealType 00782 scale; 00783 00784 size_t 00785 length; 00786 00787 /* 00788 Clone the image. 00789 */ 00790 assert(image != (const Image *) NULL); 00791 assert(image->signature == MagickSignature); 00792 if (image->debug != MagickFalse) 00793 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename); 00794 assert(exception != (ExceptionInfo *) NULL); 00795 assert(exception->signature == MagickSignature); 00796 clone_image=(Image *) AcquireMagickMemory(sizeof(*clone_image)); 00797 if (clone_image == (Image *) NULL) 00798 ThrowImageException(ResourceLimitError,"MemoryAllocationFailed"); 00799 (void) ResetMagickMemory(clone_image,0,sizeof(*clone_image)); 00800 clone_image->signature=MagickSignature; 00801 clone_image->storage_class=image->storage_class; 00802 clone_image->number_channels=image->number_channels; 00803 clone_image->number_meta_channels=image->number_meta_channels; 00804 clone_image->metacontent_extent=image->metacontent_extent; 00805 clone_image->colorspace=image->colorspace; 00806 clone_image->mask=image->mask; 00807 clone_image->matte=image->matte; 00808 clone_image->columns=image->columns; 00809 clone_image->rows=image->rows; 00810 clone_image->dither=image->dither; 00811 if (image->colormap != (PixelInfo *) NULL) 00812 { 00813 /* 00814 Allocate and copy the image colormap. 00815 */ 00816 clone_image->colors=image->colors; 00817 length=(size_t) image->colors; 00818 clone_image->colormap=(PixelInfo *) AcquireQuantumMemory(length, 00819 sizeof(*clone_image->colormap)); 00820 if (clone_image->colormap == (PixelInfo *) NULL) 00821 ThrowImageException(ResourceLimitError,"MemoryAllocationFailed"); 00822 (void) CopyMagickMemory(clone_image->colormap,image->colormap,length* 00823 sizeof(*clone_image->colormap)); 00824 } 00825 (void) CloneImageProfiles(clone_image,image); 00826 (void) CloneImageProperties(clone_image,image); 00827 (void) CloneImageArtifacts(clone_image,image); 00828 GetTimerInfo(&clone_image->timer); 00829 if (image->ascii85 != (void *) NULL) 00830 Ascii85Initialize(clone_image); 00831 clone_image->magick_columns=image->magick_columns; 00832 clone_image->magick_rows=image->magick_rows; 00833 clone_image->type=image->type; 00834 clone_image->channel_mask=image->channel_mask; 00835 clone_image->channel_map=ClonePixelChannelMap(image->channel_map); 00836 (void) CopyMagickString(clone_image->magick_filename,image->magick_filename, 00837 MaxTextExtent); 00838 (void) CopyMagickString(clone_image->magick,image->magick,MaxTextExtent); 00839 (void) CopyMagickString(clone_image->filename,image->filename,MaxTextExtent); 00840 clone_image->progress_monitor=image->progress_monitor; 00841 clone_image->client_data=image->client_data; 00842 clone_image->reference_count=1; 00843 clone_image->next=image->next; 00844 clone_image->previous=image->previous; 00845 clone_image->list=NewImageList(); 00846 if (detach == MagickFalse) 00847 clone_image->blob=ReferenceBlob(image->blob); 00848 else 00849 { 00850 clone_image->next=NewImageList(); 00851 clone_image->previous=NewImageList(); 00852 clone_image->blob=CloneBlobInfo((BlobInfo *) NULL); 00853 } 00854 clone_image->ping=image->ping; 00855 clone_image->debug=IsEventLogging(); 00856 clone_image->semaphore=AllocateSemaphoreInfo(); 00857 if ((columns == 0) && (rows == 0)) 00858 { 00859 if (image->montage != (char *) NULL) 00860 (void) CloneString(&clone_image->montage,image->montage); 00861 if (image->directory != (char *) NULL) 00862 (void) CloneString(&clone_image->directory,image->directory); 00863 clone_image->cache=ReferencePixelCache(image->cache); 00864 return(clone_image); 00865 } 00866 scale=(MagickRealType) columns/(MagickRealType) image->columns; 00867 clone_image->page.width=(size_t) floor(scale*image->page.width+0.5); 00868 clone_image->page.x=(ssize_t) ceil(scale*image->page.x-0.5); 00869 clone_image->tile_offset.x=(ssize_t) ceil(scale*image->tile_offset.x-0.5); 00870 scale=(MagickRealType) rows/(MagickRealType) image->rows; 00871 clone_image->page.height=(size_t) floor(scale*image->page.height+0.5); 00872 clone_image->page.y=(ssize_t) ceil(scale*image->page.y-0.5); 00873 clone_image->tile_offset.y=(ssize_t) ceil(scale*image->tile_offset.y-0.5); 00874 clone_image->columns=columns; 00875 clone_image->rows=rows; 00876 clone_image->cache=ClonePixelCache(image->cache); 00877 return(clone_image); 00878 } 00879 00880 /* 00881 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 00882 % % 00883 % % 00884 % % 00885 % C l o n e I m a g e I n f o % 00886 % % 00887 % % 00888 % % 00889 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 00890 % 00891 % CloneImageInfo() makes a copy of the given image info structure. If 00892 % NULL is specified, a new image info structure is created initialized to 00893 % default values. 00894 % 00895 % The format of the CloneImageInfo method is: 00896 % 00897 % ImageInfo *CloneImageInfo(const ImageInfo *image_info) 00898 % 00899 % A description of each parameter follows: 00900 % 00901 % o image_info: the image info. 00902 % 00903 */ 00904 MagickExport ImageInfo *CloneImageInfo(const ImageInfo *image_info) 00905 { 00906 ImageInfo 00907 *clone_info; 00908 00909 clone_info=AcquireImageInfo(); 00910 if (image_info == (ImageInfo *) NULL) 00911 return(clone_info); 00912 clone_info->compression=image_info->compression; 00913 clone_info->temporary=image_info->temporary; 00914 clone_info->adjoin=image_info->adjoin; 00915 clone_info->antialias=image_info->antialias; 00916 clone_info->scene=image_info->scene; 00917 clone_info->number_scenes=image_info->number_scenes; 00918 clone_info->depth=image_info->depth; 00919 (void) CloneString(&clone_info->size,image_info->size); 00920 (void) CloneString(&clone_info->extract,image_info->extract); 00921 (void) CloneString(&clone_info->scenes,image_info->scenes); 00922 (void) CloneString(&clone_info->page,image_info->page); 00923 clone_info->interlace=image_info->interlace; 00924 clone_info->endian=image_info->endian; 00925 clone_info->units=image_info->units; 00926 clone_info->quality=image_info->quality; 00927 (void) CloneString(&clone_info->sampling_factor,image_info->sampling_factor); 00928 (void) CloneString(&clone_info->server_name,image_info->server_name); 00929 (void) CloneString(&clone_info->font,image_info->font); 00930 (void) CloneString(&clone_info->texture,image_info->texture); 00931 (void) CloneString(&clone_info->density,image_info->density); 00932 clone_info->pointsize=image_info->pointsize; 00933 clone_info->fuzz=image_info->fuzz; 00934 clone_info->background_color=image_info->background_color; 00935 clone_info->border_color=image_info->border_color; 00936 clone_info->matte_color=image_info->matte_color; 00937 clone_info->transparent_color=image_info->transparent_color; 00938 clone_info->dither=image_info->dither; 00939 clone_info->monochrome=image_info->monochrome; 00940 clone_info->colorspace=image_info->colorspace; 00941 clone_info->type=image_info->type; 00942 clone_info->orientation=image_info->orientation; 00943 clone_info->preview_type=image_info->preview_type; 00944 clone_info->group=image_info->group; 00945 clone_info->ping=image_info->ping; 00946 clone_info->verbose=image_info->verbose; 00947 (void) CloneString(&clone_info->view,image_info->view); 00948 clone_info->progress_monitor=image_info->progress_monitor; 00949 clone_info->client_data=image_info->client_data; 00950 clone_info->cache=image_info->cache; 00951 if (image_info->cache != (void *) NULL) 00952 clone_info->cache=ReferencePixelCache(image_info->cache); 00953 if (image_info->profile != (void *) NULL) 00954 clone_info->profile=(void *) CloneStringInfo((StringInfo *) 00955 image_info->profile); 00956 SetImageInfoFile(clone_info,image_info->file); 00957 SetImageInfoBlob(clone_info,image_info->blob,image_info->length); 00958 clone_info->stream=image_info->stream; 00959 (void) CopyMagickString(clone_info->magick,image_info->magick,MaxTextExtent); 00960 (void) CopyMagickString(clone_info->unique,image_info->unique,MaxTextExtent); 00961 (void) CopyMagickString(clone_info->zero,image_info->zero,MaxTextExtent); 00962 (void) CopyMagickString(clone_info->filename,image_info->filename, 00963 MaxTextExtent); 00964 clone_info->channel=image_info->channel; 00965 (void) CloneImageOptions(clone_info,image_info); 00966 clone_info->debug=IsEventLogging(); 00967 clone_info->signature=image_info->signature; 00968 return(clone_info); 00969 } 00970 00971 /* 00972 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 00973 % % 00974 % % 00975 % % 00976 % C o m b i n e I m a g e s % 00977 % % 00978 % % 00979 % % 00980 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 00981 % 00982 % CombineImages() combines one or more images into a single image. The 00983 % grayscale value of the pixels of each image in the sequence is assigned in 00984 % order to the specified channels of the combined image. The typical 00985 % ordering would be image 1 => Red, 2 => Green, 3 => Blue, etc. 00986 % 00987 % The format of the CombineImages method is: 00988 % 00989 % Image *CombineImages(const Image *image,ExceptionInfo *exception) 00990 % 00991 % A description of each parameter follows: 00992 % 00993 % o image: the image. 00994 % 00995 % o exception: return any errors or warnings in this structure. 00996 % 00997 */ 00998 00999 static inline size_t MagickMin(const size_t x,const size_t y) 01000 { 01001 if (x < y) 01002 return(x); 01003 return(y); 01004 } 01005 01006 MagickExport Image *CombineImages(const Image *image,ExceptionInfo *exception) 01007 { 01008 #define CombineImageTag "Combine/Image" 01009 01010 CacheView 01011 *combine_view; 01012 01013 Image 01014 *combine_image; 01015 01016 MagickBooleanType 01017 status; 01018 01019 MagickOffsetType 01020 progress; 01021 01022 ssize_t 01023 y; 01024 01025 /* 01026 Ensure the image are the same size. 01027 */ 01028 assert(image != (const Image *) NULL); 01029 assert(image->signature == MagickSignature); 01030 if (image->debug != MagickFalse) 01031 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename); 01032 assert(exception != (ExceptionInfo *) NULL); 01033 assert(exception->signature == MagickSignature); 01034 combine_image=CloneImage(image,0,0,MagickTrue,exception); 01035 if (combine_image == (Image *) NULL) 01036 return((Image *) NULL); 01037 if (SetImageStorageClass(combine_image,DirectClass,exception) == MagickFalse) 01038 { 01039 combine_image=DestroyImage(combine_image); 01040 return((Image *) NULL); 01041 } 01042 if ((GetPixelAlphaTraits(image) & UpdatePixelTrait) != 0) 01043 combine_image->matte=MagickTrue; 01044 /* 01045 Combine images. 01046 */ 01047 status=MagickTrue; 01048 progress=0; 01049 combine_view=AcquireCacheView(combine_image); 01050 for (y=0; y < (ssize_t) combine_image->rows; y++) 01051 { 01052 CacheView 01053 *image_view; 01054 01055 const Image 01056 *next; 01057 01058 Quantum 01059 *pixels; 01060 01061 register const Quantum 01062 *restrict p; 01063 01064 register Quantum 01065 *restrict q; 01066 01067 register ssize_t 01068 i; 01069 01070 if (status == MagickFalse) 01071 continue; 01072 pixels=GetCacheViewAuthenticPixels(combine_view,0,y,combine_image->columns, 01073 1,exception); 01074 if (pixels == (Quantum *) NULL) 01075 { 01076 status=MagickFalse; 01077 continue; 01078 } 01079 next=image; 01080 for (i=0; i < (ssize_t) GetPixelChannels(image); i++) 01081 { 01082 PixelChannel 01083 channel; 01084 01085 PixelTrait 01086 combine_traits, 01087 traits; 01088 01089 register ssize_t 01090 x; 01091 01092 if (next == (Image *) NULL) 01093 continue; 01094 channel=GetPixelChannelMapChannel(image,i); 01095 traits=GetPixelChannelMapTraits(image,channel); 01096 combine_traits=GetPixelChannelMapTraits(combine_image,channel); 01097 if ((traits == UndefinedPixelTrait) || 01098 (combine_traits == UndefinedPixelTrait)) 01099 continue; 01100 image_view=AcquireCacheView(next); 01101 p=GetCacheViewVirtualPixels(image_view,0,y,next->columns,1,exception); 01102 if (p == (const Quantum *) NULL) 01103 continue; 01104 q=pixels; 01105 for (x=0; x < (ssize_t) combine_image->columns; x++) 01106 { 01107 if (x < (ssize_t) image->columns) 01108 { 01109 q[i]=GetPixelGray(image,p); 01110 p+=GetPixelChannels(image); 01111 } 01112 q+=GetPixelChannels(combine_image); 01113 } 01114 image_view=DestroyCacheView(image_view); 01115 next=GetNextImageInList(next); 01116 if (SyncCacheViewAuthenticPixels(combine_view,exception) == MagickFalse) 01117 status=MagickFalse; 01118 if (image->progress_monitor != (MagickProgressMonitor) NULL) 01119 { 01120 MagickBooleanType 01121 proceed; 01122 01123 proceed=SetImageProgress(image,CombineImageTag,progress++, 01124 combine_image->rows); 01125 if (proceed == MagickFalse) 01126 status=MagickFalse; 01127 } 01128 } 01129 } 01130 combine_view=DestroyCacheView(combine_view); 01131 if (status == MagickFalse) 01132 combine_image=DestroyImage(combine_image); 01133 return(combine_image); 01134 } 01135 01136 /* 01137 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 01138 % % 01139 % % 01140 % % 01141 % D e s t r o y I m a g e % 01142 % % 01143 % % 01144 % % 01145 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 01146 % 01147 % DestroyImage() dereferences an image, deallocating memory associated with 01148 % the image if the reference count becomes zero. 01149 % 01150 % The format of the DestroyImage method is: 01151 % 01152 % Image *DestroyImage(Image *image) 01153 % 01154 % A description of each parameter follows: 01155 % 01156 % o image: the image. 01157 % 01158 */ 01159 MagickExport Image *DestroyImage(Image *image) 01160 { 01161 MagickBooleanType 01162 destroy; 01163 01164 /* 01165 Dereference image. 01166 */ 01167 assert(image != (Image *) NULL); 01168 assert(image->signature == MagickSignature); 01169 if (image->debug != MagickFalse) 01170 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename); 01171 destroy=MagickFalse; 01172 LockSemaphoreInfo(image->semaphore); 01173 image->reference_count--; 01174 if (image->reference_count == 0) 01175 destroy=MagickTrue; 01176 UnlockSemaphoreInfo(image->semaphore); 01177 if (destroy == MagickFalse) 01178 return((Image *) NULL); 01179 /* 01180 Destroy image. 01181 */ 01182 DestroyImagePixels(image); 01183 image->channel_map=DestroyPixelChannelMap(image->channel_map); 01184 if (image->montage != (char *) NULL) 01185 image->montage=DestroyString(image->montage); 01186 if (image->directory != (char *) NULL) 01187 image->directory=DestroyString(image->directory); 01188 if (image->colormap != (PixelInfo *) NULL) 01189 image->colormap=(PixelInfo *) RelinquishMagickMemory(image->colormap); 01190 if (image->geometry != (char *) NULL) 01191 image->geometry=DestroyString(image->geometry); 01192 DestroyImageProfiles(image); 01193 DestroyImageProperties(image); 01194 DestroyImageArtifacts(image); 01195 if (image->ascii85 != (Ascii85Info*) NULL) 01196 image->ascii85=(Ascii85Info *) RelinquishMagickMemory(image->ascii85); 01197 DestroyBlob(image); 01198 if (image->semaphore != (SemaphoreInfo *) NULL) 01199 DestroySemaphoreInfo(&image->semaphore); 01200 image->signature=(~MagickSignature); 01201 image=(Image *) RelinquishMagickMemory(image); 01202 return(image); 01203 } 01204 01205 /* 01206 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 01207 % % 01208 % % 01209 % % 01210 % D e s t r o y I m a g e I n f o % 01211 % % 01212 % % 01213 % % 01214 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 01215 % 01216 % DestroyImageInfo() deallocates memory associated with an ImageInfo 01217 % structure. 01218 % 01219 % The format of the DestroyImageInfo method is: 01220 % 01221 % ImageInfo *DestroyImageInfo(ImageInfo *image_info) 01222 % 01223 % A description of each parameter follows: 01224 % 01225 % o image_info: the image info. 01226 % 01227 */ 01228 MagickExport ImageInfo *DestroyImageInfo(ImageInfo *image_info) 01229 { 01230 assert(image_info != (ImageInfo *) NULL); 01231 assert(image_info->signature == MagickSignature); 01232 if (image_info->debug != MagickFalse) 01233 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s", 01234 image_info->filename); 01235 if (image_info->size != (char *) NULL) 01236 image_info->size=DestroyString(image_info->size); 01237 if (image_info->extract != (char *) NULL) 01238 image_info->extract=DestroyString(image_info->extract); 01239 if (image_info->scenes != (char *) NULL) 01240 image_info->scenes=DestroyString(image_info->scenes); 01241 if (image_info->page != (char *) NULL) 01242 image_info->page=DestroyString(image_info->page); 01243 if (image_info->sampling_factor != (char *) NULL) 01244 image_info->sampling_factor=DestroyString( 01245 image_info->sampling_factor); 01246 if (image_info->server_name != (char *) NULL) 01247 image_info->server_name=DestroyString( 01248 image_info->server_name); 01249 if (image_info->font != (char *) NULL) 01250 image_info->font=DestroyString(image_info->font); 01251 if (image_info->texture != (char *) NULL) 01252 image_info->texture=DestroyString(image_info->texture); 01253 if (image_info->density != (char *) NULL) 01254 image_info->density=DestroyString(image_info->density); 01255 if (image_info->view != (char *) NULL) 01256 image_info->view=DestroyString(image_info->view); 01257 if (image_info->cache != (void *) NULL) 01258 image_info->cache=DestroyPixelCache(image_info->cache); 01259 if (image_info->profile != (StringInfo *) NULL) 01260 image_info->profile=(void *) DestroyStringInfo((StringInfo *) 01261 image_info->profile); 01262 DestroyImageOptions(image_info); 01263 image_info->signature=(~MagickSignature); 01264 image_info=(ImageInfo *) RelinquishMagickMemory(image_info); 01265 return(image_info); 01266 } 01267 01268 /* 01269 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 01270 % % 01271 % % 01272 % % 01273 + D i s a s s o c i a t e I m a g e S t r e a m % 01274 % % 01275 % % 01276 % % 01277 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 01278 % 01279 % DisassociateImageStream() disassociates the image stream. 01280 % 01281 % The format of the DisassociateImageStream method is: 01282 % 01283 % MagickBooleanType DisassociateImageStream(const Image *image) 01284 % 01285 % A description of each parameter follows: 01286 % 01287 % o image: the image. 01288 % 01289 */ 01290 MagickExport void DisassociateImageStream(Image *image) 01291 { 01292 assert(image != (const Image *) NULL); 01293 assert(image->signature == MagickSignature); 01294 if (image->debug != MagickFalse) 01295 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename); 01296 (void) DetachBlob(image->blob); 01297 } 01298 01299 /* 01300 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 01301 % % 01302 % % 01303 % % 01304 % G e t I m a g e A l p h a C h a n n e l % 01305 % % 01306 % % 01307 % % 01308 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 01309 % 01310 % GetImageAlphaChannel() returns MagickFalse if the image alpha channel is 01311 % not activated. That is, the image is RGB rather than RGBA or CMYK rather 01312 % than CMYKA. 01313 % 01314 % The format of the GetImageAlphaChannel method is: 01315 % 01316 % MagickBooleanType GetImageAlphaChannel(const Image *image) 01317 % 01318 % A description of each parameter follows: 01319 % 01320 % o image: the image. 01321 % 01322 */ 01323 MagickExport MagickBooleanType GetImageAlphaChannel(const Image *image) 01324 { 01325 assert(image != (const Image *) NULL); 01326 if (image->debug != MagickFalse) 01327 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"..."); 01328 assert(image->signature == MagickSignature); 01329 return(image->matte); 01330 } 01331 01332 /* 01333 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 01334 % % 01335 % % 01336 % % 01337 % G e t I m a g e I n f o % 01338 % % 01339 % % 01340 % % 01341 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 01342 % 01343 % GetImageInfo() initializes image_info to default values. 01344 % 01345 % The format of the GetImageInfo method is: 01346 % 01347 % void GetImageInfo(ImageInfo *image_info) 01348 % 01349 % A description of each parameter follows: 01350 % 01351 % o image_info: the image info. 01352 % 01353 */ 01354 MagickExport void GetImageInfo(ImageInfo *image_info) 01355 { 01356 const char 01357 *synchronize; 01358 01359 ExceptionInfo 01360 *exception; 01361 01362 /* 01363 File and image dimension members. 01364 */ 01365 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"..."); 01366 assert(image_info != (ImageInfo *) NULL); 01367 (void) ResetMagickMemory(image_info,0,sizeof(*image_info)); 01368 image_info->adjoin=MagickTrue; 01369 image_info->interlace=NoInterlace; 01370 image_info->channel=DefaultChannels; 01371 image_info->quality=UndefinedCompressionQuality; 01372 image_info->antialias=MagickTrue; 01373 image_info->dither=MagickTrue; 01374 synchronize=GetEnvironmentValue("MAGICK_SYNCHRONIZE"); 01375 if (synchronize != (const char *) NULL) 01376 image_info->synchronize=IsMagickTrue(synchronize); 01377 exception=AcquireExceptionInfo(); 01378 (void) QueryColorCompliance(BackgroundColor,AllCompliance, 01379 &image_info->background_color,exception); 01380 (void) QueryColorCompliance(BorderColor,AllCompliance, 01381 &image_info->border_color,exception); 01382 (void) QueryColorCompliance(MatteColor,AllCompliance,&image_info->matte_color, 01383 exception); 01384 (void) QueryColorCompliance(TransparentColor,AllCompliance, 01385 &image_info->transparent_color,exception); 01386 exception=DestroyExceptionInfo(exception); 01387 image_info->debug=IsEventLogging(); 01388 image_info->signature=MagickSignature; 01389 } 01390 01391 /* 01392 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 01393 % % 01394 % % 01395 % % 01396 % G e t I m a g e I n f o F i l e % 01397 % % 01398 % % 01399 % % 01400 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 01401 % 01402 % GetImageInfoFile() returns the image info file member. 01403 % 01404 % The format of the GetImageInfoFile method is: 01405 % 01406 % FILE *GetImageInfoFile(const ImageInfo *image_info) 01407 % 01408 % A description of each parameter follows: 01409 % 01410 % o image_info: the image info. 01411 % 01412 */ 01413 MagickExport FILE *GetImageInfoFile(const ImageInfo *image_info) 01414 { 01415 return(image_info->file); 01416 } 01417 01418 /* 01419 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 01420 % % 01421 % % 01422 % % 01423 % G e t I m a g e M a s k % 01424 % % 01425 % % 01426 % % 01427 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 01428 % 01429 % GetImageMask() returns the mask associated with the image. 01430 % 01431 % The format of the GetImageMask method is: 01432 % 01433 % Image *GetImageMask(const Image *image,ExceptionInfo *exception) 01434 % 01435 % A description of each parameter follows: 01436 % 01437 % o image: the image. 01438 % 01439 */ 01440 MagickExport Image *GetImageMask(const Image *image,ExceptionInfo *exception) 01441 { 01442 CacheView 01443 *mask_view, 01444 *image_view; 01445 01446 Image 01447 *mask_image; 01448 01449 MagickBooleanType 01450 status; 01451 01452 ssize_t 01453 y; 01454 01455 /* 01456 Get image mask. 01457 */ 01458 assert(image != (Image *) NULL); 01459 if (image->debug != MagickFalse) 01460 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"..."); 01461 assert(image->signature == MagickSignature); 01462 mask_image=CloneImage(image,image->columns,image->rows,MagickTrue,exception); 01463 if (mask_image == (Image *) NULL) 01464 return((Image *) NULL); 01465 status=MagickTrue; 01466 mask_image->colorspace=GRAYColorspace; 01467 mask_image->mask=MagickFalse; 01468 image_view=AcquireCacheView(image); 01469 mask_view=AcquireCacheView(mask_image); 01470 for (y=0; y < (ssize_t) image->rows; y++) 01471 { 01472 register const Quantum 01473 *restrict p; 01474 01475 register Quantum 01476 *restrict q; 01477 01478 register ssize_t 01479 x; 01480 01481 if (status == MagickFalse) 01482 continue; 01483 p=GetCacheViewVirtualPixels(image_view,0,y,image->columns,1,exception); 01484 q=GetCacheViewAuthenticPixels(mask_view,0,y,mask_image->columns,1, 01485 exception); 01486 if ((p == (const Quantum *) NULL) || (q == (Quantum *) NULL)) 01487 { 01488 status=MagickFalse; 01489 continue; 01490 } 01491 for (x=0; x < (ssize_t) image->columns; x++) 01492 { 01493 SetPixelGray(mask_image,GetPixelMask(image,p),q); 01494 p+=GetPixelChannels(image); 01495 q+=GetPixelChannels(mask_image); 01496 } 01497 if (SyncCacheViewAuthenticPixels(mask_view,exception) == MagickFalse) 01498 status=MagickFalse; 01499 } 01500 mask_view=DestroyCacheView(mask_view); 01501 image_view=DestroyCacheView(image_view); 01502 return(mask_image); 01503 } 01504 01505 /* 01506 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 01507 % % 01508 % % 01509 % % 01510 + G e t I m a g e R e f e r e n c e C o u n t % 01511 % % 01512 % % 01513 % % 01514 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 01515 % 01516 % GetImageReferenceCount() returns the image reference count. 01517 % 01518 % The format of the GetReferenceCount method is: 01519 % 01520 % ssize_t GetImageReferenceCount(Image *image) 01521 % 01522 % A description of each parameter follows: 01523 % 01524 % o image: the image. 01525 % 01526 */ 01527 MagickExport ssize_t GetImageReferenceCount(Image *image) 01528 { 01529 ssize_t 01530 reference_count; 01531 01532 assert(image != (Image *) NULL); 01533 assert(image->signature == MagickSignature); 01534 if (image->debug != MagickFalse) 01535 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename); 01536 LockSemaphoreInfo(image->semaphore); 01537 reference_count=image->reference_count; 01538 UnlockSemaphoreInfo(image->semaphore); 01539 return(reference_count); 01540 } 01541 01542 /* 01543 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 01544 % % 01545 % % 01546 % % 01547 % G e t I m a g e V i r t u a l P i x e l M e t h o d % 01548 % % 01549 % % 01550 % % 01551 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 01552 % 01553 % GetImageVirtualPixelMethod() gets the "virtual pixels" method for the 01554 % image. A virtual pixel is any pixel access that is outside the boundaries 01555 % of the image cache. 01556 % 01557 % The format of the GetImageVirtualPixelMethod() method is: 01558 % 01559 % VirtualPixelMethod GetImageVirtualPixelMethod(const Image *image) 01560 % 01561 % A description of each parameter follows: 01562 % 01563 % o image: the image. 01564 % 01565 */ 01566 MagickExport VirtualPixelMethod GetImageVirtualPixelMethod(const Image *image) 01567 { 01568 assert(image != (Image *) NULL); 01569 assert(image->signature == MagickSignature); 01570 if (image->debug != MagickFalse) 01571 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename); 01572 return(GetPixelCacheVirtualMethod(image)); 01573 } 01574 01575 /* 01576 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 01577 % % 01578 % % 01579 % % 01580 % I n t e r p r e t I m a g e F i l e n a m e % 01581 % % 01582 % % 01583 % % 01584 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 01585 % 01586 % InterpretImageFilename() interprets embedded characters in an image filename. 01587 % The filename length is returned. 01588 % 01589 % The format of the InterpretImageFilename method is: 01590 % 01591 % size_t InterpretImageFilename(const ImageInfo *image_info, 01592 % Image *image,const char *format,int value,char *filename, 01593 % ExceptionInfo *exception) 01594 % 01595 % A description of each parameter follows. 01596 % 01597 % o image_info: the image info.. 01598 % 01599 % o image: the image. 01600 % 01601 % o format: A filename describing the format to use to write the numeric 01602 % argument. Only the first numeric format identifier is replaced. 01603 % 01604 % o value: Numeric value to substitute into format filename. 01605 % 01606 % o filename: return the formatted filename in this character buffer. 01607 % 01608 % o exception: return any errors or warnings in this structure. 01609 % 01610 */ 01611 MagickExport size_t InterpretImageFilename(const ImageInfo *image_info, 01612 Image *image,const char *format,int value,char *filename, 01613 ExceptionInfo *exception) 01614 { 01615 char 01616 *q; 01617 01618 int 01619 c; 01620 01621 MagickBooleanType 01622 canonical; 01623 01624 register const char 01625 *p; 01626 01627 size_t 01628 length; 01629 01630 canonical=MagickFalse; 01631 length=0; 01632 (void) CopyMagickString(filename,format,MaxTextExtent); 01633 for (p=strchr(format,'%'); p != (char *) NULL; p=strchr(p+1,'%')) 01634 { 01635 q=(char *) p+1; 01636 if (*q == '%') 01637 { 01638 p=q+1; 01639 continue; 01640 } 01641 if (*q == '0') 01642 { 01643 ssize_t 01644 value; 01645 01646 value=(ssize_t) strtol(q,&q,10); 01647 (void) value; 01648 } 01649 switch (*q) 01650 { 01651 case 'd': 01652 case 'o': 01653 case 'x': 01654 { 01655 q++; 01656 c=(*q); 01657 *q='\0'; 01658 (void) FormatLocaleString(filename+(p-format),(size_t) (MaxTextExtent- 01659 (p-format)),p,value); 01660 *q=c; 01661 (void) ConcatenateMagickString(filename,q,MaxTextExtent); 01662 canonical=MagickTrue; 01663 if (*(q-1) != '%') 01664 break; 01665 p++; 01666 break; 01667 } 01668 case '[': 01669 { 01670 char 01671 pattern[MaxTextExtent]; 01672 01673 const char 01674 *value; 01675 01676 register char 01677 *r; 01678 01679 register ssize_t 01680 i; 01681 01682 ssize_t 01683 depth; 01684 01685 /* 01686 Image option. 01687 */ 01688 if (strchr(p,']') == (char *) NULL) 01689 break; 01690 depth=1; 01691 r=q+1; 01692 for (i=0; (i < (MaxTextExtent-1L)) && (*r != '\0'); i++) 01693 { 01694 if (*r == '[') 01695 depth++; 01696 if (*r == ']') 01697 depth--; 01698 if (depth <= 0) 01699 break; 01700 pattern[i]=(*r++); 01701 } 01702 pattern[i]='\0'; 01703 if (LocaleNCompare(pattern,"filename:",9) != 0) 01704 break; 01705 value=(const char *) NULL; 01706 if ((image_info != (const ImageInfo *) NULL) && 01707 (image != (const Image *) NULL)) 01708 value=GetMagickProperty(image_info,image,pattern,exception); 01709 else 01710 if (image != (Image *) NULL) 01711 value=GetImageProperty(image,pattern,exception); 01712 else 01713 if (image_info != (ImageInfo *) NULL) 01714 value=GetImageOption(image_info,pattern); 01715 if (value == (const char *) NULL) 01716 break; 01717 q--; 01718 c=(*q); 01719 *q='\0'; 01720 (void) CopyMagickString(filename+(p-format-length),value,(size_t) 01721 (MaxTextExtent-(p-format-length))); 01722 length+=strlen(pattern)-1; 01723 *q=c; 01724 (void) ConcatenateMagickString(filename,r+1,MaxTextExtent); 01725 canonical=MagickTrue; 01726 if (*(q-1) != '%') 01727 break; 01728 p++; 01729 break; 01730 } 01731 default: 01732 break; 01733 } 01734 } 01735 for (q=filename; *q != '\0'; q++) 01736 if ((*q == '%') && (*(q+1) == '%')) 01737 { 01738 (void) CopyMagickString(q,q+1,(size_t) (MaxTextExtent-(q-filename))); 01739 canonical=MagickTrue; 01740 } 01741 if (canonical == MagickFalse) 01742 (void) CopyMagickString(filename,format,MaxTextExtent); 01743 return(strlen(filename)); 01744 } 01745 01746 /* 01747 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 01748 % % 01749 % % 01750 % % 01751 % I s H i g h D y n a m i c R a n g e I m a g e % 01752 % % 01753 % % 01754 % % 01755 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 01756 % 01757 % IsHighDynamicRangeImage() returns MagickTrue if any pixel component is 01758 % non-integer or exceeds the bounds of the quantum depth (e.g. for Q16 01759 % 0..65535. 01760 % 01761 % The format of the IsHighDynamicRangeImage method is: 01762 % 01763 % MagickBooleanType IsHighDynamicRangeImage(const Image *image, 01764 % ExceptionInfo *exception) 01765 % 01766 % A description of each parameter follows: 01767 % 01768 % o image: the image. 01769 % 01770 % o exception: return any errors or warnings in this structure. 01771 % 01772 */ 01773 MagickExport MagickBooleanType IsHighDynamicRangeImage(const Image *image, 01774 ExceptionInfo *exception) 01775 { 01776 #if !defined(MAGICKCORE_HDRI_SUPPORT) 01777 (void) image; 01778 (void) exception; 01779 return(MagickFalse); 01780 #else 01781 CacheView 01782 *image_view; 01783 01784 MagickBooleanType 01785 status; 01786 01787 ssize_t 01788 y; 01789 01790 assert(image != (Image *) NULL); 01791 assert(image->signature == MagickSignature); 01792 if (image->debug != MagickFalse) 01793 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename); 01794 status=MagickTrue; 01795 image_view=AcquireCacheView(image); 01796 #if defined(MAGICKCORE_OPENMP_SUPPORT) 01797 #pragma omp parallel for schedule(static,4) shared(status) 01798 #endif 01799 for (y=0; y < (ssize_t) image->rows; y++) 01800 { 01801 PixelInfo 01802 pixel; 01803 01804 register const Quantum 01805 *p; 01806 01807 register ssize_t 01808 x; 01809 01810 if (status == MagickFalse) 01811 continue; 01812 p=GetCacheViewVirtualPixels(image_view,0,y,image->columns,1,exception); 01813 if (p == (const Quantum *) NULL) 01814 { 01815 status=MagickFalse; 01816 continue; 01817 } 01818 for (x=0; x < (ssize_t) image->columns; x++) 01819 { 01820 PixelTrait 01821 traits; 01822 01823 register ssize_t 01824 i; 01825 01826 if (GetPixelMask(image,p) != 0) 01827 { 01828 p+=GetPixelChannels(image); 01829 continue; 01830 } 01831 for (i=0; i < (ssize_t) GetPixelChannels(image); i++) 01832 { 01833 MagickRealType 01834 pixel; 01835 01836 traits=GetPixelChannelMapTraits(image,i); 01837 if (traits == UndefinedPixelTrait) 01838 continue; 01839 pixel=(MagickRealType) p[i]; 01840 if ((pixel < 0.0) || (pixel > QuantumRange) || 01841 (pixel != (QuantumAny) pixel)) 01842 break; 01843 } 01844 p+=GetPixelChannels(image); 01845 if (i < (ssize_t) GetPixelChannels(image)) 01846 status=MagickFalse; 01847 } 01848 if (x < (ssize_t) image->columns) 01849 status=MagickFalse; 01850 } 01851 image_view=DestroyCacheView(image_view); 01852 return(status != MagickFalse ? MagickFalse : MagickTrue); 01853 #endif 01854 } 01855 01856 /* 01857 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 01858 % % 01859 % % 01860 % % 01861 % I s I m a g e O b j e c t % 01862 % % 01863 % % 01864 % % 01865 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 01866 % 01867 % IsImageObject() returns MagickTrue if the image sequence contains a valid 01868 % set of image objects. 01869 % 01870 % The format of the IsImageObject method is: 01871 % 01872 % MagickBooleanType IsImageObject(const Image *image) 01873 % 01874 % A description of each parameter follows: 01875 % 01876 % o image: the image. 01877 % 01878 */ 01879 MagickExport MagickBooleanType IsImageObject(const Image *image) 01880 { 01881 register const Image 01882 *p; 01883 01884 assert(image != (Image *) NULL); 01885 if (image->debug != MagickFalse) 01886 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"..."); 01887 for (p=image; p != (Image *) NULL; p=GetNextImageInList(p)) 01888 if (p->signature != MagickSignature) 01889 return(MagickFalse); 01890 return(MagickTrue); 01891 } 01892 01893 /* 01894 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 01895 % % 01896 % % 01897 % % 01898 % I s T a i n t I m a g e % 01899 % % 01900 % % 01901 % % 01902 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 01903 % 01904 % IsTaintImage() returns MagickTrue any pixel in the image has been altered 01905 % since it was first constituted. 01906 % 01907 % The format of the IsTaintImage method is: 01908 % 01909 % MagickBooleanType IsTaintImage(const Image *image) 01910 % 01911 % A description of each parameter follows: 01912 % 01913 % o image: the image. 01914 % 01915 */ 01916 MagickExport MagickBooleanType IsTaintImage(const Image *image) 01917 { 01918 char 01919 magick[MaxTextExtent], 01920 filename[MaxTextExtent]; 01921 01922 register const Image 01923 *p; 01924 01925 assert(image != (Image *) NULL); 01926 if (image->debug != MagickFalse) 01927 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"..."); 01928 assert(image->signature == MagickSignature); 01929 (void) CopyMagickString(magick,image->magick,MaxTextExtent); 01930 (void) CopyMagickString(filename,image->filename,MaxTextExtent); 01931 for (p=image; p != (Image *) NULL; p=GetNextImageInList(p)) 01932 { 01933 if (p->taint != MagickFalse) 01934 return(MagickTrue); 01935 if (LocaleCompare(p->magick,magick) != 0) 01936 return(MagickTrue); 01937 if (LocaleCompare(p->filename,filename) != 0) 01938 return(MagickTrue); 01939 } 01940 return(MagickFalse); 01941 } 01942 01943 /* 01944 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 01945 % % 01946 % % 01947 % % 01948 % M o d i f y I m a g e % 01949 % % 01950 % % 01951 % % 01952 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 01953 % 01954 % ModifyImage() ensures that there is only a single reference to the image 01955 % to be modified, updating the provided image pointer to point to a clone of 01956 % the original image if necessary. 01957 % 01958 % The format of the ModifyImage method is: 01959 % 01960 % MagickBooleanType ModifyImage(Image *image,ExceptionInfo *exception) 01961 % 01962 % A description of each parameter follows: 01963 % 01964 % o image: the image. 01965 % 01966 % o exception: return any errors or warnings in this structure. 01967 % 01968 */ 01969 MagickExport MagickBooleanType ModifyImage(Image **image, 01970 ExceptionInfo *exception) 01971 { 01972 Image 01973 *clone_image; 01974 01975 assert(image != (Image **) NULL); 01976 assert(*image != (Image *) NULL); 01977 assert((*image)->signature == MagickSignature); 01978 if ((*image)->debug != MagickFalse) 01979 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",(*image)->filename); 01980 if (GetImageReferenceCount(*image) <= 1) 01981 return(MagickTrue); 01982 clone_image=CloneImage(*image,0,0,MagickTrue,exception); 01983 LockSemaphoreInfo((*image)->semaphore); 01984 (*image)->reference_count--; 01985 UnlockSemaphoreInfo((*image)->semaphore); 01986 *image=clone_image; 01987 return(MagickTrue); 01988 } 01989 01990 /* 01991 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 01992 % % 01993 % % 01994 % % 01995 % N e w M a g i c k I m a g e % 01996 % % 01997 % % 01998 % % 01999 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 02000 % 02001 % NewMagickImage() creates a blank image canvas of the specified size and 02002 % background color. 02003 % 02004 % The format of the NewMagickImage method is: 02005 % 02006 % Image *NewMagickImage(const ImageInfo *image_info, 02007 % const size_t width,const size_t height,const PixelInfo *background, 02008 % ExceptionInfo *exception) 02009 % 02010 % A description of each parameter follows: 02011 % 02012 % o image: the image. 02013 % 02014 % o width: the image width. 02015 % 02016 % o height: the image height. 02017 % 02018 % o background: the image color. 02019 % 02020 % o exception: return any errors or warnings in this structure. 02021 % 02022 */ 02023 MagickExport Image *NewMagickImage(const ImageInfo *image_info, 02024 const size_t width,const size_t height,const PixelInfo *background, 02025 ExceptionInfo *exception) 02026 { 02027 CacheView 02028 *image_view; 02029 02030 Image 02031 *image; 02032 02033 MagickBooleanType 02034 status; 02035 02036 ssize_t 02037 y; 02038 02039 assert(image_info != (const ImageInfo *) NULL); 02040 if (image_info->debug != MagickFalse) 02041 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"..."); 02042 assert(image_info->signature == MagickSignature); 02043 assert(background != (const PixelInfo *) NULL); 02044 image=AcquireImage(image_info,exception); 02045 image->columns=width; 02046 image->rows=height; 02047 image->colorspace=background->colorspace; 02048 image->matte=background->matte; 02049 image->fuzz=background->fuzz; 02050 image->depth=background->depth; 02051 status=MagickTrue; 02052 image_view=AcquireCacheView(image); 02053 #if defined(MAGICKCORE_OPENMP_SUPPORT) 02054 #pragma omp parallel for schedule(static,4) shared(status) 02055 #endif 02056 for (y=0; y < (ssize_t) image->rows; y++) 02057 { 02058 register Quantum 02059 *restrict q; 02060 02061 register ssize_t 02062 x; 02063 02064 if (status == MagickFalse) 02065 continue; 02066 q=QueueCacheViewAuthenticPixels(image_view,0,y,image->columns,1,exception); 02067 if (q == (Quantum *) NULL) 02068 { 02069 status=MagickFalse; 02070 continue; 02071 } 02072 for (x=0; x < (ssize_t) image->columns; x++) 02073 { 02074 SetPixelInfoPixel(image,background,q); 02075 q+=GetPixelChannels(image); 02076 } 02077 if (SyncCacheViewAuthenticPixels(image_view,exception) == MagickFalse) 02078 status=MagickFalse; 02079 } 02080 image_view=DestroyCacheView(image_view); 02081 if (status == MagickFalse) 02082 image=DestroyImage(image); 02083 return(image); 02084 } 02085 02086 /* 02087 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 02088 % % 02089 % % 02090 % % 02091 % R e f e r e n c e I m a g e % 02092 % % 02093 % % 02094 % % 02095 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 02096 % 02097 % ReferenceImage() increments the reference count associated with an image 02098 % returning a pointer to the image. 02099 % 02100 % The format of the ReferenceImage method is: 02101 % 02102 % Image *ReferenceImage(Image *image) 02103 % 02104 % A description of each parameter follows: 02105 % 02106 % o image: the image. 02107 % 02108 */ 02109 MagickExport Image *ReferenceImage(Image *image) 02110 { 02111 assert(image != (Image *) NULL); 02112 if (image->debug != MagickFalse) 02113 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"..."); 02114 assert(image->signature == MagickSignature); 02115 LockSemaphoreInfo(image->semaphore); 02116 image->reference_count++; 02117 UnlockSemaphoreInfo(image->semaphore); 02118 return(image); 02119 } 02120 02121 /* 02122 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 02123 % % 02124 % % 02125 % % 02126 % R e s e t I m a g e P a g e % 02127 % % 02128 % % 02129 % % 02130 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 02131 % 02132 % ResetImagePage() resets the image page canvas and position. 02133 % 02134 % The format of the ResetImagePage method is: 02135 % 02136 % MagickBooleanType ResetImagePage(Image *image,const char *page) 02137 % 02138 % A description of each parameter follows: 02139 % 02140 % o image: the image. 02141 % 02142 % o page: the relative page specification. 02143 % 02144 */ 02145 MagickExport MagickBooleanType ResetImagePage(Image *image,const char *page) 02146 { 02147 MagickStatusType 02148 flags; 02149 02150 RectangleInfo 02151 geometry; 02152 02153 assert(image != (Image *) NULL); 02154 assert(image->signature == MagickSignature); 02155 if (image->debug != MagickFalse) 02156 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename); 02157 flags=ParseAbsoluteGeometry(page,&geometry); 02158 if ((flags & WidthValue) != 0) 02159 { 02160 if ((flags & HeightValue) == 0) 02161 geometry.height=geometry.width; 02162 image->page.width=geometry.width; 02163 image->page.height=geometry.height; 02164 } 02165 if ((flags & AspectValue) != 0) 02166 { 02167 if ((flags & XValue) != 0) 02168 image->page.x+=geometry.x; 02169 if ((flags & YValue) != 0) 02170 image->page.y+=geometry.y; 02171 } 02172 else 02173 { 02174 if ((flags & XValue) != 0) 02175 { 02176 image->page.x=geometry.x; 02177 if ((image->page.width == 0) && (geometry.x > 0)) 02178 image->page.width=image->columns+geometry.x; 02179 } 02180 if ((flags & YValue) != 0) 02181 { 02182 image->page.y=geometry.y; 02183 if ((image->page.height == 0) && (geometry.y > 0)) 02184 image->page.height=image->rows+geometry.y; 02185 } 02186 } 02187 return(MagickTrue); 02188 } 02189 02190 /* 02191 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 02192 % % 02193 % % 02194 % % 02195 % S e p a r a t e I m a g e % 02196 % % 02197 % % 02198 % % 02199 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 02200 % 02201 % SeparateImage() separates a channel from the image and returns it as a 02202 % grayscale image. 02203 % 02204 % The format of the SeparateImage method is: 02205 % 02206 % Image *SeparateImage(const Image *image,const ChannelType channel, 02207 % ExceptionInfo *exception) 02208 % 02209 % A description of each parameter follows: 02210 % 02211 % o image: the image. 02212 % 02213 % o channel: the image channel. 02214 % 02215 % o exception: return any errors or warnings in this structure. 02216 % 02217 */ 02218 MagickExport Image *SeparateImage(const Image *image, 02219 const ChannelType channel_type,ExceptionInfo *exception) 02220 { 02221 #define GetChannelBit(mask,bit) (((size_t) (mask) >> (size_t) (bit)) & 0x01) 02222 #define SeparateImageTag "Separate/Image" 02223 02224 CacheView 02225 *image_view, 02226 *separate_view; 02227 02228 Image 02229 *separate_image; 02230 02231 MagickBooleanType 02232 status; 02233 02234 MagickOffsetType 02235 progress; 02236 02237 ssize_t 02238 y; 02239 02240 /* 02241 Initialize spread image attributes. 02242 */ 02243 assert(image != (Image *) NULL); 02244 assert(image->signature == MagickSignature); 02245 if (image->debug != MagickFalse) 02246 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename); 02247 assert(exception != (ExceptionInfo *) NULL); 02248 assert(exception->signature == MagickSignature); 02249 separate_image=CloneImage(image,image->columns,image->rows,MagickTrue, 02250 exception); 02251 if (separate_image == (Image *) NULL) 02252 return((Image *) NULL); 02253 if (SetImageStorageClass(separate_image,DirectClass,exception) == MagickFalse) 02254 { 02255 separate_image=DestroyImage(separate_image); 02256 return((Image *) NULL); 02257 } 02258 separate_image->colorspace=GRAYColorspace; 02259 /* 02260 Separate image. 02261 */ 02262 status=MagickTrue; 02263 progress=0; 02264 image_view=AcquireCacheView(image); 02265 separate_view=AcquireCacheView(separate_image); 02266 #if defined(MAGICKCORE_OPENMP_SUPPORT) 02267 #pragma omp parallel for schedule(static) shared(progress,status) 02268 #endif 02269 for (y=0; y < (ssize_t) image->rows; y++) 02270 { 02271 register const Quantum 02272 *restrict p; 02273 02274 register Quantum 02275 *restrict q; 02276 02277 register ssize_t 02278 x; 02279 02280 if (status == MagickFalse) 02281 continue; 02282 p=GetCacheViewVirtualPixels(image_view,0,y,image->columns,1,exception); 02283 q=QueueCacheViewAuthenticPixels(separate_view,0,y,separate_image->columns,1, 02284 exception); 02285 if ((p == (const Quantum *) NULL) || (q == (Quantum *) NULL)) 02286 { 02287 status=MagickFalse; 02288 continue; 02289 } 02290 for (x=0; x < (ssize_t) image->columns; x++) 02291 { 02292 register ssize_t 02293 i; 02294 02295 if (GetPixelMask(image,p) != 0) 02296 { 02297 p+=GetPixelChannels(image); 02298 q+=GetPixelChannels(separate_image); 02299 continue; 02300 } 02301 SetPixelChannel(separate_image,GrayPixelChannel,0,q); 02302 for (i=0; i < (ssize_t) GetPixelChannels(image); i++) 02303 { 02304 PixelChannel 02305 channel; 02306 02307 PixelTrait 02308 traits; 02309 02310 channel=GetPixelChannelMapChannel(image,i); 02311 traits=GetPixelChannelMapTraits(image,channel); 02312 if ((traits == UndefinedPixelTrait) || 02313 (GetChannelBit(channel_type,channel) == 0)) 02314 continue; 02315 SetPixelChannel(separate_image,GrayPixelChannel,p[i],q); 02316 } 02317 p+=GetPixelChannels(image); 02318 q+=GetPixelChannels(separate_image); 02319 } 02320 if (SyncCacheViewAuthenticPixels(separate_view,exception) == MagickFalse) 02321 status=MagickFalse; 02322 if (image->progress_monitor != (MagickProgressMonitor) NULL) 02323 { 02324 MagickBooleanType 02325 proceed; 02326 02327 #if defined(MAGICKCORE_OPENMP_SUPPORT) 02328 #pragma omp critical (MagickCore_SeparateImage) 02329 #endif 02330 proceed=SetImageProgress(image,SeparateImageTag,progress++,image->rows); 02331 if (proceed == MagickFalse) 02332 status=MagickFalse; 02333 } 02334 } 02335 separate_view=DestroyCacheView(separate_view); 02336 image_view=DestroyCacheView(image_view); 02337 return(separate_image); 02338 } 02339 02340 /* 02341 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 02342 % % 02343 % % 02344 % % 02345 % S e p a r a t e I m a g e s % 02346 % % 02347 % % 02348 % % 02349 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 02350 % 02351 % SeparateImages() returns a separate grayscale image for each channel 02352 % specified. 02353 % 02354 % The format of the SeparateImages method is: 02355 % 02356 % MagickBooleanType SeparateImages(const Image *image, 02357 % ExceptionInfo *exception) 02358 % 02359 % A description of each parameter follows: 02360 % 02361 % o image: the image. 02362 % 02363 % o exception: return any errors or warnings in this structure. 02364 % 02365 */ 02366 MagickExport Image *SeparateImages(const Image *image,ExceptionInfo *exception) 02367 { 02368 Image 02369 *images, 02370 *separate_image; 02371 02372 register ssize_t 02373 i; 02374 02375 assert(image != (Image *) NULL); 02376 assert(image->signature == MagickSignature); 02377 if (image->debug != MagickFalse) 02378 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename); 02379 images=NewImageList(); 02380 for (i=0; i < (ssize_t) GetPixelChannels(image); i++) 02381 { 02382 PixelChannel 02383 channel; 02384 02385 PixelTrait 02386 traits; 02387 02388 channel=GetPixelChannelMapChannel(image,i); 02389 traits=GetPixelChannelMapTraits(image,channel); 02390 if ((traits == UndefinedPixelTrait) || 02391 ((traits & UpdatePixelTrait) == 0)) 02392 continue; 02393 separate_image=SeparateImage(image,(ChannelType) (1 << channel),exception); 02394 if (separate_image != (Image *) NULL) 02395 AppendImageToList(&images,separate_image); 02396 } 02397 return(images); 02398 } 02399 02400 /* 02401 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 02402 % % 02403 % % 02404 % % 02405 % S e t I m a g e A l p h a C h a n n e l % 02406 % % 02407 % % 02408 % % 02409 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 02410 % 02411 % SetImageAlphaChannel() activates, deactivates, resets, or sets the alpha 02412 % channel. 02413 % 02414 % The format of the SetImageAlphaChannel method is: 02415 % 02416 % MagickBooleanType SetImageAlphaChannel(Image *image, 02417 % const AlphaChannelType alpha_type,ExceptionInfo *exception) 02418 % 02419 % A description of each parameter follows: 02420 % 02421 % o image: the image. 02422 % 02423 % o alpha_type: The alpha channel type: ActivateAlphaChannel, 02424 % CopyAlphaChannel, DeactivateAlphaChannel, ExtractAlphaChannel, 02425 % OpaqueAlphaChannel, SetAlphaChannel, ShapeAlphaChannel, and 02426 % TransparentAlphaChannel. 02427 % 02428 % o exception: return any errors or warnings in this structure. 02429 % 02430 */ 02431 02432 static inline void FlattenPixelInfo(const Image *image,const PixelInfo *p, 02433 const MagickRealType alpha,const Quantum *q,const MagickRealType beta, 02434 Quantum *composite) 02435 { 02436 MagickRealType 02437 Da, 02438 gamma, 02439 Sa; 02440 02441 register ssize_t 02442 i; 02443 02444 /* 02445 Compose pixel p over pixel q with the given alpha. 02446 */ 02447 Sa=QuantumScale*alpha; 02448 Da=QuantumScale*beta, 02449 gamma=Sa*(-Da)+Sa+Da; 02450 gamma=1.0/(gamma <= MagickEpsilon ? 1.0 : gamma); 02451 for (i=0; i < (ssize_t) GetPixelChannels(image); i++) 02452 { 02453 PixelChannel 02454 channel; 02455 02456 PixelTrait 02457 traits; 02458 02459 channel=GetPixelChannelMapChannel(image,i); 02460 traits=GetPixelChannelMapTraits(image,channel); 02461 if (traits == UndefinedPixelTrait) 02462 continue; 02463 switch (channel) 02464 { 02465 case RedPixelChannel: 02466 { 02467 composite[i]=ClampToQuantum(gamma*MagickOver_((MagickRealType) q[i], 02468 beta,(MagickRealType) p->red,alpha)); 02469 break; 02470 } 02471 case GreenPixelChannel: 02472 { 02473 composite[i]=ClampToQuantum(gamma*MagickOver_((MagickRealType) q[i], 02474 beta,(MagickRealType) p->green,alpha)); 02475 break; 02476 } 02477 case BluePixelChannel: 02478 { 02479 composite[i]=ClampToQuantum(gamma*MagickOver_((MagickRealType) q[i], 02480 beta,(MagickRealType) p->blue,alpha)); 02481 break; 02482 } 02483 case BlackPixelChannel: 02484 { 02485 composite[i]=ClampToQuantum(gamma*MagickOver_((MagickRealType) q[i], 02486 beta,(MagickRealType) p->black,alpha)); 02487 break; 02488 } 02489 case AlphaPixelChannel: 02490 { 02491 composite[i]=ClampToQuantum(QuantumRange*(Sa*(-Da)+Sa+Da)); 02492 break; 02493 } 02494 default: 02495 break; 02496 } 02497 } 02498 } 02499 02500 MagickExport MagickBooleanType SetImageAlphaChannel(Image *image, 02501 const AlphaChannelType alpha_type,ExceptionInfo *exception) 02502 { 02503 MagickBooleanType 02504 status; 02505 02506 assert(image != (Image *) NULL); 02507 if (image->debug != MagickFalse) 02508 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"..."); 02509 assert(image->signature == MagickSignature); 02510 status=MagickTrue; 02511 switch (alpha_type) 02512 { 02513 case ActivateAlphaChannel: 02514 { 02515 image->matte=MagickTrue; 02516 break; 02517 } 02518 case BackgroundAlphaChannel: 02519 { 02520 CacheView 02521 *image_view; 02522 02523 ssize_t 02524 y; 02525 02526 /* 02527 Set transparent pixels to background color. 02528 */ 02529 if (image->matte == MagickFalse) 02530 break; 02531 if (SetImageStorageClass(image,DirectClass,exception) == MagickFalse) 02532 break; 02533 image_view=AcquireCacheView(image); 02534 #if defined(MAGICKCORE_OPENMP_SUPPORT) 02535 #pragma omp parallel for schedule(static,4) shared(status) 02536 #endif 02537 for (y=0; y < (ssize_t) image->rows; y++) 02538 { 02539 register Quantum 02540 *restrict q; 02541 02542 register ssize_t 02543 x; 02544 02545 if (status == MagickFalse) 02546 continue; 02547 q=GetCacheViewAuthenticPixels(image_view,0,y,image->columns,1, 02548 exception); 02549 if (q == (Quantum *) NULL) 02550 { 02551 status=MagickFalse; 02552 continue; 02553 } 02554 for (x=0; x < (ssize_t) image->columns; x++) 02555 { 02556 if (GetPixelAlpha(image,q) == TransparentAlpha) 02557 SetPixelInfoPixel(image,&image->background_color,q); 02558 q+=GetPixelChannels(image); 02559 } 02560 if (SyncCacheViewAuthenticPixels(image_view,exception) == MagickFalse) 02561 status=MagickFalse; 02562 } 02563 image_view=DestroyCacheView(image_view); 02564 return(status); 02565 } 02566 case CopyAlphaChannel: 02567 case ShapeAlphaChannel: 02568 { 02569 /* 02570 Copy pixel intensity to the alpha channel. 02571 */ 02572 status=CompositeImage(image,IntensityCompositeOp,image,0,0,exception); 02573 if (alpha_type == ShapeAlphaChannel) 02574 (void) LevelImageColors(image,&image->background_color, 02575 &image->background_color,MagickTrue,exception); 02576 break; 02577 } 02578 case DeactivateAlphaChannel: 02579 { 02580 image->matte=MagickFalse; 02581 break; 02582 } 02583 case ExtractAlphaChannel: 02584 { 02585 status=CompositeImage(image,AlphaCompositeOp,image,0,0,exception); 02586 image->matte=MagickFalse; 02587 break; 02588 } 02589 case OpaqueAlphaChannel: 02590 { 02591 status=SetImageAlpha(image,OpaqueAlpha,exception); 02592 break; 02593 } 02594 case RemoveAlphaChannel: 02595 { 02596 CacheView 02597 *image_view; 02598 02599 ssize_t 02600 y; 02601 02602 /* 02603 Remove transparency. 02604 */ 02605 if (image->matte == MagickFalse) 02606 break; 02607 if (SetImageStorageClass(image,DirectClass,exception) == MagickFalse) 02608 break; 02609 image_view=AcquireCacheView(image); 02610 #if defined(MAGICKCORE_OPENMP_SUPPORT) 02611 #pragma omp parallel for schedule(static,4) shared(status) 02612 #endif 02613 for (y=0; y < (ssize_t) image->rows; y++) 02614 { 02615 register Quantum 02616 *restrict q; 02617 02618 register ssize_t 02619 x; 02620 02621 if (status == MagickFalse) 02622 continue; 02623 q=GetCacheViewAuthenticPixels(image_view,0,y,image->columns,1, 02624 exception); 02625 if (q == (Quantum *) NULL) 02626 { 02627 status=MagickFalse; 02628 continue; 02629 } 02630 for (x=0; x < (ssize_t) image->columns; x++) 02631 { 02632 FlattenPixelInfo(image,&image->background_color, 02633 image->background_color.alpha,q,(MagickRealType) 02634 GetPixelAlpha(image,q),q); 02635 q+=GetPixelChannels(image); 02636 } 02637 if (SyncCacheViewAuthenticPixels(image_view,exception) == MagickFalse) 02638 status=MagickFalse; 02639 } 02640 image_view=DestroyCacheView(image_view); 02641 image->matte=image->background_color.matte; 02642 return(status); 02643 } 02644 case SetAlphaChannel: 02645 { 02646 if (image->matte == MagickFalse) 02647 status=SetImageAlpha(image,OpaqueAlpha,exception); 02648 break; 02649 } 02650 case TransparentAlphaChannel: 02651 { 02652 status=SetImageAlpha(image,TransparentAlpha,exception); 02653 break; 02654 } 02655 case UndefinedAlphaChannel: 02656 break; 02657 } 02658 if (status == MagickFalse) 02659 return(status); 02660 return(SyncImagePixelCache(image,exception)); 02661 } 02662 02663 /* 02664 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 02665 % % 02666 % % 02667 % % 02668 % S e t I m a g e B a c k g r o u n d C o l o r % 02669 % % 02670 % % 02671 % % 02672 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 02673 % 02674 % SetImageBackgroundColor() initializes the image pixels to the image 02675 % background color. The background color is defined by the background_color 02676 % member of the image structure. 02677 % 02678 % The format of the SetImage method is: 02679 % 02680 % MagickBooleanType SetImageBackgroundColor(Image *image, 02681 % ExceptionInfo *exception) 02682 % 02683 % A description of each parameter follows: 02684 % 02685 % o image: the image. 02686 % 02687 % o exception: return any errors or warnings in this structure. 02688 % 02689 */ 02690 MagickExport MagickBooleanType SetImageBackgroundColor(Image *image, 02691 ExceptionInfo *exception) 02692 { 02693 CacheView 02694 *image_view; 02695 02696 MagickBooleanType 02697 status; 02698 02699 ssize_t 02700 y; 02701 02702 assert(image != (Image *) NULL); 02703 if (image->debug != MagickFalse) 02704 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"..."); 02705 assert(image->signature == MagickSignature); 02706 if (SetImageStorageClass(image,DirectClass,exception) == MagickFalse) 02707 return(MagickFalse); 02708 if (image->background_color.matte != MagickFalse) 02709 image->matte=MagickTrue; 02710 /* 02711 Set image background color. 02712 */ 02713 status=MagickTrue; 02714 image_view=AcquireCacheView(image); 02715 for (y=0; y < (ssize_t) image->rows; y++) 02716 { 02717 register Quantum 02718 *restrict q; 02719 02720 register ssize_t 02721 x; 02722 02723 if (status == MagickFalse) 02724 continue; 02725 q=QueueCacheViewAuthenticPixels(image_view,0,y,image->columns,1,exception); 02726 if (q == (Quantum *) NULL) 02727 { 02728 status=MagickFalse; 02729 continue; 02730 } 02731 for (x=0; x < (ssize_t) image->columns; x++) 02732 { 02733 SetPixelInfoPixel(image,&image->background_color,q); 02734 q+=GetPixelChannels(image); 02735 } 02736 if (SyncCacheViewAuthenticPixels(image_view,exception) == MagickFalse) 02737 status=MagickFalse; 02738 } 02739 image_view=DestroyCacheView(image_view); 02740 return(status); 02741 } 02742 02743 /* 02744 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 02745 % % 02746 % % 02747 % % 02748 % S e t I m a g e C o l o r % 02749 % % 02750 % % 02751 % % 02752 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 02753 % 02754 % SetImageColor() set the entire image canvas to the specified color. 02755 % 02756 % The format of the SetImageColor method is: 02757 % 02758 % MagickBooleanType SetImageColor(Image *image,const PixelInfo *color, 02759 % ExeptionInfo *exception) 02760 % 02761 % A description of each parameter follows: 02762 % 02763 % o image: the image. 02764 % 02765 % o background: the image color. 02766 % 02767 % o exception: return any errors or warnings in this structure. 02768 % 02769 */ 02770 MagickExport MagickBooleanType SetImageColor(Image *image, 02771 const PixelInfo *color,ExceptionInfo *exception) 02772 { 02773 CacheView 02774 *image_view; 02775 02776 MagickBooleanType 02777 status; 02778 02779 ssize_t 02780 y; 02781 02782 assert(image != (Image *) NULL); 02783 if (image->debug != MagickFalse) 02784 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"..."); 02785 assert(image->signature == MagickSignature); 02786 assert(color != (const PixelInfo *) NULL); 02787 image->colorspace=color->colorspace; 02788 image->matte=color->matte; 02789 image->fuzz=color->fuzz; 02790 image->depth=color->depth; 02791 status=MagickTrue; 02792 image_view=AcquireCacheView(image); 02793 #if defined(MAGICKCORE_OPENMP_SUPPORT) 02794 #pragma omp parallel for schedule(static,4) shared(status) 02795 #endif 02796 for (y=0; y < (ssize_t) image->rows; y++) 02797 { 02798 register Quantum 02799 *restrict q; 02800 02801 register ssize_t 02802 x; 02803 02804 if (status == MagickFalse) 02805 continue; 02806 q=QueueCacheViewAuthenticPixels(image_view,0,y,image->columns,1,exception); 02807 if (q == (Quantum *) NULL) 02808 { 02809 status=MagickFalse; 02810 continue; 02811 } 02812 for (x=0; x < (ssize_t) image->columns; x++) 02813 { 02814 SetPixelInfoPixel(image,color,q); 02815 q+=GetPixelChannels(image); 02816 } 02817 if (SyncCacheViewAuthenticPixels(image_view,exception) == MagickFalse) 02818 status=MagickFalse; 02819 } 02820 image_view=DestroyCacheView(image_view); 02821 return(status); 02822 } 02823 02824 /* 02825 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 02826 % % 02827 % % 02828 % % 02829 % S e t I m a g e S t o r a g e C l a s s % 02830 % % 02831 % % 02832 % % 02833 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 02834 % 02835 % SetImageStorageClass() sets the image class: DirectClass for true color 02836 % images or PseudoClass for colormapped images. 02837 % 02838 % The format of the SetImageStorageClass method is: 02839 % 02840 % MagickBooleanType SetImageStorageClass(Image *image, 02841 % const ClassType storage_class,ExceptionInfo *exception) 02842 % 02843 % A description of each parameter follows: 02844 % 02845 % o image: the image. 02846 % 02847 % o storage_class: The image class. 02848 % 02849 % o exception: return any errors or warnings in this structure. 02850 % 02851 */ 02852 MagickExport MagickBooleanType SetImageStorageClass(Image *image, 02853 const ClassType storage_class,ExceptionInfo *exception) 02854 { 02855 image->storage_class=storage_class; 02856 return(SyncImagePixelCache(image,exception)); 02857 } 02858 02859 /* 02860 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 02861 % % 02862 % % 02863 % % 02864 % S e t I m a g e E x t e n t % 02865 % % 02866 % % 02867 % % 02868 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 02869 % 02870 % SetImageExtent() sets the image size (i.e. columns & rows). 02871 % 02872 % The format of the SetImageExtent method is: 02873 % 02874 % MagickBooleanType SetImageExtent(Image *image,const size_t columns, 02875 % const size_t rows,ExceptionInfo *exception) 02876 % 02877 % A description of each parameter follows: 02878 % 02879 % o image: the image. 02880 % 02881 % o columns: The image width in pixels. 02882 % 02883 % o rows: The image height in pixels. 02884 % 02885 % o exception: return any errors or warnings in this structure. 02886 % 02887 */ 02888 MagickExport MagickBooleanType SetImageExtent(Image *image,const size_t columns, 02889 const size_t rows,ExceptionInfo *exception) 02890 { 02891 if ((columns == 0) || (rows == 0)) 02892 return(MagickFalse); 02893 image->columns=columns; 02894 image->rows=rows; 02895 return(SyncImagePixelCache(image,exception)); 02896 } 02897 02898 /* 02899 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 02900 % % 02901 % % 02902 % % 02903 + S e t I m a g e I n f o % 02904 % % 02905 % % 02906 % % 02907 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 02908 % 02909 % SetImageInfo() initializes the `magick' field of the ImageInfo structure. 02910 % It is set to a type of image format based on the prefix or suffix of the 02911 % filename. For example, `ps:image' returns PS indicating a Postscript image. 02912 % JPEG is returned for this filename: `image.jpg'. The filename prefix has 02913 % precendence over the suffix. Use an optional index enclosed in brackets 02914 % after a file name to specify a desired scene of a multi-resolution image 02915 % format like Photo CD (e.g. img0001.pcd[4]). A True (non-zero) return value 02916 % indicates success. 02917 % 02918 % The format of the SetImageInfo method is: 02919 % 02920 % MagickBooleanType SetImageInfo(ImageInfo *image_info, 02921 % const unsigned int frames,ExceptionInfo *exception) 02922 % 02923 % A description of each parameter follows: 02924 % 02925 % o image_info: the image info. 02926 % 02927 % o frames: the number of images you intend to write. 02928 % 02929 % o exception: return any errors or warnings in this structure. 02930 % 02931 */ 02932 MagickExport MagickBooleanType SetImageInfo(ImageInfo *image_info, 02933 const unsigned int frames,ExceptionInfo *exception) 02934 { 02935 char 02936 extension[MaxTextExtent], 02937 filename[MaxTextExtent], 02938 magic[MaxTextExtent], 02939 *q, 02940 subimage[MaxTextExtent]; 02941 02942 const MagicInfo 02943 *magic_info; 02944 02945 const MagickInfo 02946 *magick_info; 02947 02948 ExceptionInfo 02949 *sans_exception; 02950 02951 Image 02952 *image; 02953 02954 MagickBooleanType 02955 status; 02956 02957 register const char 02958 *p; 02959 02960 ssize_t 02961 count; 02962 02963 unsigned char 02964 magick[2*MaxTextExtent]; 02965 02966 /* 02967 Look for 'image.format' in filename. 02968 */ 02969 assert(image_info != (ImageInfo *) NULL); 02970 assert(image_info->signature == MagickSignature); 02971 if (image_info->debug != MagickFalse) 02972 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s", 02973 image_info->filename); 02974 *subimage='\0'; 02975 if (frames == 0) 02976 { 02977 GetPathComponent(image_info->filename,SubimagePath,subimage); 02978 if (*subimage != '\0') 02979 { 02980 /* 02981 Look for scene specification (e.g. img0001.pcd[4]). 02982 */ 02983 if (IsSceneGeometry(subimage,MagickFalse) == MagickFalse) 02984 { 02985 if (IsGeometry(subimage) != MagickFalse) 02986 (void) CloneString(&image_info->extract,subimage); 02987 } 02988 else 02989 { 02990 size_t 02991 first, 02992 last; 02993 02994 (void) CloneString(&image_info->scenes,subimage); 02995 image_info->scene=StringToUnsignedLong(image_info->scenes); 02996 image_info->number_scenes=image_info->scene; 02997 p=image_info->scenes; 02998 for (q=(char *) image_info->scenes; *q != '\0'; p++) 02999 { 03000 while ((isspace((int) ((unsigned char) *p)) != 0) || 03001 (*p == ',')) 03002 p++; 03003 first=(size_t) strtol(p,&q,10); 03004 last=first; 03005 while (isspace((int) ((unsigned char) *q)) != 0) 03006 q++; 03007 if (*q == '-') 03008 last=(size_t) strtol(q+1,&q,10); 03009 if (first > last) 03010 Swap(first,last); 03011 if (first < image_info->scene) 03012 image_info->scene=first; 03013 if (last > image_info->number_scenes) 03014 image_info->number_scenes=last; 03015 p=q; 03016 } 03017 image_info->number_scenes-=image_info->scene-1; 03018 } 03019 } 03020 } 03021 *extension='\0'; 03022 GetPathComponent(image_info->filename,ExtensionPath,extension); 03023 #if defined(MAGICKCORE_ZLIB_DELEGATE) 03024 if (*extension != '\0') 03025 if ((LocaleCompare(extension,"gz") == 0) || 03026 (LocaleCompare(extension,"Z") == 0) || 03027 (LocaleCompare(extension,"svgz") == 0) || 03028 (LocaleCompare(extension,"wmz") == 0)) 03029 { 03030 char 03031 path[MaxTextExtent]; 03032 03033 (void) CopyMagickString(path,image_info->filename,MaxTextExtent); 03034 path[strlen(path)-strlen(extension)-1]='\0'; 03035 GetPathComponent(path,ExtensionPath,extension); 03036 } 03037 #endif 03038 #if defined(MAGICKCORE_BZLIB_DELEGATE) 03039 if (*extension != '\0') 03040 if (LocaleCompare(extension,"bz2") == 0) 03041 { 03042 char 03043 path[MaxTextExtent]; 03044 03045 (void) CopyMagickString(path,image_info->filename,MaxTextExtent); 03046 path[strlen(path)-strlen(extension)-1]='\0'; 03047 GetPathComponent(path,ExtensionPath,extension); 03048 } 03049 #endif 03050 image_info->affirm=MagickFalse; 03051 sans_exception=AcquireExceptionInfo(); 03052 if (*extension != '\0') 03053 { 03054 MagickFormatType 03055 format_type; 03056 03057 register ssize_t 03058 i; 03059 03060 static const char 03061 *format_type_formats[] = 03062 { 03063 "AUTOTRACE", 03064 "BROWSE", 03065 "DCRAW", 03066 "EDIT", 03067 "EPHEMERAL", 03068 "LAUNCH", 03069 "MPEG:DECODE", 03070 "MPEG:ENCODE", 03071 "PRINT", 03072 "PS:ALPHA", 03073 "PS:CMYK", 03074 "PS:COLOR", 03075 "PS:GRAY", 03076 "PS:MONO", 03077 "SCAN", 03078 "SHOW", 03079 "WIN", 03080 (char *) NULL 03081 }; 03082 03083 /* 03084 User specified image format. 03085 */ 03086 (void) CopyMagickString(magic,extension,MaxTextExtent); 03087 LocaleUpper(magic); 03088 /* 03089 Look for explicit image formats. 03090 */ 03091 format_type=UndefinedFormatType; 03092 i=0; 03093 while ((format_type == UndefinedFormatType) && 03094 (format_type_formats[i] != (char *) NULL)) 03095 { 03096 if ((*magic == *format_type_formats[i]) && 03097 (LocaleCompare(magic,format_type_formats[i]) == 0)) 03098 format_type=ExplicitFormatType; 03099 i++; 03100 } 03101 magick_info=GetMagickInfo(magic,sans_exception); 03102 if ((magick_info != (const MagickInfo *) NULL) && 03103 (magick_info->format_type != UndefinedFormatType)) 03104 format_type=magick_info->format_type; 03105 if (format_type == UndefinedFormatType) 03106 (void) CopyMagickString(image_info->magick,magic,MaxTextExtent); 03107 else 03108 if (format_type == ExplicitFormatType) 03109 { 03110 image_info->affirm=MagickTrue; 03111 (void) CopyMagickString(image_info->magick,magic,MaxTextExtent); 03112 } 03113 if (LocaleCompare(magic,"RGB") == 0) 03114 image_info->affirm=MagickFalse; /* maybe SGI disguised as RGB */ 03115 } 03116 /* 03117 Look for explicit 'format:image' in filename. 03118 */ 03119 *magic='\0'; 03120 GetPathComponent(image_info->filename,MagickPath,magic); 03121 if (*magic == '\0') 03122 (void) CopyMagickString(magic,image_info->magick,MaxTextExtent); 03123 else 03124 { 03125 /* 03126 User specified image format. 03127 */ 03128 LocaleUpper(magic); 03129 if (IsMagickConflict(magic) == MagickFalse) 03130 { 03131 (void) CopyMagickString(image_info->magick,magic,MaxTextExtent); 03132 if (LocaleCompare(magic,"EPHEMERAL") != 0) 03133 image_info->affirm=MagickTrue; 03134 else 03135 image_info->temporary=MagickTrue; 03136 } 03137 } 03138 magick_info=GetMagickInfo(magic,sans_exception); 03139 sans_exception=DestroyExceptionInfo(sans_exception); 03140 if ((magick_info == (const MagickInfo *) NULL) || 03141 (GetMagickEndianSupport(magick_info) == MagickFalse)) 03142 image_info->endian=UndefinedEndian; 03143 GetPathComponent(image_info->filename,CanonicalPath,filename); 03144 (void) CopyMagickString(image_info->filename,filename,MaxTextExtent); 03145 if ((image_info->adjoin != MagickFalse) && (frames > 1)) 03146 { 03147 /* 03148 Test for multiple image support (e.g. image%02d.png). 03149 */ 03150 (void) InterpretImageFilename(image_info,(Image *) NULL, 03151 image_info->filename,(int) image_info->scene,filename,exception); 03152 if ((LocaleCompare(filename,image_info->filename) != 0) && 03153 (strchr(filename,'%') == (char *) NULL)) 03154 image_info->adjoin=MagickFalse; 03155 } 03156 if ((image_info->adjoin != MagickFalse) && (frames > 0)) 03157 { 03158 /* 03159 Some image formats do not support multiple frames per file. 03160 */ 03161 magick_info=GetMagickInfo(magic,exception); 03162 if (magick_info != (const MagickInfo *) NULL) 03163 if (GetMagickAdjoin(magick_info) == MagickFalse) 03164 image_info->adjoin=MagickFalse; 03165 } 03166 if (image_info->affirm != MagickFalse) 03167 return(MagickTrue); 03168 if (frames == 0) 03169 { 03170 /* 03171 Determine the image format from the first few bytes of the file. 03172 */ 03173 image=AcquireImage(image_info,exception); 03174 (void) CopyMagickString(image->filename,image_info->filename, 03175 MaxTextExtent); 03176 status=OpenBlob(image_info,image,ReadBinaryBlobMode,exception); 03177 if (status == MagickFalse) 03178 { 03179 image=DestroyImage(image); 03180 return(MagickFalse); 03181 } 03182 if ((IsBlobSeekable(image) == MagickFalse) || 03183 (IsBlobExempt(image) != MagickFalse)) 03184 { 03185 /* 03186 Copy standard input or pipe to temporary file. 03187 */ 03188 *filename='\0'; 03189 status=ImageToFile(image,filename,exception); 03190 (void) CloseBlob(image); 03191 if (status == MagickFalse) 03192 { 03193 image=DestroyImage(image); 03194 return(MagickFalse); 03195 } 03196 SetImageInfoFile(image_info,(FILE *) NULL); 03197 (void) CopyMagickString(image->filename,filename,MaxTextExtent); 03198 status=OpenBlob(image_info,image,ReadBinaryBlobMode,exception); 03199 if (status == MagickFalse) 03200 { 03201 image=DestroyImage(image); 03202 return(MagickFalse); 03203 } 03204 (void) CopyMagickString(image_info->filename,filename,MaxTextExtent); 03205 image_info->temporary=MagickTrue; 03206 } 03207 (void) ResetMagickMemory(magick,0,sizeof(magick)); 03208 count=ReadBlob(image,2*MaxTextExtent,magick); 03209 (void) CloseBlob(image); 03210 image=DestroyImage(image); 03211 /* 03212 Check magic.xml configuration file. 03213 */ 03214 sans_exception=AcquireExceptionInfo(); 03215 magic_info=GetMagicInfo(magick,(size_t) count,sans_exception); 03216 if ((magic_info != (const MagicInfo *) NULL) && 03217 (GetMagicName(magic_info) != (char *) NULL)) 03218 { 03219 (void) CopyMagickString(image_info->magick,GetMagicName(magic_info), 03220 MaxTextExtent); 03221 magick_info=GetMagickInfo(image_info->magick,sans_exception); 03222 if ((magick_info == (const MagickInfo *) NULL) || 03223 (GetMagickEndianSupport(magick_info) == MagickFalse)) 03224 image_info->endian=UndefinedEndian; 03225 sans_exception=DestroyExceptionInfo(sans_exception); 03226 return(MagickTrue); 03227 } 03228 magick_info=GetMagickInfo(image_info->magick,sans_exception); 03229 if ((magick_info == (const MagickInfo *) NULL) || 03230 (GetMagickEndianSupport(magick_info) == MagickFalse)) 03231 image_info->endian=UndefinedEndian; 03232 sans_exception=DestroyExceptionInfo(sans_exception); 03233 } 03234 return(MagickTrue); 03235 } 03236 03237 /* 03238 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 03239 % % 03240 % % 03241 % % 03242 % S e t I m a g e I n f o B l o b % 03243 % % 03244 % % 03245 % % 03246 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 03247 % 03248 % SetImageInfoBlob() sets the image info blob member. 03249 % 03250 % The format of the SetImageInfoBlob method is: 03251 % 03252 % void SetImageInfoBlob(ImageInfo *image_info,const void *blob, 03253 % const size_t length) 03254 % 03255 % A description of each parameter follows: 03256 % 03257 % o image_info: the image info. 03258 % 03259 % o blob: the blob. 03260 % 03261 % o length: the blob length. 03262 % 03263 */ 03264 MagickExport void SetImageInfoBlob(ImageInfo *image_info,const void *blob, 03265 const size_t length) 03266 { 03267 assert(image_info != (ImageInfo *) NULL); 03268 assert(image_info->signature == MagickSignature); 03269 if (image_info->debug != MagickFalse) 03270 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s", 03271 image_info->filename); 03272 image_info->blob=(void *) blob; 03273 image_info->length=length; 03274 } 03275 03276 /* 03277 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 03278 % % 03279 % % 03280 % % 03281 % S e t I m a g e I n f o F i l e % 03282 % % 03283 % % 03284 % % 03285 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 03286 % 03287 % SetImageInfoFile() sets the image info file member. 03288 % 03289 % The format of the SetImageInfoFile method is: 03290 % 03291 % void SetImageInfoFile(ImageInfo *image_info,FILE *file) 03292 % 03293 % A description of each parameter follows: 03294 % 03295 % o image_info: the image info. 03296 % 03297 % o file: the file. 03298 % 03299 */ 03300 MagickExport void SetImageInfoFile(ImageInfo *image_info,FILE *file) 03301 { 03302 assert(image_info != (ImageInfo *) NULL); 03303 assert(image_info->signature == MagickSignature); 03304 if (image_info->debug != MagickFalse) 03305 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s", 03306 image_info->filename); 03307 image_info->file=file; 03308 } 03309 03310 /* 03311 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 03312 % % 03313 % % 03314 % % 03315 % S e t I m a g e M a s k % 03316 % % 03317 % % 03318 % % 03319 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 03320 % 03321 % SetImageMask() associates a mask with the image. The mask must be the same 03322 % dimensions as the image. 03323 % 03324 % The format of the SetImageMask method is: 03325 % 03326 % MagickBooleanType SetImageMask(Image *image,const Image *mask, 03327 % ExceptionInfo *exception) 03328 % 03329 % A description of each parameter follows: 03330 % 03331 % o image: the image. 03332 % 03333 % o mask: the image mask. 03334 % 03335 % o exception: return any errors or warnings in this structure. 03336 % 03337 */ 03338 MagickExport MagickBooleanType SetImageMask(Image *image,const Image *mask, 03339 ExceptionInfo *exception) 03340 { 03341 CacheView 03342 *mask_view, 03343 *image_view; 03344 03345 MagickBooleanType 03346 status; 03347 03348 ssize_t 03349 y; 03350 03351 /* 03352 Set image mask. 03353 */ 03354 assert(image != (Image *) NULL); 03355 if (image->debug != MagickFalse) 03356 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"..."); 03357 assert(image->signature == MagickSignature); 03358 if (mask == (const Image *) NULL) 03359 { 03360 image->mask=MagickFalse; 03361 return(MagickTrue); 03362 } 03363 if ((mask->columns != image->columns) || (mask->rows != image->rows)) 03364 ThrowBinaryException(ImageError,"ImageSizeDiffers",image->filename); 03365 status=MagickTrue; 03366 image->mask=MagickTrue; 03367 image_view=AcquireCacheView(image); 03368 mask_view=AcquireCacheView(mask); 03369 for (y=0; y < (ssize_t) image->rows; y++) 03370 { 03371 register const Quantum 03372 *restrict p; 03373 03374 register Quantum 03375 *restrict q; 03376 03377 register ssize_t 03378 x; 03379 03380 if (status == MagickFalse) 03381 continue; 03382 p=GetCacheViewVirtualPixels(mask_view,0,y,mask->columns,1,exception); 03383 q=GetCacheViewAuthenticPixels(image_view,0,y,image->columns,1,exception); 03384 if ((p == (const Quantum *) NULL) || (q == (Quantum *) NULL)) 03385 { 03386 status=MagickFalse; 03387 continue; 03388 } 03389 for (x=0; x < (ssize_t) image->columns; x++) 03390 { 03391 SetPixelMask(image,GetPixelGray(mask,p),q); 03392 p+=GetPixelChannels(mask); 03393 q+=GetPixelChannels(image); 03394 } 03395 if (SyncCacheViewAuthenticPixels(image_view,exception) == MagickFalse) 03396 status=MagickFalse; 03397 } 03398 mask_view=DestroyCacheView(mask_view); 03399 image_view=DestroyCacheView(image_view); 03400 return(status); 03401 } 03402 03403 /* 03404 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 03405 % % 03406 % % 03407 % % 03408 % S e t I m a g e A l p h a % 03409 % % 03410 % % 03411 % % 03412 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 03413 % 03414 % SetImageAlpha() sets the alpha levels of the image. 03415 % 03416 % The format of the SetImageAlpha method is: 03417 % 03418 % MagickBooleanType SetImageAlpha(Image *image,const Quantum alpha, 03419 % ExceptionInfo *exception) 03420 % 03421 % A description of each parameter follows: 03422 % 03423 % o image: the image. 03424 % 03425 % o Alpha: the level of transparency: 0 is fully opaque and QuantumRange is 03426 % fully transparent. 03427 % 03428 */ 03429 MagickExport MagickBooleanType SetImageAlpha(Image *image,const Quantum alpha, 03430 ExceptionInfo *exception) 03431 { 03432 CacheView 03433 *image_view; 03434 03435 MagickBooleanType 03436 status; 03437 03438 ssize_t 03439 y; 03440 03441 assert(image != (Image *) NULL); 03442 if (image->debug != MagickFalse) 03443 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"..."); 03444 assert(image->signature == MagickSignature); 03445 image->matte=MagickTrue; 03446 status=MagickTrue; 03447 image_view=AcquireCacheView(image); 03448 #if defined(MAGICKCORE_OPENMP_SUPPORT) 03449 #pragma omp parallel for schedule(static,4) shared(status) 03450 #endif 03451 for (y=0; y < (ssize_t) image->rows; y++) 03452 { 03453 register Quantum 03454 *restrict q; 03455 03456 register ssize_t 03457 x; 03458 03459 if (status == MagickFalse) 03460 continue; 03461 q=GetCacheViewAuthenticPixels(image_view,0,y,image->columns,1,exception); 03462 if (q == (Quantum *) NULL) 03463 { 03464 status=MagickFalse; 03465 continue; 03466 } 03467 for (x=0; x < (ssize_t) image->columns; x++) 03468 { 03469 SetPixelAlpha(image,alpha,q); 03470 q+=GetPixelChannels(image); 03471 } 03472 if (SyncCacheViewAuthenticPixels(image_view,exception) == MagickFalse) 03473 status=MagickFalse; 03474 } 03475 image_view=DestroyCacheView(image_view); 03476 return(status); 03477 } 03478 03479 /* 03480 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 03481 % % 03482 % % 03483 % % 03484 % S e t I m a g e T y p e % 03485 % % 03486 % % 03487 % % 03488 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 03489 % 03490 % SetImageType() sets the type of image. Choose from these types: 03491 % 03492 % Bilevel Grayscale GrayscaleMatte 03493 % Palette PaletteMatte TrueColor 03494 % TrueColorMatte ColorSeparation ColorSeparationMatte 03495 % OptimizeType 03496 % 03497 % The format of the SetImageType method is: 03498 % 03499 % MagickBooleanType SetImageType(Image *image,const ImageType type, 03500 % ExceptionInfo *exception) 03501 % 03502 % A description of each parameter follows: 03503 % 03504 % o image: the image. 03505 % 03506 % o type: Image type. 03507 % 03508 % o exception: return any errors or warnings in this structure. 03509 % 03510 */ 03511 MagickExport MagickBooleanType SetImageType(Image *image,const ImageType type, 03512 ExceptionInfo *exception) 03513 { 03514 const char 03515 *artifact; 03516 03517 ImageInfo 03518 *image_info; 03519 03520 MagickBooleanType 03521 status; 03522 03523 QuantizeInfo 03524 *quantize_info; 03525 03526 assert(image != (Image *) NULL); 03527 if (image->debug != MagickFalse) 03528 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"..."); 03529 assert(image->signature == MagickSignature); 03530 status=MagickTrue; 03531 image_info=AcquireImageInfo(); 03532 image_info->dither=image->dither; 03533 artifact=GetImageArtifact(image,"dither"); 03534 if (artifact != (const char *) NULL) 03535 (void) SetImageOption(image_info,"dither",artifact); 03536 switch (type) 03537 { 03538 case BilevelType: 03539 { 03540 if (IsImageMonochrome(image,exception) == MagickFalse) 03541 { 03542 quantize_info=AcquireQuantizeInfo(image_info); 03543 quantize_info->number_colors=2; 03544 quantize_info->colorspace=GRAYColorspace; 03545 status=QuantizeImage(quantize_info,image,exception); 03546 quantize_info=DestroyQuantizeInfo(quantize_info); 03547 } 03548 image->matte=MagickFalse; 03549 break; 03550 } 03551 case GrayscaleType: 03552 { 03553 if (IsImageGray(image,exception) == MagickFalse) 03554 status=TransformImageColorspace(image,GRAYColorspace,exception); 03555 image->matte=MagickFalse; 03556 break; 03557 } 03558 case GrayscaleMatteType: 03559 { 03560 if (IsImageGray(image,exception) == MagickFalse) 03561 status=TransformImageColorspace(image,GRAYColorspace,exception); 03562 if (image->matte == MagickFalse) 03563 (void) SetImageAlphaChannel(image,OpaqueAlphaChannel,exception); 03564 break; 03565 } 03566 case PaletteType: 03567 { 03568 if (IsRGBColorspace(image->colorspace) == MagickFalse) 03569 status=TransformImageColorspace(image,RGBColorspace,exception); 03570 if ((image->storage_class == DirectClass) || (image->colors > 256)) 03571 { 03572 quantize_info=AcquireQuantizeInfo(image_info); 03573 quantize_info->number_colors=256; 03574 status=QuantizeImage(quantize_info,image,exception); 03575 quantize_info=DestroyQuantizeInfo(quantize_info); 03576 } 03577 image->matte=MagickFalse; 03578 break; 03579 } 03580 case PaletteBilevelMatteType: 03581 { 03582 ChannelType 03583 channel_mask; 03584 03585 if (IsRGBColorspace(image->colorspace) == MagickFalse) 03586 status=TransformImageColorspace(image,RGBColorspace,exception); 03587 if (image->matte == MagickFalse) 03588 (void) SetImageAlphaChannel(image,OpaqueAlphaChannel,exception); 03589 channel_mask=SetPixelChannelMask(image,AlphaChannel); 03590 (void) BilevelImage(image,(double) QuantumRange/2.0,exception); 03591 (void) SetPixelChannelMask(image,channel_mask); 03592 quantize_info=AcquireQuantizeInfo(image_info); 03593 status=QuantizeImage(quantize_info,image,exception); 03594 quantize_info=DestroyQuantizeInfo(quantize_info); 03595 break; 03596 } 03597 case PaletteMatteType: 03598 { 03599 if (IsRGBColorspace(image->colorspace) == MagickFalse) 03600 status=TransformImageColorspace(image,RGBColorspace,exception); 03601 if (image->matte == MagickFalse) 03602 (void) SetImageAlphaChannel(image,OpaqueAlphaChannel,exception); 03603 quantize_info=AcquireQuantizeInfo(image_info); 03604 quantize_info->colorspace=TransparentColorspace; 03605 status=QuantizeImage(quantize_info,image,exception); 03606 quantize_info=DestroyQuantizeInfo(quantize_info); 03607 break; 03608 } 03609 case TrueColorType: 03610 { 03611 if (IsRGBColorspace(image->colorspace) == MagickFalse) 03612 status=TransformImageColorspace(image,RGBColorspace,exception); 03613 if (image->storage_class != DirectClass) 03614 status=SetImageStorageClass(image,DirectClass,exception); 03615 image->matte=MagickFalse; 03616 break; 03617 } 03618 case TrueColorMatteType: 03619 { 03620 if (IsRGBColorspace(image->colorspace) == MagickFalse) 03621 status=TransformImageColorspace(image,RGBColorspace,exception); 03622 if (image->storage_class != DirectClass) 03623 status=SetImageStorageClass(image,DirectClass,exception); 03624 if (image->matte == MagickFalse) 03625 (void) SetImageAlphaChannel(image,OpaqueAlphaChannel,exception); 03626 break; 03627 } 03628 case ColorSeparationType: 03629 { 03630 if (image->colorspace != CMYKColorspace) 03631 { 03632 if (IsRGBColorspace(image->colorspace) == MagickFalse) 03633 status=TransformImageColorspace(image,RGBColorspace,exception); 03634 status=TransformImageColorspace(image,CMYKColorspace,exception); 03635 } 03636 if (image->storage_class != DirectClass) 03637 status=SetImageStorageClass(image,DirectClass,exception); 03638 image->matte=MagickFalse; 03639 break; 03640 } 03641 case ColorSeparationMatteType: 03642 { 03643 if (image->colorspace != CMYKColorspace) 03644 { 03645 if (IsRGBColorspace(image->colorspace) == MagickFalse) 03646 status=TransformImageColorspace(image,RGBColorspace,exception); 03647 status=TransformImageColorspace(image,CMYKColorspace,exception); 03648 } 03649 if (image->storage_class != DirectClass) 03650 status=SetImageStorageClass(image,DirectClass,exception); 03651 if (image->matte == MagickFalse) 03652 status=SetImageAlphaChannel(image,OpaqueAlphaChannel,exception); 03653 break; 03654 } 03655 case OptimizeType: 03656 case UndefinedType: 03657 break; 03658 } 03659 image->type=type; 03660 image_info=DestroyImageInfo(image_info); 03661 return(status); 03662 } 03663 03664 /* 03665 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 03666 % % 03667 % % 03668 % % 03669 % S e t I m a g e V i r t u a l P i x e l M e t h o d % 03670 % % 03671 % % 03672 % % 03673 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 03674 % 03675 % SetImageVirtualPixelMethod() sets the "virtual pixels" method for the 03676 % image and returns the previous setting. A virtual pixel is any pixel access 03677 % that is outside the boundaries of the image cache. 03678 % 03679 % The format of the SetImageVirtualPixelMethod() method is: 03680 % 03681 % VirtualPixelMethod SetImageVirtualPixelMethod(const Image *image, 03682 % const VirtualPixelMethod virtual_pixel_method) 03683 % 03684 % A description of each parameter follows: 03685 % 03686 % o image: the image. 03687 % 03688 % o virtual_pixel_method: choose the type of virtual pixel. 03689 % 03690 */ 03691 MagickExport VirtualPixelMethod SetImageVirtualPixelMethod(const Image *image, 03692 const VirtualPixelMethod virtual_pixel_method) 03693 { 03694 assert(image != (const Image *) NULL); 03695 assert(image->signature == MagickSignature); 03696 if (image->debug != MagickFalse) 03697 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename); 03698 return(SetPixelCacheVirtualMethod(image,virtual_pixel_method)); 03699 } 03700 03701 /* 03702 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 03703 % % 03704 % % 03705 % % 03706 % S m u s h I m a g e s % 03707 % % 03708 % % 03709 % % 03710 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 03711 % 03712 % SmushImages() takes all images from the current image pointer to the end 03713 % of the image list and smushes them to each other top-to-bottom if the 03714 % stack parameter is true, otherwise left-to-right. 03715 % 03716 % The current gravity setting now effects how the image is justified in the 03717 % final image. 03718 % 03719 % The format of the SmushImages method is: 03720 % 03721 % Image *SmushImages(const Image *images,const MagickBooleanType stack, 03722 % ExceptionInfo *exception) 03723 % 03724 % A description of each parameter follows: 03725 % 03726 % o images: the image sequence. 03727 % 03728 % o stack: A value other than 0 stacks the images top-to-bottom. 03729 % 03730 % o offset: minimum distance in pixels between images. 03731 % 03732 % o exception: return any errors or warnings in this structure. 03733 % 03734 */ 03735 03736 static ssize_t SmushXGap(const Image *smush_image,const Image *images, 03737 const ssize_t offset,ExceptionInfo *exception) 03738 { 03739 CacheView 03740 *left_view, 03741 *right_view; 03742 03743 const Image 03744 *left_image, 03745 *right_image; 03746 03747 RectangleInfo 03748 left_geometry, 03749 right_geometry; 03750 03751 register const Quantum 03752 *p; 03753 03754 register ssize_t 03755 i, 03756 y; 03757 03758 size_t 03759 gap; 03760 03761 ssize_t 03762 x; 03763 03764 if (images->previous == (Image *) NULL) 03765 return(0); 03766 right_image=images; 03767 SetGeometry(smush_image,&right_geometry); 03768 GravityAdjustGeometry(right_image->columns,right_image->rows, 03769 right_image->gravity,&right_geometry); 03770 left_image=images->previous; 03771 SetGeometry(smush_image,&left_geometry); 03772 GravityAdjustGeometry(left_image->columns,left_image->rows, 03773 left_image->gravity,&left_geometry); 03774 gap=right_image->columns; 03775 left_view=AcquireCacheView(left_image); 03776 right_view=AcquireCacheView(right_image); 03777 for (y=0; y < (ssize_t) smush_image->rows; y++) 03778 { 03779 for (x=(ssize_t) left_image->columns-1; x > 0; x--) 03780 { 03781 p=GetCacheViewVirtualPixels(left_view,x,left_geometry.y+y,1,1,exception); 03782 if ((p == (const Quantum *) NULL) || 03783 (GetPixelAlpha(left_image,p) != TransparentAlpha) || 03784 ((left_image->columns-x-1) >= gap)) 03785 break; 03786 } 03787 i=(ssize_t) left_image->columns-x-1; 03788 for (x=0; x < (ssize_t) right_image->columns; x++) 03789 { 03790 p=GetCacheViewVirtualPixels(right_view,x,right_geometry.y+y,1,1, 03791 exception); 03792 if ((p == (const Quantum *) NULL) || 03793 (GetPixelAlpha(right_image,p) != TransparentAlpha) || 03794 ((x+i) >= (ssize_t) gap)) 03795 break; 03796 } 03797 if ((x+i) < (ssize_t) gap) 03798 gap=(size_t) (x+i); 03799 } 03800 right_view=DestroyCacheView(right_view); 03801 left_view=DestroyCacheView(left_view); 03802 if (y < (ssize_t) smush_image->rows) 03803 return(offset); 03804 return((ssize_t) gap-offset); 03805 } 03806 03807 static ssize_t SmushYGap(const Image *smush_image,const Image *images, 03808 const ssize_t offset,ExceptionInfo *exception) 03809 { 03810 CacheView 03811 *bottom_view, 03812 *top_view; 03813 03814 const Image 03815 *bottom_image, 03816 *top_image; 03817 03818 RectangleInfo 03819 bottom_geometry, 03820 top_geometry; 03821 03822 register const Quantum 03823 *p; 03824 03825 register ssize_t 03826 i, 03827 x; 03828 03829 size_t 03830 gap; 03831 03832 ssize_t 03833 y; 03834 03835 if (images->previous == (Image *) NULL) 03836 return(0); 03837 bottom_image=images; 03838 SetGeometry(smush_image,&bottom_geometry); 03839 GravityAdjustGeometry(bottom_image->columns,bottom_image->rows, 03840 bottom_image->gravity,&bottom_geometry); 03841 top_image=images->previous; 03842 SetGeometry(smush_image,&top_geometry); 03843 GravityAdjustGeometry(top_image->columns,top_image->rows,top_image->gravity, 03844 &top_geometry); 03845 gap=bottom_image->rows; 03846 top_view=AcquireCacheView(top_image); 03847 bottom_view=AcquireCacheView(bottom_image); 03848 for (x=0; x < (ssize_t) smush_image->columns; x++) 03849 { 03850 for (y=(ssize_t) top_image->rows-1; y > 0; y--) 03851 { 03852 p=GetCacheViewVirtualPixels(top_view,top_geometry.x+x,y,1,1,exception); 03853 if ((p == (const Quantum *) NULL) || 03854 (GetPixelAlpha(top_image,p) != TransparentAlpha) || 03855 ((top_image->rows-y-1) >= gap)) 03856 break; 03857 } 03858 i=(ssize_t) top_image->rows-y-1; 03859 for (y=0; y < (ssize_t) bottom_image->rows; y++) 03860 { 03861 p=GetCacheViewVirtualPixels(bottom_view,bottom_geometry.x+x,y,1,1, 03862 exception); 03863 if ((p == (const Quantum *) NULL) || 03864 (GetPixelAlpha(bottom_image,p) != TransparentAlpha) || 03865 ((y+i) >= (ssize_t) gap)) 03866 break; 03867 } 03868 if ((y+i) < (ssize_t) gap) 03869 gap=(size_t) (y+i); 03870 } 03871 bottom_view=DestroyCacheView(bottom_view); 03872 top_view=DestroyCacheView(top_view); 03873 if (x < (ssize_t) smush_image->columns) 03874 return(offset); 03875 return((ssize_t) gap-offset); 03876 } 03877 03878 MagickExport Image *SmushImages(const Image *images, 03879 const MagickBooleanType stack,const ssize_t offset,ExceptionInfo *exception) 03880 { 03881 #define SmushImageTag "Smush/Image" 03882 03883 CacheView 03884 *smush_view; 03885 03886 const Image 03887 *image; 03888 03889 Image 03890 *smush_image; 03891 03892 MagickBooleanType 03893 matte, 03894 proceed, 03895 status; 03896 03897 MagickOffsetType 03898 n; 03899 03900 RectangleInfo 03901 geometry; 03902 03903 register const Image 03904 *next; 03905 03906 size_t 03907 height, 03908 number_images, 03909 width; 03910 03911 ssize_t 03912 x_offset, 03913 y_offset; 03914 03915 /* 03916 Compute maximum area of smushed area. 03917 */ 03918 assert(images != (Image *) NULL); 03919 assert(images->signature == MagickSignature); 03920 if (images->debug != MagickFalse) 03921 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",images->filename); 03922 assert(exception != (ExceptionInfo *) NULL); 03923 assert(exception->signature == MagickSignature); 03924 image=images; 03925 matte=image->matte; 03926 number_images=1; 03927 width=image->columns; 03928 height=image->rows; 03929 next=GetNextImageInList(image); 03930 for ( ; next != (Image *) NULL; next=