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