43 #include "magick/studio.h" 44 #include "magick/artifact.h" 45 #include "magick/attribute.h" 46 #include "magick/blob.h" 47 #include "magick/blob-private.h" 48 #include "magick/cache.h" 49 #include "magick/cache-private.h" 50 #include "magick/cache-view.h" 51 #include "magick/client.h" 52 #include "magick/channel.h" 53 #include "magick/color.h" 54 #include "magick/color-private.h" 55 #include "magick/colormap.h" 56 #include "magick/colormap-private.h" 57 #include "magick/colorspace.h" 58 #include "magick/colorspace-private.h" 59 #include "magick/composite.h" 60 #include "magick/composite-private.h" 61 #include "magick/constitute.h" 62 #include "magick/deprecate.h" 63 #include "magick/draw.h" 64 #include "magick/draw-private.h" 65 #include "magick/effect.h" 66 #include "magick/enhance.h" 67 #include "magick/exception.h" 68 #include "magick/exception-private.h" 69 #include "magick/geometry.h" 70 #include "magick/histogram.h" 71 #include "magick/identify.h" 72 #include "magick/image.h" 73 #include "magick/image-private.h" 74 #include "magick/list.h" 75 #include "magick/log.h" 76 #include "magick/memory_.h" 77 #include "magick/magick.h" 78 #include "magick/monitor.h" 79 #include "magick/monitor-private.h" 80 #include "magick/option.h" 81 #include "magick/paint.h" 82 #include "magick/pixel.h" 83 #include "magick/pixel-private.h" 84 #include "magick/property.h" 85 #include "magick/quantize.h" 86 #include "magick/random_.h" 87 #include "magick/resource_.h" 88 #include "magick/semaphore.h" 89 #include "magick/segment.h" 90 #include "magick/splay-tree.h" 91 #include "magick/string_.h" 92 #include "magick/string-private.h" 93 #include "magick/thread-private.h" 94 #include "magick/threshold.h" 95 #include "magick/transform.h" 96 #include "magick/utility.h" 136 static double GetEdgeBackgroundCensus(
const Image *image,
137 const CacheView *image_view,
const GravityType gravity,
const size_t width,
138 const size_t height,
const ssize_t x_offset,
const ssize_t y_offset,
171 case NorthWestGravity:
175 p=GetCacheViewVirtualPixels(image_view,0,0,1,1,exception);
178 case NorthEastGravity:
181 p=GetCacheViewVirtualPixels(image_view,(ssize_t) image->columns-1,0,1,1,
185 case SouthEastGravity:
188 p=GetCacheViewVirtualPixels(image_view,(ssize_t) image->columns-1,
189 (ssize_t) image->rows-1,1,1,exception);
192 case SouthWestGravity:
195 p=GetCacheViewVirtualPixels(image_view,0,(ssize_t) image->rows-1,1,1,
202 GetMagickPixelPacket(image,&background);
203 SetMagickPixelPacket(image,p,(IndexPacket *) NULL,&background);
204 artifact=GetImageArtifact(image,
"background");
205 if (artifact != (
const char *) NULL)
206 (void) QueryMagickColor(artifact,&background,exception);
207 artifact=GetImageArtifact(image,
"trim:background-color");
208 if (artifact != (
const char *) NULL)
209 (void) QueryMagickColor(artifact,&background,exception);
210 edge_geometry.width=width;
211 edge_geometry.height=height;
212 edge_geometry.x=x_offset;
213 edge_geometry.y=y_offset;
214 GravityAdjustGeometry(image->columns,image->rows,gravity,&edge_geometry);
215 edge_image=CropImage(image,&edge_geometry,exception);
216 if (edge_image == (
Image *) NULL)
219 GetMagickPixelPacket(edge_image,&pixel);
220 edge_view=AcquireVirtualCacheView(edge_image,exception);
221 for (y=0; y < (ssize_t) edge_image->rows; y++)
226 p=GetCacheViewVirtualPixels(edge_view,0,y,edge_image->columns,1,exception);
229 for (x=0; x < (ssize_t) edge_image->columns; x++)
231 SetMagickPixelPacket(edge_image,p,(IndexPacket *) NULL,&pixel);
232 if (IsMagickColorSimilar(&pixel,&background) == MagickFalse)
237 census/=((double) edge_image->columns*edge_image->rows);
238 edge_view=DestroyCacheView(edge_view);
239 edge_image=DestroyImage(edge_image);
243 static inline double GetMinEdgeBackgroundCensus(
const CensusInfo *edge)
248 census=MagickMin(MagickMin(MagickMin(edge->left,edge->right),edge->top),
279 assert(image != (
Image *) NULL);
280 assert(image->signature == MagickCoreSignature);
281 if (IsEventLogging() != MagickFalse)
282 (void) LogMagickEvent(TraceEvent,GetMagickModule(),
"%s",image->filename);
283 SetGeometry(image,&bounds);
284 edge_image=CloneImage(image,0,0,MagickTrue,exception);
285 if (edge_image == (
Image *) NULL)
287 (void) ParseAbsoluteGeometry(
"0x0+0+0",&edge_image->page);
288 (void) memset(&vertex,0,
sizeof(vertex));
289 edge_view=AcquireVirtualCacheView(edge_image,exception);
290 edge.left=GetEdgeBackgroundCensus(edge_image,edge_view,WestGravity,
292 edge.right=GetEdgeBackgroundCensus(edge_image,edge_view,EastGravity,
294 edge.top=GetEdgeBackgroundCensus(edge_image,edge_view,NorthGravity,
296 edge.bottom=GetEdgeBackgroundCensus(edge_image,edge_view,SouthGravity,
298 percent_background=1.0;
299 artifact=GetImageArtifact(edge_image,
"trim:percent-background");
300 if (artifact != (
const char *) NULL)
301 percent_background=StringToDouble(artifact,(
char **) NULL)/100.0;
302 percent_background=MagickMin(MagickMax(1.0-percent_background,MagickEpsilon),
304 background_census=GetMinEdgeBackgroundCensus(&edge);
305 for ( ; background_census < percent_background;
306 background_census=GetMinEdgeBackgroundCensus(&edge))
308 if ((bounds.width == 0) || (bounds.height == 0))
310 if (fabs(edge.left-background_census) < MagickEpsilon)
317 edge.left=GetEdgeBackgroundCensus(edge_image,edge_view,
318 NorthWestGravity,1,bounds.height,(ssize_t) vertex.left,(ssize_t)
319 vertex.top,exception);
320 edge.top=GetEdgeBackgroundCensus(edge_image,edge_view,
321 NorthWestGravity,bounds.width,1,(ssize_t) vertex.left,(ssize_t)
322 vertex.top,exception);
323 edge.bottom=GetEdgeBackgroundCensus(edge_image,edge_view,
324 SouthWestGravity,bounds.width,1,(ssize_t) vertex.left,(ssize_t)
325 vertex.bottom,exception);
328 if (fabs(edge.right-background_census) < MagickEpsilon)
335 edge.right=GetEdgeBackgroundCensus(edge_image,edge_view,
336 NorthEastGravity,1,bounds.height,(ssize_t) vertex.right,(ssize_t)
337 vertex.top,exception);
338 edge.top=GetEdgeBackgroundCensus(edge_image,edge_view,
339 NorthWestGravity,bounds.width,1,(ssize_t) vertex.left,(ssize_t)
340 vertex.top,exception);
341 edge.bottom=GetEdgeBackgroundCensus(edge_image,edge_view,
342 SouthWestGravity,bounds.width,1,(ssize_t) vertex.left,(ssize_t)
343 vertex.bottom,exception);
346 if (fabs(edge.top-background_census) < MagickEpsilon)
353 edge.left=GetEdgeBackgroundCensus(edge_image,edge_view,
354 NorthWestGravity,1,bounds.height,(ssize_t) vertex.left,(ssize_t)
355 vertex.top,exception);
356 edge.right=GetEdgeBackgroundCensus(edge_image,edge_view,
357 NorthEastGravity,1,bounds.height,(ssize_t) vertex.right,(ssize_t)
358 vertex.top,exception);
359 edge.top=GetEdgeBackgroundCensus(edge_image,edge_view,
360 NorthWestGravity,bounds.width,1,(ssize_t) vertex.left,(ssize_t)
361 vertex.top,exception);
364 if (fabs(edge.bottom-background_census) < MagickEpsilon)
371 edge.left=GetEdgeBackgroundCensus(edge_image,edge_view,
372 NorthWestGravity,1,bounds.height,(ssize_t) vertex.left,(ssize_t)
373 vertex.top,exception);
374 edge.right=GetEdgeBackgroundCensus(edge_image,edge_view,
375 NorthEastGravity,1,bounds.height,(ssize_t) vertex.right,(ssize_t)
376 vertex.top,exception);
377 edge.bottom=GetEdgeBackgroundCensus(edge_image,edge_view,
378 SouthWestGravity,bounds.width,1,(ssize_t) vertex.left,(ssize_t)
379 vertex.bottom,exception);
383 edge_view=DestroyCacheView(edge_view);
384 edge_image=DestroyImage(edge_image);
385 bounds.x=(ssize_t) vertex.left;
386 bounds.y=(ssize_t) vertex.top;
387 if ((bounds.width == 0) || (bounds.height == 0))
388 (void) ThrowMagickException(exception,GetMagickModule(),OptionWarning,
389 "GeometryDoesNotContainImage",
"`%s'",image->filename);
418 assert(image != (
Image *) NULL);
419 assert(image->signature == MagickCoreSignature);
420 if (IsEventLogging() != MagickFalse)
421 (void) LogMagickEvent(TraceEvent,GetMagickModule(),
"%s",image->filename);
422 artifact=GetImageArtifact(image,
"trim:percent-background");
423 if (artifact != (
const char *) NULL)
424 return(GetEdgeBoundingBox(image,exception));
425 bounds.width=image->columns == 1 ? 1 : 0;
426 bounds.height=image->rows == 1 ? 1 : 0;
427 bounds.x=(ssize_t) image->columns;
428 bounds.y=(ssize_t) image->rows;
429 GetMagickPixelPacket(image,&target[0]);
430 image_view=AcquireVirtualCacheView(image,exception);
431 p=GetCacheViewVirtualPixels(image_view,0,0,1,1,exception);
434 image_view=DestroyCacheView(image_view);
437 SetMagickPixelPacket(image,p,GetCacheViewVirtualIndexQueue(image_view),
439 GetMagickPixelPacket(image,&target[1]);
440 p=GetCacheViewVirtualPixels(image_view,(ssize_t) image->columns-1,0,1,1,
443 SetMagickPixelPacket(image,p,GetCacheViewVirtualIndexQueue(image_view),
445 GetMagickPixelPacket(image,&target[2]);
446 p=GetCacheViewVirtualPixels(image_view,0,(ssize_t) image->rows-1,1,1,
449 SetMagickPixelPacket(image,p,GetCacheViewVirtualIndexQueue(image_view),
451 GetMagickPixelPacket(image,&target[3]);
452 p=GetCacheViewVirtualPixels(image_view,(ssize_t) image->columns-1,
453 (ssize_t) image->rows-1,1,1,exception);
455 SetMagickPixelPacket(image,p,GetCacheViewVirtualIndexQueue(image_view),
458 GetMagickPixelPacket(image,&zero);
459 #if defined(MAGICKCORE_OPENMP_SUPPORT) 460 #pragma omp parallel for schedule(static) shared(status) \ 461 magick_number_threads(image,image,image->rows,2) 463 for (y=0; y < (ssize_t) image->rows; y++)
472 *magick_restrict indexes;
480 if (status == MagickFalse)
482 #if defined(MAGICKCORE_OPENMP_SUPPORT) 483 # pragma omp critical (MagickCore_GetImageBoundingBox) 486 p=GetCacheViewVirtualPixels(image_view,0,y,image->columns,1,exception);
492 indexes=GetCacheViewVirtualIndexQueue(image_view);
494 for (x=0; x < (ssize_t) image->columns; x++)
496 SetMagickPixelPacket(image,p,indexes+x,&pixel);
497 if ((x < bounding_box.x) &&
498 (IsMagickColorSimilar(&pixel,&target[0]) == MagickFalse))
500 if ((x > (ssize_t) bounding_box.width) &&
501 (IsMagickColorSimilar(&pixel,&target[1]) == MagickFalse))
502 bounding_box.width=(size_t) x;
503 if ((y < bounding_box.y) &&
504 (IsMagickColorSimilar(&pixel,&target[0]) == MagickFalse))
506 if ((y > (ssize_t) bounding_box.height) &&
507 (IsMagickColorSimilar(&pixel,&target[2]) == MagickFalse))
508 bounding_box.height=(size_t) y;
509 if ((x < (ssize_t) bounding_box.width) &&
510 (y > (ssize_t) bounding_box.height) &&
511 (IsMagickColorSimilar(&pixel,&target[3]) == MagickFalse))
513 bounding_box.width=(size_t) x;
514 bounding_box.height=(size_t) y;
518 #if defined(MAGICKCORE_OPENMP_SUPPORT) 519 # pragma omp critical (MagickCore_GetImageBoundingBox) 522 if (bounding_box.x < bounds.x)
523 bounds.x=bounding_box.x;
524 if (bounding_box.y < bounds.y)
525 bounds.y=bounding_box.y;
526 if (bounding_box.width > bounds.width)
527 bounds.width=bounding_box.width;
528 if (bounding_box.height > bounds.height)
529 bounds.height=bounding_box.height;
532 image_view=DestroyCacheView(image_view);
533 if ((bounds.width == 0) || (bounds.height == 0))
534 (void) ThrowMagickException(exception,GetMagickModule(),OptionWarning,
535 "GeometryDoesNotContainImage",
"`%s'",image->filename);
538 bounds.width-=(size_t) (bounds.x-1);
539 bounds.height-=(size_t) (bounds.y-1);
574 return(GetImageChannelDepth(image,CompositeChannels,exception));
577 MagickExport
size_t GetImageChannelDepth(
const Image *image,
600 assert(image != (
Image *) NULL);
602 assert(image->signature == MagickCoreSignature);
603 if (IsEventLogging() != MagickFalse)
604 (void) LogMagickEvent(TraceEvent,GetMagickModule(),
"%s",image->filename);
605 number_threads=(size_t) GetMagickResourceLimit(ThreadResource);
606 current_depth=(
size_t *) AcquireQuantumMemory(number_threads,
607 sizeof(*current_depth));
608 if (current_depth == (
size_t *) NULL)
609 ThrowFatalException(ResourceLimitFatalError,
"MemoryAllocationFailed");
611 for (i=0; i < (ssize_t) number_threads; i++)
613 if ((image->storage_class == PseudoClass) && (image->matte == MagickFalse))
615 #if defined(MAGICKCORE_OPENMP_SUPPORT) 616 #pragma omp parallel for schedule(static) shared(status) \ 617 magick_number_threads(image,image,image->colors,1) 619 for (i=0; i < (ssize_t) image->colors; i++)
622 id = GetOpenMPThreadId();
624 while (current_depth[
id] < MAGICKCORE_QUANTUM_DEPTH)
633 range=GetQuantumRange(current_depth[
id]);
634 if ((channel & RedChannel) != 0)
635 if (IsPixelAtDepth(image->colormap[i].red,range) == MagickFalse)
637 if ((atDepth != MagickFalse) && ((channel & GreenChannel) != 0))
638 if (IsPixelAtDepth(image->colormap[i].green,range) == MagickFalse)
640 if ((atDepth != MagickFalse) && ((channel & BlueChannel) != 0))
641 if (IsPixelAtDepth(image->colormap[i].blue,range) == MagickFalse)
643 if ((atDepth != MagickFalse))
648 depth=current_depth[0];
649 for (i=1; i < (ssize_t) number_threads; i++)
650 if (depth < current_depth[i])
651 depth=current_depth[i];
652 current_depth=(
size_t *) RelinquishMagickMemory(current_depth);
655 image_view=AcquireVirtualCacheView(image,exception);
656 #if !defined(MAGICKCORE_HDRI_SUPPORT) 657 DisableMSCWarning(4127)
658 if (1UL*QuantumRange <= MaxMap)
667 depth_map=(
size_t *) AcquireQuantumMemory(MaxMap+1,
sizeof(*depth_map));
668 if (depth_map == (
size_t *) NULL)
669 ThrowFatalException(ResourceLimitFatalError,
"MemoryAllocationFailed");
670 for (i=0; i <= (ssize_t) MaxMap; i++)
675 for (depth=1; depth < MAGICKCORE_QUANTUM_DEPTH; depth++)
683 range=GetQuantumRange(depth);
685 if (pixel == ScaleAnyToQuantum(ScaleQuantumToAny(pixel,range),range))
690 #if defined(MAGICKCORE_OPENMP_SUPPORT) 691 #pragma omp parallel for schedule(static) shared(status) \ 692 magick_number_threads(image,image,image->rows,1) 694 for (y=0; y < (ssize_t) image->rows; y++)
697 id = GetOpenMPThreadId();
700 *magick_restrict indexes;
708 if (status == MagickFalse)
710 p=GetCacheViewVirtualPixels(image_view,0,y,image->columns,1,exception);
713 indexes=GetCacheViewVirtualIndexQueue(image_view);
714 for (x=0; x < (ssize_t) image->columns; x++)
719 if ((channel & RedChannel) != 0)
721 pixel=GetPixelRed(p);
722 if (depth_map[ScaleQuantumToMap(pixel)] > current_depth[
id])
723 current_depth[id]=depth_map[ScaleQuantumToMap(pixel)];
725 if ((channel & GreenChannel) != 0)
727 pixel=GetPixelGreen(p);
728 if (depth_map[ScaleQuantumToMap(pixel)] > current_depth[
id])
729 current_depth[id]=depth_map[ScaleQuantumToMap(pixel)];
731 if ((channel & BlueChannel) != 0)
733 pixel=GetPixelBlue(p);
734 if (depth_map[ScaleQuantumToMap(pixel)] > current_depth[
id])
735 current_depth[id]=depth_map[ScaleQuantumToMap(pixel)];
737 if (((channel & OpacityChannel) != 0) &&
738 (image->matte != MagickFalse))
740 pixel=GetPixelOpacity(p);
741 if (depth_map[ScaleQuantumToMap(pixel)] > current_depth[
id])
742 current_depth[id]=depth_map[ScaleQuantumToMap(pixel)];
744 if (((channel & IndexChannel) != 0) &&
745 (image->colorspace == CMYKColorspace))
747 pixel=GetPixelIndex(indexes+x);
748 if (depth_map[ScaleQuantumToMap(pixel)] > current_depth[
id])
749 current_depth[id]=depth_map[ScaleQuantumToMap(pixel)];
753 if (current_depth[
id] == MAGICKCORE_QUANTUM_DEPTH)
756 image_view=DestroyCacheView(image_view);
757 depth=current_depth[0];
758 for (i=1; i < (ssize_t) number_threads; i++)
759 if (depth < current_depth[i])
760 depth=current_depth[i];
761 depth_map=(
size_t *) RelinquishMagickMemory(depth_map);
762 current_depth=(
size_t *) RelinquishMagickMemory(current_depth);
766 #if defined(MAGICKCORE_OPENMP_SUPPORT) 767 #pragma omp parallel for schedule(static) shared(status) \ 768 magick_number_threads(image,image,image->rows,1) 770 for (y=0; y < (ssize_t) image->rows; y++)
773 id = GetOpenMPThreadId();
776 *magick_restrict indexes;
784 if (status == MagickFalse)
786 p=GetCacheViewVirtualPixels(image_view,0,y,image->columns,1,exception);
789 indexes=GetCacheViewVirtualIndexQueue(image_view);
790 for (x=0; x < (ssize_t) image->columns; x++)
792 while (current_depth[
id] < MAGICKCORE_QUANTUM_DEPTH)
801 range=GetQuantumRange(current_depth[
id]);
802 if ((atDepth != MagickFalse) && ((channel & RedChannel) != 0))
803 if (IsPixelAtDepth(GetPixelRed(p),range) == MagickFalse)
805 if ((atDepth != MagickFalse) && ((channel & GreenChannel) != 0))
806 if (IsPixelAtDepth(GetPixelGreen(p),range) == MagickFalse)
808 if ((atDepth != MagickFalse) && ((channel & BlueChannel) != 0))
809 if (IsPixelAtDepth(GetPixelBlue(p),range) == MagickFalse)
811 if ((atDepth != MagickFalse) && ((channel & OpacityChannel) != 0) &&
812 (image->matte != MagickFalse))
813 if (IsPixelAtDepth(GetPixelOpacity(p),range) == MagickFalse)
815 if ((atDepth != MagickFalse) && ((channel & IndexChannel) != 0) &&
816 (image->colorspace == CMYKColorspace))
817 if (IsPixelAtDepth(GetPixelIndex(indexes+x),range) == MagickFalse)
819 if ((atDepth != MagickFalse))
825 if (current_depth[
id] == MAGICKCORE_QUANTUM_DEPTH)
828 image_view=DestroyCacheView(image_view);
829 depth=current_depth[0];
830 for (i=1; i < (ssize_t) number_threads; i++)
831 if (depth < current_depth[i])
832 depth=current_depth[i];
833 current_depth=(
size_t *) RelinquishMagickMemory(current_depth);
864 MagickExport
size_t GetImageQuantumDepth(
const Image *image,
865 const MagickBooleanType constrain)
882 if (constrain != MagickFalse)
883 depth=(size_t) MagickMin((
double) depth,(double) MAGICKCORE_QUANTUM_DEPTH);
921 assert(image != (
Image *) NULL);
922 assert(image->signature == MagickCoreSignature);
923 if (IsEventLogging() != MagickFalse)
924 (void) LogMagickEvent(TraceEvent,GetMagickModule(),
"%s",image->filename);
925 if (image->colorspace == CMYKColorspace)
927 if (image->matte == MagickFalse)
928 return(ColorSeparationType);
929 return(ColorSeparationMatteType);
931 if (IsMonochromeImage(image,exception) != MagickFalse)
933 if (IsGrayImage(image,exception) != MagickFalse)
935 if (image->matte != MagickFalse)
936 return(GrayscaleMatteType);
937 return(GrayscaleType);
939 if (IsPaletteImage(image,exception) != MagickFalse)
941 if (image->matte != MagickFalse)
942 return(PaletteMatteType);
945 if (image->matte != MagickFalse)
946 return(TrueColorMatteType);
947 return(TrueColorType);
974 MagickExport ImageType IdentifyImageGray(
const Image *image,
986 assert(image != (
Image *) NULL);
987 assert(image->signature == MagickCoreSignature);
988 if (IsEventLogging() != MagickFalse)
989 (void) LogMagickEvent(TraceEvent,GetMagickModule(),
"%s",image->filename);
990 if ((image->type == BilevelType) || (image->type == GrayscaleType) ||
991 (image->type == GrayscaleMatteType))
993 if (IssRGBCompatibleColorspace(image->colorspace) == MagickFalse)
994 return(UndefinedType);
995 image_view=AcquireVirtualCacheView(image,exception);
996 #if defined(MAGICKCORE_OPENMP_SUPPORT) 997 #pragma omp parallel for schedule(static) shared(type) \ 998 magick_number_threads(image,image,image->rows,2) 1000 for (y=0; y < (ssize_t) image->rows; y++)
1008 if (type == UndefinedType)
1010 p=GetCacheViewVirtualPixels(image_view,0,y,image->columns,1,exception);
1016 for (x=0; x < (ssize_t) image->columns; x++)
1018 if (IsPixelGray(p) == MagickFalse)
1023 if ((type == BilevelType) && (IsPixelMonochrome(p) == MagickFalse))
1028 image_view=DestroyCacheView(image_view);
1029 if ((type == GrayscaleType) && (image->matte != MagickFalse))
1030 type=GrayscaleMatteType;
1061 MagickExport MagickBooleanType IdentifyImageMonochrome(
const Image *image,
1073 assert(image != (
Image *) NULL);
1074 assert(image->signature == MagickCoreSignature);
1075 if (IsEventLogging() != MagickFalse)
1076 (void) LogMagickEvent(TraceEvent,GetMagickModule(),
"%s",image->filename);
1077 if (image->type == BilevelType)
1079 if (IssRGBCompatibleColorspace(image->colorspace) == MagickFalse)
1080 return(MagickFalse);
1081 image_view=AcquireVirtualCacheView(image,exception);
1082 #if defined(MAGICKCORE_OPENMP_SUPPORT) 1083 #pragma omp parallel for schedule(static) shared(type) \ 1084 magick_number_threads(image,image,image->rows,2) 1086 for (y=0; y < (ssize_t) image->rows; y++)
1094 if (type == UndefinedType)
1096 p=GetCacheViewVirtualPixels(image_view,0,y,image->columns,1,exception);
1102 for (x=0; x < (ssize_t) image->columns; x++)
1104 if (IsPixelMonochrome(p) == MagickFalse)
1112 image_view=DestroyCacheView(image_view);
1113 return(type == BilevelType ? MagickTrue : MagickFalse);
1148 MagickExport ImageType IdentifyImageType(
const Image *image,
1151 assert(image != (
Image *) NULL);
1152 assert(image->signature == MagickCoreSignature);
1153 if (IsEventLogging() != MagickFalse)
1154 (void) LogMagickEvent(TraceEvent,GetMagickModule(),
"%s",image->filename);
1155 if (image->colorspace == CMYKColorspace)
1157 if (image->matte == MagickFalse)
1158 return(ColorSeparationType);
1159 return(ColorSeparationMatteType);
1161 if (IdentifyImageMonochrome(image,exception) != MagickFalse)
1162 return(BilevelType);
1163 if (IdentifyImageGray(image,exception) != UndefinedType)
1165 if (image->matte != MagickFalse)
1166 return(GrayscaleMatteType);
1167 return(GrayscaleType);
1169 if (IdentifyPaletteImage(image,exception) != MagickFalse)
1171 if (image->matte != MagickFalse)
1172 return(PaletteMatteType);
1173 return(PaletteType);
1175 if (image->matte != MagickFalse)
1176 return(TrueColorMatteType);
1177 return(TrueColorType);
1206 MagickExport MagickBooleanType IsGrayImage(
const Image *image,
1209 assert(image != (
Image *) NULL);
1210 assert(image->signature == MagickCoreSignature);
1211 magick_unreferenced(exception);
1212 if ((image->type == BilevelType) || (image->type == GrayscaleType) ||
1213 (image->type == GrayscaleMatteType))
1215 return(MagickFalse);
1243 MagickExport MagickBooleanType IsMonochromeImage(
const Image *image,
1246 assert(image != (
Image *) NULL);
1247 assert(image->signature == MagickCoreSignature);
1248 magick_unreferenced(exception);
1249 if (image->type == BilevelType)
1251 return(MagickFalse);
1280 MagickExport MagickBooleanType IsOpaqueImage(
const Image *image,
1287 opaque = MagickTrue;
1295 assert(image != (
Image *) NULL);
1296 assert(image->signature == MagickCoreSignature);
1297 if (IsEventLogging() != MagickFalse)
1298 (void) LogMagickEvent(TraceEvent,GetMagickModule(),
"%s",image->filename);
1299 if (image->matte == MagickFalse)
1301 image_view=AcquireVirtualCacheView(image,exception);
1302 #if defined(MAGICKCORE_OPENMP_SUPPORT) 1303 #pragma omp parallel for schedule(static) shared(opaque) \ 1304 magick_number_threads(image,image,image->rows,2) 1306 for (y=0; y < (ssize_t) image->rows; y++)
1314 if (opaque == MagickFalse)
1316 p=GetCacheViewVirtualPixels(image_view,0,y,image->columns,1,exception);
1322 for (x=0; x < (ssize_t) image->columns; x++)
1324 if (GetPixelOpacity(p) != OpaqueOpacity)
1332 image_view=DestroyCacheView(image_view);
1365 MagickExport MagickBooleanType SetImageDepth(
Image *image,
1368 return(SetImageChannelDepth(image,CompositeChannels,depth));
1371 MagickExport MagickBooleanType SetImageChannelDepth(
Image *image,
1372 const ChannelType channel,
const size_t depth)
1389 assert(image != (
Image *) NULL);
1390 if (IsEventLogging() != MagickFalse)
1391 (void) LogMagickEvent(TraceEvent,GetMagickModule(),
"...");
1392 assert(image->signature == MagickCoreSignature);
1393 if (depth >= MAGICKCORE_QUANTUM_DEPTH)
1398 range=GetQuantumRange(depth);
1399 if (image->storage_class == PseudoClass)
1404 #if defined(MAGICKCORE_OPENMP_SUPPORT) 1405 #pragma omp parallel for schedule(static) shared(status) \ 1406 magick_number_threads(image,image,image->rows,1) 1408 for (i=0; i < (ssize_t) image->colors; i++)
1410 if ((channel & RedChannel) != 0)
1411 image->colormap[i].red=ScaleAnyToQuantum(ScaleQuantumToAny(
1412 ClampPixel((MagickRealType) image->colormap[i].red),range),range);
1413 if ((channel & GreenChannel) != 0)
1414 image->colormap[i].green=ScaleAnyToQuantum(ScaleQuantumToAny(
1415 ClampPixel((MagickRealType) image->colormap[i].green),range),range);
1416 if ((channel & BlueChannel) != 0)
1417 image->colormap[i].blue=ScaleAnyToQuantum(ScaleQuantumToAny(
1418 ClampPixel((MagickRealType) image->colormap[i].blue),range),range);
1419 if ((channel & OpacityChannel) != 0)
1420 image->colormap[i].opacity=ScaleAnyToQuantum(ScaleQuantumToAny(
1421 ClampPixel((MagickRealType) image->colormap[i].opacity),range),
1426 exception=(&image->exception);
1427 image_view=AcquireAuthenticCacheView(image,exception);
1428 #if !defined(MAGICKCORE_HDRI_SUPPORT) 1429 DisableMSCWarning(4127)
1430 if (1UL*QuantumRange <= MaxMap)
1442 depth_map=(Quantum *) AcquireQuantumMemory(MaxMap+1,
sizeof(*depth_map));
1443 if (depth_map == (Quantum *) NULL)
1444 ThrowFatalException(ResourceLimitFatalError,
"MemoryAllocationFailed");
1445 for (i=0; i <= (ssize_t) MaxMap; i++)
1446 depth_map[i]=ScaleAnyToQuantum(ScaleQuantumToAny((Quantum) i,range),
1448 #if defined(MAGICKCORE_OPENMP_SUPPORT) 1449 #pragma omp parallel for schedule(static) shared(status) \ 1450 magick_number_threads(image,image,image->rows,2) 1452 for (y=0; y < (ssize_t) image->rows; y++)
1460 if (status == MagickFalse)
1462 q=GetCacheViewAuthenticPixels(image_view,0,y,image->columns,1,
1469 for (x=0; x < (ssize_t) image->columns; x++)
1471 if ((channel & RedChannel) != 0)
1472 SetPixelRed(q,depth_map[ScaleQuantumToMap(GetPixelRed(q))]);
1473 if ((channel & GreenChannel) != 0)
1474 SetPixelGreen(q,depth_map[ScaleQuantumToMap(GetPixelGreen(q))]);
1475 if ((channel & BlueChannel) != 0)
1476 SetPixelBlue(q,depth_map[ScaleQuantumToMap(GetPixelBlue(q))]);
1477 if (((channel & OpacityChannel) != 0) &&
1478 (image->matte != MagickFalse))
1479 SetPixelOpacity(q,depth_map[ScaleQuantumToMap(GetPixelOpacity(q))]);
1482 if (SyncCacheViewAuthenticPixels(image_view,exception) == MagickFalse)
1488 image_view=DestroyCacheView(image_view);
1489 depth_map=(Quantum *) RelinquishMagickMemory(depth_map);
1490 if (status != MagickFalse)
1498 #if defined(MAGICKCORE_OPENMP_SUPPORT) 1499 #pragma omp parallel for schedule(static) shared(status) \ 1500 magick_number_threads(image,image,image->rows,2) 1502 for (y=0; y < (ssize_t) image->rows; y++)
1510 if (status == MagickFalse)
1512 q=GetCacheViewAuthenticPixels(image_view,0,y,image->columns,1,exception);
1518 for (x=0; x < (ssize_t) image->columns; x++)
1520 if ((channel & RedChannel) != 0)
1521 SetPixelRed(q,ScaleAnyToQuantum(ScaleQuantumToAny(ClampPixel(
1522 (MagickRealType) GetPixelRed(q)),range),range));
1523 if ((channel & GreenChannel) != 0)
1524 SetPixelGreen(q,ScaleAnyToQuantum(ScaleQuantumToAny(ClampPixel(
1525 (MagickRealType) GetPixelGreen(q)),range),range));
1526 if ((channel & BlueChannel) != 0)
1527 SetPixelBlue(q,ScaleAnyToQuantum(ScaleQuantumToAny(ClampPixel(
1528 (MagickRealType) GetPixelBlue(q)),range),range));
1529 if (((channel & OpacityChannel) != 0) && (image->matte != MagickFalse))
1530 SetPixelOpacity(q,ScaleAnyToQuantum(ScaleQuantumToAny(ClampPixel(
1531 (MagickRealType) GetPixelOpacity(q)),range),range));
1534 if (SyncCacheViewAuthenticPixels(image_view,exception) == MagickFalse)
1540 image_view=DestroyCacheView(image_view);
1541 if (status != MagickFalse)
1574 MagickExport MagickBooleanType SetImageType(
Image *image,
const ImageType type)
1588 assert(image != (
Image *) NULL);
1589 if (IsEventLogging() != MagickFalse)
1590 (void) LogMagickEvent(TraceEvent,GetMagickModule(),
"...");
1591 assert(image->signature == MagickCoreSignature);
1593 image_info=AcquireImageInfo();
1594 image_info->dither=image->dither;
1595 artifact=GetImageArtifact(image,
"dither");
1596 if (artifact != (
const char *) NULL)
1597 (void) SetImageOption(image_info,
"dither",artifact);
1602 if (IsGrayColorspace(image->colorspace) == MagickFalse)
1603 status=TransformImageColorspace(image,GRAYColorspace);
1604 (void) NormalizeImage(image);
1605 (void) BilevelImage(image,(
double) QuantumRange/2.0);
1606 quantize_info=AcquireQuantizeInfo(image_info);
1607 quantize_info->number_colors=2;
1608 quantize_info->colorspace=GRAYColorspace;
1609 status=QuantizeImage(quantize_info,image);
1610 quantize_info=DestroyQuantizeInfo(quantize_info);
1611 image->matte=MagickFalse;
1616 if (IsGrayColorspace(image->colorspace) == MagickFalse)
1617 status=TransformImageColorspace(image,GRAYColorspace);
1618 image->matte=MagickFalse;
1621 case GrayscaleMatteType:
1623 if (IsGrayColorspace(image->colorspace) == MagickFalse)
1624 status=TransformImageColorspace(image,GRAYColorspace);
1625 if (image->matte == MagickFalse)
1626 (void) SetImageAlphaChannel(image,OpaqueAlphaChannel);
1631 if (IssRGBCompatibleColorspace(image->colorspace) == MagickFalse)
1632 status=TransformImageColorspace(image,sRGBColorspace);
1633 if ((image->storage_class == DirectClass) || (image->colors > 256))
1635 quantize_info=AcquireQuantizeInfo(image_info);
1636 quantize_info->number_colors=256;
1637 status=QuantizeImage(quantize_info,image);
1638 quantize_info=DestroyQuantizeInfo(quantize_info);
1640 image->matte=MagickFalse;
1643 case PaletteBilevelMatteType:
1645 if (IssRGBCompatibleColorspace(image->colorspace) == MagickFalse)
1646 status=TransformImageColorspace(image,sRGBColorspace);
1647 if (image->matte == MagickFalse)
1648 (void) SetImageAlphaChannel(image,OpaqueAlphaChannel);
1649 (void) BilevelImageChannel(image,AlphaChannel,(
double) QuantumRange/2.0);
1650 quantize_info=AcquireQuantizeInfo(image_info);
1651 status=QuantizeImage(quantize_info,image);
1652 quantize_info=DestroyQuantizeInfo(quantize_info);
1655 case PaletteMatteType:
1657 if (IssRGBCompatibleColorspace(image->colorspace) == MagickFalse)
1658 status=TransformImageColorspace(image,sRGBColorspace);
1659 if (image->matte == MagickFalse)
1660 (void) SetImageAlphaChannel(image,OpaqueAlphaChannel);
1661 quantize_info=AcquireQuantizeInfo(image_info);
1662 quantize_info->colorspace=TransparentColorspace;
1663 status=QuantizeImage(quantize_info,image);
1664 quantize_info=DestroyQuantizeInfo(quantize_info);
1669 if (IssRGBCompatibleColorspace(image->colorspace) == MagickFalse)
1670 status=TransformImageColorspace(image,sRGBColorspace);
1671 if (image->storage_class != DirectClass)
1672 status=SetImageStorageClass(image,DirectClass);
1673 image->matte=MagickFalse;
1676 case TrueColorMatteType:
1678 if (IssRGBCompatibleColorspace(image->colorspace) == MagickFalse)
1679 status=TransformImageColorspace(image,sRGBColorspace);
1680 if (image->storage_class != DirectClass)
1681 status=SetImageStorageClass(image,DirectClass);
1682 if (image->matte == MagickFalse)
1683 (void) SetImageAlphaChannel(image,OpaqueAlphaChannel);
1686 case ColorSeparationType:
1688 if (image->colorspace != CMYKColorspace)
1689 status=TransformImageColorspace(image,CMYKColorspace);
1690 if (image->storage_class != DirectClass)
1691 status=SetImageStorageClass(image,DirectClass);
1692 image->matte=MagickFalse;
1695 case ColorSeparationMatteType:
1697 if (image->colorspace != CMYKColorspace)
1698 status=TransformImageColorspace(image,CMYKColorspace);
1699 if (image->storage_class != DirectClass)
1700 status=SetImageStorageClass(image,DirectClass);
1701 if (image->matte == MagickFalse)
1702 (void) SetImageAlphaChannel(image,OpaqueAlphaChannel);
1709 image_info=DestroyImageInfo(image_info);
1710 if (status == MagickFalse)
1711 return(MagickFalse);