|
MagickCore
6.7.5
|
00001 /* 00002 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 00003 % % 00004 % % 00005 % % 00006 % AAA TTTTT TTTTT RRRR IIIII BBBB U U TTTTT EEEEE % 00007 % A A T T R R I B B U U T E % 00008 % AAAAA T T RRRR I BBBB U U T EEE % 00009 % A A T T R R I B B U U T E % 00010 % A A T T R R IIIII BBBB UUU T EEEEE % 00011 % % 00012 % % 00013 % MagickCore Get / Set Image Attributes % 00014 % % 00015 % Software Design % 00016 % John Cristy % 00017 % October 2002 % 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/attribute.h" 00045 #include "MagickCore/blob.h" 00046 #include "MagickCore/blob-private.h" 00047 #include "MagickCore/cache.h" 00048 #include "MagickCore/cache-view.h" 00049 #include "MagickCore/client.h" 00050 #include "MagickCore/color.h" 00051 #include "MagickCore/color-private.h" 00052 #include "MagickCore/colormap.h" 00053 #include "MagickCore/colormap-private.h" 00054 #include "MagickCore/colorspace.h" 00055 #include "MagickCore/colorspace-private.h" 00056 #include "MagickCore/composite.h" 00057 #include "MagickCore/composite-private.h" 00058 #include "MagickCore/constitute.h" 00059 #include "MagickCore/draw.h" 00060 #include "MagickCore/draw-private.h" 00061 #include "MagickCore/effect.h" 00062 #include "MagickCore/enhance.h" 00063 #include "MagickCore/exception.h" 00064 #include "MagickCore/exception-private.h" 00065 #include "MagickCore/geometry.h" 00066 #include "MagickCore/histogram.h" 00067 #include "MagickCore/identify.h" 00068 #include "MagickCore/image.h" 00069 #include "MagickCore/image-private.h" 00070 #include "MagickCore/list.h" 00071 #include "MagickCore/log.h" 00072 #include "MagickCore/memory_.h" 00073 #include "MagickCore/magick.h" 00074 #include "MagickCore/monitor.h" 00075 #include "MagickCore/monitor-private.h" 00076 #include "MagickCore/paint.h" 00077 #include "MagickCore/pixel.h" 00078 #include "MagickCore/pixel-accessor.h" 00079 #include "MagickCore/property.h" 00080 #include "MagickCore/quantize.h" 00081 #include "MagickCore/quantum-private.h" 00082 #include "MagickCore/random_.h" 00083 #include "MagickCore/resource_.h" 00084 #include "MagickCore/semaphore.h" 00085 #include "MagickCore/segment.h" 00086 #include "MagickCore/splay-tree.h" 00087 #include "MagickCore/string_.h" 00088 #include "MagickCore/thread-private.h" 00089 #include "MagickCore/threshold.h" 00090 #include "MagickCore/transform.h" 00091 #include "MagickCore/utility.h" 00092 00093 /* 00094 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 00095 % % 00096 % % 00097 % % 00098 + G e t I m a g e B o u n d i n g B o x % 00099 % % 00100 % % 00101 % % 00102 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 00103 % 00104 % GetImageBoundingBox() returns the bounding box of an image canvas. 00105 % 00106 % The format of the GetImageBoundingBox method is: 00107 % 00108 % RectangleInfo GetImageBoundingBox(const Image *image, 00109 % ExceptionInfo *exception) 00110 % 00111 % A description of each parameter follows: 00112 % 00113 % o bounds: Method GetImageBoundingBox returns the bounding box of an 00114 % image canvas. 00115 % 00116 % o image: the image. 00117 % 00118 % o exception: return any errors or warnings in this structure. 00119 % 00120 */ 00121 MagickExport RectangleInfo GetImageBoundingBox(const Image *image, 00122 ExceptionInfo *exception) 00123 { 00124 CacheView 00125 *image_view; 00126 00127 MagickBooleanType 00128 status; 00129 00130 PixelInfo 00131 target[3], 00132 zero; 00133 00134 RectangleInfo 00135 bounds; 00136 00137 register const Quantum 00138 *p; 00139 00140 ssize_t 00141 y; 00142 00143 assert(image != (Image *) NULL); 00144 assert(image->signature == MagickSignature); 00145 if (image->debug != MagickFalse) 00146 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename); 00147 bounds.width=0; 00148 bounds.height=0; 00149 bounds.x=(ssize_t) image->columns; 00150 bounds.y=(ssize_t) image->rows; 00151 GetPixelInfo(image,&target[0]); 00152 image_view=AcquireCacheView(image); 00153 p=GetCacheViewVirtualPixels(image_view,0,0,1,1,exception); 00154 if (p == (const Quantum *) NULL) 00155 { 00156 image_view=DestroyCacheView(image_view); 00157 return(bounds); 00158 } 00159 GetPixelInfoPixel(image,p,&target[0]); 00160 GetPixelInfo(image,&target[1]); 00161 p=GetCacheViewVirtualPixels(image_view,(ssize_t) image->columns-1,0,1,1, 00162 exception); 00163 GetPixelInfoPixel(image,p,&target[1]); 00164 GetPixelInfo(image,&target[2]); 00165 p=GetCacheViewVirtualPixels(image_view,0,(ssize_t) image->rows-1,1,1, 00166 exception); 00167 GetPixelInfoPixel(image,p,&target[2]); 00168 status=MagickTrue; 00169 GetPixelInfo(image,&zero); 00170 #if defined(MAGICKCORE_OPENMP_SUPPORT) 00171 #pragma omp parallel for schedule(static,4) shared(status) 00172 #endif 00173 for (y=0; y < (ssize_t) image->rows; y++) 00174 { 00175 PixelInfo 00176 pixel; 00177 00178 RectangleInfo 00179 bounding_box; 00180 00181 register const Quantum 00182 *restrict p; 00183 00184 register ssize_t 00185 x; 00186 00187 if (status == MagickFalse) 00188 continue; 00189 #if defined(MAGICKCORE_OPENMP_SUPPORT) 00190 # pragma omp critical (MagickCore_GetImageBoundingBox) 00191 #endif 00192 bounding_box=bounds; 00193 p=GetCacheViewVirtualPixels(image_view,0,y,image->columns,1,exception); 00194 if (p == (const Quantum *) NULL) 00195 { 00196 status=MagickFalse; 00197 continue; 00198 } 00199 pixel=zero; 00200 for (x=0; x < (ssize_t) image->columns; x++) 00201 { 00202 GetPixelInfoPixel(image,p,&pixel); 00203 if ((x < bounding_box.x) && 00204 (IsFuzzyEquivalencePixelInfo(&pixel,&target[0]) == MagickFalse)) 00205 bounding_box.x=x; 00206 if ((x > (ssize_t) bounding_box.width) && 00207 (IsFuzzyEquivalencePixelInfo(&pixel,&target[1]) == MagickFalse)) 00208 bounding_box.width=(size_t) x; 00209 if ((y < bounding_box.y) && 00210 (IsFuzzyEquivalencePixelInfo(&pixel,&target[0]) == MagickFalse)) 00211 bounding_box.y=y; 00212 if ((y > (ssize_t) bounding_box.height) && 00213 (IsFuzzyEquivalencePixelInfo(&pixel,&target[2]) == MagickFalse)) 00214 bounding_box.height=(size_t) y; 00215 p+=GetPixelChannels(image); 00216 } 00217 #if defined(MAGICKCORE_OPENMP_SUPPORT) 00218 # pragma omp critical (MagickCore_GetImageBoundingBox) 00219 #endif 00220 { 00221 if (bounding_box.x < bounds.x) 00222 bounds.x=bounding_box.x; 00223 if (bounding_box.y < bounds.y) 00224 bounds.y=bounding_box.y; 00225 if (bounding_box.width > bounds.width) 00226 bounds.width=bounding_box.width; 00227 if (bounding_box.height > bounds.height) 00228 bounds.height=bounding_box.height; 00229 } 00230 } 00231 image_view=DestroyCacheView(image_view); 00232 if ((bounds.width == 0) || (bounds.height == 0)) 00233 (void) ThrowMagickException(exception,GetMagickModule(),OptionWarning, 00234 "GeometryDoesNotContainImage","`%s'",image->filename); 00235 else 00236 { 00237 bounds.width-=(bounds.x-1); 00238 bounds.height-=(bounds.y-1); 00239 } 00240 return(bounds); 00241 } 00242 00243 /* 00244 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 00245 % % 00246 % % 00247 % % 00248 % G e t I m a g e D e p t h % 00249 % % 00250 % % 00251 % % 00252 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 00253 % 00254 % GetImageDepth() returns the depth of a particular image channel. 00255 % 00256 % The format of the GetImageDepth method is: 00257 % 00258 % size_t GetImageDepth(const Image *image,ExceptionInfo *exception) 00259 % 00260 % A description of each parameter follows: 00261 % 00262 % o image: the image. 00263 % 00264 % o exception: return any errors or warnings in this structure. 00265 % 00266 */ 00267 MagickExport size_t GetImageDepth(const Image *image,ExceptionInfo *exception) 00268 { 00269 CacheView 00270 *image_view; 00271 00272 MagickBooleanType 00273 status; 00274 00275 register ssize_t 00276 id; 00277 00278 size_t 00279 *current_depth, 00280 depth, 00281 number_threads; 00282 00283 ssize_t 00284 y; 00285 00286 /* 00287 Compute image depth. 00288 */ 00289 assert(image != (Image *) NULL); 00290 assert(image->signature == MagickSignature); 00291 if (image->debug != MagickFalse) 00292 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename); 00293 number_threads=GetOpenMPMaximumThreads(); 00294 current_depth=(size_t *) AcquireQuantumMemory(number_threads, 00295 sizeof(*current_depth)); 00296 if (current_depth == (size_t *) NULL) 00297 ThrowFatalException(ResourceLimitFatalError,"MemoryAllocationFailed"); 00298 status=MagickTrue; 00299 for (id=0; id < (ssize_t) number_threads; id++) 00300 current_depth[id]=1; 00301 if ((image->storage_class == PseudoClass) && (image->matte == MagickFalse)) 00302 { 00303 register ssize_t 00304 i; 00305 00306 #if defined(MAGICKCORE_OPENMP_SUPPORT) 00307 #pragma omp parallel for schedule(static) shared(status) 00308 #endif 00309 for (i=0; i < (ssize_t) image->colors; i++) 00310 { 00311 const int 00312 id = GetOpenMPThreadId(); 00313 00314 if (status == MagickFalse) 00315 continue; 00316 while (current_depth[id] < MAGICKCORE_QUANTUM_DEPTH) 00317 { 00318 MagickStatusType 00319 status; 00320 00321 QuantumAny 00322 range; 00323 00324 status=0; 00325 range=GetQuantumRange(current_depth[id]); 00326 if ((GetPixelRedTraits(image) & UpdatePixelTrait) != 0) 00327 status|=ClampToQuantum(image->colormap[i].red) != 00328 ScaleAnyToQuantum(ScaleQuantumToAny(ClampToQuantum( 00329 image->colormap[i].red),range),range); 00330 if ((GetPixelGreenTraits(image) & UpdatePixelTrait) != 0) 00331 status|=ClampToQuantum(image->colormap[i].green) != 00332 ScaleAnyToQuantum(ScaleQuantumToAny(ClampToQuantum( 00333 image->colormap[i].green),range),range); 00334 if ((GetPixelBlueTraits(image) & UpdatePixelTrait) != 0) 00335 status|=ClampToQuantum(image->colormap[i].blue) != 00336 ScaleAnyToQuantum(ScaleQuantumToAny(ClampToQuantum( 00337 image->colormap[i].blue),range),range); 00338 if (status == 0) 00339 break; 00340 current_depth[id]++; 00341 } 00342 } 00343 depth=current_depth[0]; 00344 for (id=1; id < (ssize_t) number_threads; id++) 00345 if (depth < current_depth[id]) 00346 depth=current_depth[id]; 00347 current_depth=(size_t *) RelinquishMagickMemory(current_depth); 00348 return(depth); 00349 } 00350 image_view=AcquireCacheView(image); 00351 #if !defined(MAGICKCORE_HDRI_SUPPORT) 00352 if (QuantumRange <= MaxMap) 00353 { 00354 register ssize_t 00355 i; 00356 00357 size_t 00358 *depth_map; 00359 00360 /* 00361 Scale pixels to desired (optimized with depth map). 00362 */ 00363 depth_map=(size_t *) AcquireQuantumMemory(MaxMap+1,sizeof(*depth_map)); 00364 if (depth_map == (size_t *) NULL) 00365 ThrowFatalException(ResourceLimitFatalError,"MemoryAllocationFailed"); 00366 for (i=0; i <= (ssize_t) MaxMap; i++) 00367 { 00368 unsigned int 00369 depth; 00370 00371 for (depth=1; depth < MAGICKCORE_QUANTUM_DEPTH; depth++) 00372 { 00373 Quantum 00374 pixel; 00375 00376 QuantumAny 00377 range; 00378 00379 range=GetQuantumRange(depth); 00380 pixel=(Quantum) i; 00381 if (pixel == ScaleAnyToQuantum(ScaleQuantumToAny(pixel,range),range)) 00382 break; 00383 } 00384 depth_map[i]=depth; 00385 } 00386 #if defined(MAGICKCORE_OPENMP_SUPPORT) 00387 #pragma omp parallel for schedule(static,4) shared(status) 00388 #endif 00389 for (y=0; y < (ssize_t) image->rows; y++) 00390 { 00391 const int 00392 id = GetOpenMPThreadId(); 00393 00394 register const Quantum 00395 *restrict p; 00396 00397 register ssize_t 00398 x; 00399 00400 if (status == MagickFalse) 00401 continue; 00402 p=GetCacheViewVirtualPixels(image_view,0,y,image->columns,1,exception); 00403 if (p == (const Quantum *) NULL) 00404 continue; 00405 for (x=0; x < (ssize_t) image->columns; x++) 00406 { 00407 register ssize_t 00408 i; 00409 00410 if (GetPixelMask(image,p) != 0) 00411 { 00412 p+=GetPixelChannels(image); 00413 continue; 00414 } 00415 for (i=0; i < (ssize_t) GetPixelChannels(image); i++) 00416 { 00417 PixelChannel 00418 channel; 00419 00420 PixelTrait 00421 traits; 00422 00423 channel=GetPixelChannelMapChannel(image,i); 00424 traits=GetPixelChannelMapTraits(image,channel); 00425 if ((traits == UndefinedPixelTrait) || 00426 (channel == IndexPixelChannel) || (channel == MaskPixelChannel)) 00427 continue; 00428 if (depth_map[ScaleQuantumToMap(p[i])] > current_depth[id]) 00429 current_depth[id]=depth_map[ScaleQuantumToMap(p[i])]; 00430 } 00431 p+=GetPixelChannels(image); 00432 } 00433 if (current_depth[id] == MAGICKCORE_QUANTUM_DEPTH) 00434 status=MagickFalse; 00435 } 00436 image_view=DestroyCacheView(image_view); 00437 depth=current_depth[0]; 00438 for (id=1; id < (ssize_t) number_threads; id++) 00439 if (depth < current_depth[id]) 00440 depth=current_depth[id]; 00441 depth_map=(size_t *) RelinquishMagickMemory(depth_map); 00442 current_depth=(size_t *) RelinquishMagickMemory(current_depth); 00443 return(depth); 00444 } 00445 #endif 00446 /* 00447 Compute pixel depth. 00448 */ 00449 #if defined(MAGICKCORE_OPENMP_SUPPORT) 00450 #pragma omp parallel for schedule(static,4) shared(status) 00451 #endif 00452 for (y=0; y < (ssize_t) image->rows; y++) 00453 { 00454 const int 00455 id = GetOpenMPThreadId(); 00456 00457 register const Quantum 00458 *restrict p; 00459 00460 register ssize_t 00461 x; 00462 00463 if (status == MagickFalse) 00464 continue; 00465 p=GetCacheViewVirtualPixels(image_view,0,y,image->columns,1,exception); 00466 if (p == (const Quantum *) NULL) 00467 continue; 00468 for (x=0; x < (ssize_t) image->columns; x++) 00469 { 00470 register ssize_t 00471 i; 00472 00473 if (GetPixelMask(image,p) != 0) 00474 { 00475 p+=GetPixelChannels(image); 00476 continue; 00477 } 00478 for (i=0; i < (ssize_t) GetPixelChannels(image); i++) 00479 { 00480 PixelChannel 00481 channel; 00482 00483 PixelTrait 00484 traits; 00485 00486 channel=GetPixelChannelMapChannel(image,i); 00487 traits=GetPixelChannelMapTraits(image,channel); 00488 if ((traits == UndefinedPixelTrait) || (channel == IndexPixelChannel) || 00489 (channel == MaskPixelChannel)) 00490 continue; 00491 while (current_depth[id] < MAGICKCORE_QUANTUM_DEPTH) 00492 { 00493 QuantumAny 00494 range; 00495 00496 range=GetQuantumRange(current_depth[id]); 00497 if (p[i] == ScaleAnyToQuantum(ScaleQuantumToAny(p[i],range),range)) 00498 break; 00499 current_depth[id]++; 00500 } 00501 } 00502 p+=GetPixelChannels(image); 00503 } 00504 if (current_depth[id] == MAGICKCORE_QUANTUM_DEPTH) 00505 status=MagickFalse; 00506 } 00507 image_view=DestroyCacheView(image_view); 00508 depth=current_depth[0]; 00509 for (id=1; id < (ssize_t) number_threads; id++) 00510 if (depth < current_depth[id]) 00511 depth=current_depth[id]; 00512 current_depth=(size_t *) RelinquishMagickMemory(current_depth); 00513 return(depth); 00514 } 00515 00516 /* 00517 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 00518 % % 00519 % % 00520 % % 00521 % G e t I m a g e Q u a n t u m D e p t h % 00522 % % 00523 % % 00524 % % 00525 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 00526 % 00527 % GetImageQuantumDepth() returns the depth of the image rounded to a legal 00528 % quantum depth: 8, 16, or 32. 00529 % 00530 % The format of the GetImageQuantumDepth method is: 00531 % 00532 % size_t GetImageQuantumDepth(const Image *image, 00533 % const MagickBooleanType constrain) 00534 % 00535 % A description of each parameter follows: 00536 % 00537 % o image: the image. 00538 % 00539 % o constrain: A value other than MagickFalse, constrains the depth to 00540 % a maximum of MAGICKCORE_QUANTUM_DEPTH. 00541 % 00542 */ 00543 00544 static inline double MagickMin(const double x,const double y) 00545 { 00546 if (x < y) 00547 return(x); 00548 return(y); 00549 } 00550 00551 MagickExport size_t GetImageQuantumDepth(const Image *image, 00552 const MagickBooleanType constrain) 00553 { 00554 size_t 00555 depth; 00556 00557 depth=image->depth; 00558 if (depth <= 8) 00559 depth=8; 00560 else 00561 if (depth <= 16) 00562 depth=16; 00563 else 00564 if (depth <= 32) 00565 depth=32; 00566 else 00567 if (depth <= 64) 00568 depth=64; 00569 if (constrain != MagickFalse) 00570 depth=(size_t) MagickMin((double) depth,(double) MAGICKCORE_QUANTUM_DEPTH); 00571 return(depth); 00572 } 00573 00574 /* 00575 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 00576 % % 00577 % % 00578 % % 00579 % G e t I m a g e T y p e % 00580 % % 00581 % % 00582 % % 00583 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 00584 % 00585 % GetImageType() returns the potential type of image: 00586 % 00587 % Bilevel Grayscale GrayscaleMatte 00588 % Palette PaletteMatte TrueColor 00589 % TrueColorMatte ColorSeparation ColorSeparationMatte 00590 % 00591 % To ensure the image type matches its potential, use SetImageType(): 00592 % 00593 % (void) SetImageType(image,GetImageType(image)); 00594 % 00595 % The format of the GetImageType method is: 00596 % 00597 % ImageType GetImageType(const Image *image,ExceptionInfo *exception) 00598 % 00599 % A description of each parameter follows: 00600 % 00601 % o image: the image. 00602 % 00603 % o exception: return any errors or warnings in this structure. 00604 % 00605 */ 00606 MagickExport ImageType GetImageType(const Image *image,ExceptionInfo *exception) 00607 { 00608 assert(image != (Image *) NULL); 00609 assert(image->signature == MagickSignature); 00610 if (image->debug != MagickFalse) 00611 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename); 00612 if (image->colorspace == CMYKColorspace) 00613 { 00614 if (image->matte == MagickFalse) 00615 return(ColorSeparationType); 00616 return(ColorSeparationMatteType); 00617 } 00618 if (IsImageMonochrome(image,exception) != MagickFalse) 00619 return(BilevelType); 00620 if (IsImageGray(image,exception) != MagickFalse) 00621 { 00622 if (image->matte != MagickFalse) 00623 return(GrayscaleMatteType); 00624 return(GrayscaleType); 00625 } 00626 if (IsPaletteImage(image,exception) != MagickFalse) 00627 { 00628 if (image->matte != MagickFalse) 00629 return(PaletteMatteType); 00630 return(PaletteType); 00631 } 00632 if (image->matte != MagickFalse) 00633 return(TrueColorMatteType); 00634 return(TrueColorType); 00635 } 00636 00637 /* 00638 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 00639 % % 00640 % % 00641 % % 00642 % I s I m a g e G r a y % 00643 % % 00644 % % 00645 % % 00646 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 00647 % 00648 % IsImageGray() returns MagickTrue if all the pixels in the image have the 00649 % same red, green, and blue intensities. 00650 % 00651 % The format of the IsImageGray method is: 00652 % 00653 % MagickBooleanType IsImageGray(const Image *image, 00654 % ExceptionInfo *exception) 00655 % 00656 % A description of each parameter follows: 00657 % 00658 % o image: the image. 00659 % 00660 % o exception: return any errors or warnings in this structure. 00661 % 00662 */ 00663 MagickExport MagickBooleanType IsImageGray(const Image *image, 00664 ExceptionInfo *exception) 00665 { 00666 CacheView 00667 *image_view; 00668 00669 ImageType 00670 type; 00671 00672 register const Quantum 00673 *p; 00674 00675 register ssize_t 00676 x; 00677 00678 ssize_t 00679 y; 00680 00681 assert(image != (Image *) NULL); 00682 assert(image->signature == MagickSignature); 00683 if (image->debug != MagickFalse) 00684 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename); 00685 if ((image->type == BilevelType) || (image->type == GrayscaleType) || 00686 (image->type == GrayscaleMatteType)) 00687 return(MagickTrue); 00688 if (IsRGBColorspace(image->colorspace) == MagickFalse) 00689 return(MagickFalse); 00690 type=BilevelType; 00691 image_view=AcquireCacheView(image); 00692 for (y=0; y < (ssize_t) image->rows; y++) 00693 { 00694 p=GetCacheViewVirtualPixels(image_view,0,y,image->columns,1,exception); 00695 if (p == (const Quantum *) NULL) 00696 break; 00697 for (x=0; x < (ssize_t) image->columns; x++) 00698 { 00699 if (IsPixelGray(image,p) == MagickFalse) 00700 { 00701 type=UndefinedType; 00702 break; 00703 } 00704 if ((type == BilevelType) && 00705 (IsPixelMonochrome(image,p) == MagickFalse)) 00706 type=GrayscaleType; 00707 p+=GetPixelChannels(image); 00708 } 00709 if (type == UndefinedType) 00710 break; 00711 } 00712 image_view=DestroyCacheView(image_view); 00713 if (type == UndefinedType) 00714 return(MagickFalse); 00715 ((Image *) image)->type=type; 00716 if ((type == GrayscaleType) && (image->matte != MagickFalse)) 00717 ((Image *) image)->type=GrayscaleMatteType; 00718 return(MagickTrue); 00719 } 00720 00721 /* 00722 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 00723 % % 00724 % % 00725 % % 00726 % I s I m a g e M o n o c h r o m e % 00727 % % 00728 % % 00729 % % 00730 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 00731 % 00732 % IsImageMonochrome() returns MagickTrue if all the pixels in the image have 00733 % the same red, green, and blue intensities and the intensity is either 00734 % 0 or QuantumRange. 00735 % 00736 % The format of the IsImageMonochrome method is: 00737 % 00738 % MagickBooleanType IsImageMonochrome(const Image *image, 00739 % ExceptionInfo *exception) 00740 % 00741 % A description of each parameter follows: 00742 % 00743 % o image: the image. 00744 % 00745 % o exception: return any errors or warnings in this structure. 00746 % 00747 */ 00748 MagickExport MagickBooleanType IsImageMonochrome(const Image *image, 00749 ExceptionInfo *exception) 00750 { 00751 CacheView 00752 *image_view; 00753 00754 ImageType 00755 type; 00756 00757 register ssize_t 00758 x; 00759 00760 register const Quantum 00761 *p; 00762 00763 ssize_t 00764 y; 00765 00766 assert(image != (Image *) NULL); 00767 assert(image->signature == MagickSignature); 00768 if (image->debug != MagickFalse) 00769 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename); 00770 if (image->type == BilevelType) 00771 return(MagickTrue); 00772 if (IsRGBColorspace(image->colorspace) == MagickFalse) 00773 return(MagickFalse); 00774 type=BilevelType; 00775 image_view=AcquireCacheView(image); 00776 for (y=0; y < (ssize_t) image->rows; y++) 00777 { 00778 p=GetCacheViewVirtualPixels(image_view,0,y,image->columns,1,exception); 00779 if (p == (const Quantum *) NULL) 00780 break; 00781 for (x=0; x < (ssize_t) image->columns; x++) 00782 { 00783 if (IsPixelMonochrome(image,p) == MagickFalse) 00784 { 00785 type=UndefinedType; 00786 break; 00787 } 00788 p+=GetPixelChannels(image); 00789 } 00790 if (type == UndefinedType) 00791 break; 00792 } 00793 image_view=DestroyCacheView(image_view); 00794 if (type == UndefinedType) 00795 return(MagickFalse); 00796 ((Image *) image)->type=type; 00797 return(MagickTrue); 00798 } 00799 00800 /* 00801 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 00802 % % 00803 % % 00804 % % 00805 % I s I m a g e O p a q u e % 00806 % % 00807 % % 00808 % % 00809 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 00810 % 00811 % IsImageOpaque() returns MagickTrue if none of the pixels in the image have 00812 % an opacity value other than opaque (0). 00813 % 00814 % The format of the IsImageOpaque method is: 00815 % 00816 % MagickBooleanType IsImageOpaque(const Image *image, 00817 % ExceptionInfo *exception) 00818 % 00819 % A description of each parameter follows: 00820 % 00821 % o image: the image. 00822 % 00823 % o exception: return any errors or warnings in this structure. 00824 % 00825 */ 00826 MagickExport MagickBooleanType IsImageOpaque(const Image *image, 00827 ExceptionInfo *exception) 00828 { 00829 CacheView 00830 *image_view; 00831 00832 register const Quantum 00833 *p; 00834 00835 register ssize_t 00836 x; 00837 00838 ssize_t 00839 y; 00840 00841 /* 00842 Determine if image is opaque. 00843 */ 00844 assert(image != (Image *) NULL); 00845 assert(image->signature == MagickSignature); 00846 if (image->debug != MagickFalse) 00847 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename); 00848 if (image->matte == MagickFalse) 00849 return(MagickTrue); 00850 image_view=AcquireCacheView(image); 00851 for (y=0; y < (ssize_t) image->rows; y++) 00852 { 00853 p=GetCacheViewVirtualPixels(image_view,0,y,image->columns,1,exception); 00854 if (p == (const Quantum *) NULL) 00855 break; 00856 for (x=0; x < (ssize_t) image->columns; x++) 00857 { 00858 if (GetPixelAlpha(image,p) != OpaqueAlpha) 00859 break; 00860 p+=GetPixelChannels(image); 00861 } 00862 if (x < (ssize_t) image->columns) 00863 break; 00864 } 00865 image_view=DestroyCacheView(image_view); 00866 return(y < (ssize_t) image->rows ? MagickFalse : MagickTrue); 00867 } 00868 00869 /* 00870 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 00871 % % 00872 % % 00873 % % 00874 % S e t I m a g e D e p t h % 00875 % % 00876 % % 00877 % % 00878 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 00879 % 00880 % SetImageDepth() sets the depth of the image. 00881 % 00882 % The format of the SetImageDepth method is: 00883 % 00884 % MagickBooleanType SetImageDepth(Image *image,const size_t depth, 00885 % ExceptionInfo *exception) 00886 % 00887 % A description of each parameter follows: 00888 % 00889 % o image: the image. 00890 % 00891 % o channel: the channel. 00892 % 00893 % o depth: the image depth. 00894 % 00895 % o exception: return any errors or warnings in this structure. 00896 % 00897 */ 00898 MagickExport MagickBooleanType SetImageDepth(Image *image, 00899 const size_t depth,ExceptionInfo *exception) 00900 { 00901 CacheView 00902 *image_view; 00903 00904 MagickBooleanType 00905 status; 00906 00907 QuantumAny 00908 range; 00909 00910 ssize_t 00911 y; 00912 00913 assert(image != (Image *) NULL); 00914 if (image->debug != MagickFalse) 00915 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"..."); 00916 assert(image->signature == MagickSignature); 00917 if (depth >= MAGICKCORE_QUANTUM_DEPTH) 00918 { 00919 image->depth=MAGICKCORE_QUANTUM_DEPTH; 00920 return(MagickTrue); 00921 } 00922 range=GetQuantumRange(depth); 00923 if (image->storage_class == PseudoClass) 00924 { 00925 register ssize_t 00926 i; 00927 00928 #if defined(MAGICKCORE_OPENMP_SUPPORT) 00929 #pragma omp parallel for schedule(static) shared(status) 00930 #endif 00931 for (i=0; i < (ssize_t) image->colors; i++) 00932 { 00933 if ((GetPixelRedTraits(image) & UpdatePixelTrait) != 0) 00934 image->colormap[i].red=(double) ScaleAnyToQuantum(ScaleQuantumToAny( 00935 ClampToQuantum(image->colormap[i].red),range),range); 00936 if ((GetPixelGreenTraits(image) & UpdatePixelTrait) != 0) 00937 image->colormap[i].green=(double) ScaleAnyToQuantum(ScaleQuantumToAny( ClampToQuantum(image->colormap[i].green),range),range); 00938 if ((GetPixelBlueTraits(image) & UpdatePixelTrait) != 0) 00939 image->colormap[i].blue=(double) ScaleAnyToQuantum(ScaleQuantumToAny( 00940 ClampToQuantum(image->colormap[i].blue),range),range); 00941 if ((GetPixelAlphaTraits(image) & UpdatePixelTrait) != 0) 00942 image->colormap[i].alpha=(double) ScaleAnyToQuantum(ScaleQuantumToAny( 00943 ClampToQuantum(image->colormap[i].alpha),range),range); 00944 } 00945 status=SyncImage(image,exception); 00946 if (status != MagickFalse) 00947 image->depth=depth; 00948 return(status); 00949 } 00950 status=MagickTrue; 00951 image_view=AcquireCacheView(image); 00952 #if !defined(MAGICKCORE_HDRI_SUPPORT) 00953 if (QuantumRange <= MaxMap) 00954 { 00955 Quantum 00956 *depth_map; 00957 00958 register ssize_t 00959 i; 00960 00961 /* 00962 Scale pixels to desired (optimized with depth map). 00963 */ 00964 depth_map=(Quantum *) AcquireQuantumMemory(MaxMap+1,sizeof(*depth_map)); 00965 if (depth_map == (Quantum *) NULL) 00966 ThrowFatalException(ResourceLimitFatalError,"MemoryAllocationFailed"); 00967 for (i=0; i <= (ssize_t) MaxMap; i++) 00968 depth_map[i]=ScaleAnyToQuantum(ScaleQuantumToAny((Quantum) i,range), 00969 range); 00970 #if defined(MAGICKCORE_OPENMP_SUPPORT) 00971 #pragma omp parallel for schedule(static,4) shared(status) 00972 #endif 00973 for (y=0; y < (ssize_t) image->rows; y++) 00974 { 00975 register ssize_t 00976 x; 00977 00978 register Quantum 00979 *restrict q; 00980 00981 if (status == MagickFalse) 00982 continue; 00983 q=GetCacheViewAuthenticPixels(image_view,0,y,image->columns,1, 00984 exception); 00985 if (q == (Quantum *) NULL) 00986 { 00987 status=MagickFalse; 00988 continue; 00989 } 00990 for (x=0; x < (ssize_t) image->columns; x++) 00991 { 00992 register ssize_t 00993 i; 00994 00995 if (GetPixelMask(image,q) != 0) 00996 { 00997 q+=GetPixelChannels(image); 00998 continue; 00999 } 01000 for (i=0; i < (ssize_t) GetPixelChannels(image); i++) 01001 { 01002 PixelChannel 01003 channel; 01004 01005 PixelTrait 01006 traits; 01007 01008 channel=GetPixelChannelMapChannel(image,i); 01009 traits=GetPixelChannelMapTraits(image,channel); 01010 if ((traits == UndefinedPixelTrait) || 01011 (channel == IndexPixelChannel) || (channel == MaskPixelChannel)) 01012 continue; 01013 q[i]=depth_map[ScaleQuantumToMap(q[i])]; 01014 } 01015 q+=GetPixelChannels(image); 01016 } 01017 if (SyncCacheViewAuthenticPixels(image_view,exception) == MagickFalse) 01018 { 01019 status=MagickFalse; 01020 continue; 01021 } 01022 } 01023 image_view=DestroyCacheView(image_view); 01024 depth_map=(Quantum *) RelinquishMagickMemory(depth_map); 01025 if (status != MagickFalse) 01026 image->depth=depth; 01027 return(status); 01028 } 01029 #endif 01030 /* 01031 Scale pixels to desired depth. 01032 */ 01033 #if defined(MAGICKCORE_OPENMP_SUPPORT) 01034 #pragma omp parallel for schedule(static,4) shared(status) 01035 #endif 01036 for (y=0; y < (ssize_t) image->rows; y++) 01037 { 01038 register ssize_t 01039 x; 01040 01041 register Quantum 01042 *restrict q; 01043 01044 if (status == MagickFalse) 01045 continue; 01046 q=GetCacheViewAuthenticPixels(image_view,0,y,image->columns,1,exception); 01047 if (q == (Quantum *) NULL) 01048 { 01049 status=MagickFalse; 01050 continue; 01051 } 01052 for (x=0; x < (ssize_t) image->columns; x++) 01053 { 01054 register ssize_t 01055 i; 01056 01057 if (GetPixelMask(image,q) != 0) 01058 { 01059 q+=GetPixelChannels(image); 01060 continue; 01061 } 01062 for (i=0; i < (ssize_t) GetPixelChannels(image); i++) 01063 { 01064 PixelChannel 01065 channel; 01066 01067 PixelTrait 01068 traits; 01069 01070 channel=GetPixelChannelMapChannel(image,i); 01071 traits=GetPixelChannelMapTraits(image,channel); 01072 if ((traits == UndefinedPixelTrait) || (channel == IndexPixelChannel) || 01073 (channel == MaskPixelChannel)) 01074 continue; 01075 q[i]=ScaleAnyToQuantum(ScaleQuantumToAny(q[i],range),range); 01076 } 01077 q+=GetPixelChannels(image); 01078 } 01079 if (SyncCacheViewAuthenticPixels(image_view,exception) == MagickFalse) 01080 { 01081 status=MagickFalse; 01082 continue; 01083 } 01084 } 01085 image_view=DestroyCacheView(image_view); 01086 if (status != MagickFalse) 01087 image->depth=depth; 01088 return(status); 01089 }