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 EdgeInfo *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,1)
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-=(bounds.x-1);
539 bounds.height-=(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,
992 assert(image != (
Image *) NULL);
993 assert(image->signature == MagickCoreSignature);
994 if (IsEventLogging() != MagickFalse)
995 (void) LogMagickEvent(TraceEvent,GetMagickModule(),
"%s",image->filename);
996 if ((image->type == BilevelType) || (image->type == GrayscaleType) ||
997 (image->type == GrayscaleMatteType))
999 if (IssRGBCompatibleColorspace(image->colorspace) == MagickFalse)
1000 return(UndefinedType);
1002 image_view=AcquireVirtualCacheView(image,exception);
1003 for (y=0; y < (ssize_t) image->rows; y++)
1005 p=GetCacheViewVirtualPixels(image_view,0,y,image->columns,1,exception);
1008 for (x=0; x < (ssize_t) image->columns; x++)
1010 if (IsPixelGray(p) == MagickFalse)
1015 if ((type == BilevelType) && (IsPixelMonochrome(p) == MagickFalse))
1019 if (type == UndefinedType)
1022 image_view=DestroyCacheView(image_view);
1023 if ((type == GrayscaleType) && (image->matte != MagickFalse))
1024 type=GrayscaleMatteType;
1055 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);
1082 image_view=AcquireVirtualCacheView(image,exception);
1083 for (y=0; y < (ssize_t) image->rows; y++)
1085 p=GetCacheViewVirtualPixels(image_view,0,y,image->columns,1,exception);
1088 for (x=0; x < (ssize_t) image->columns; x++)
1090 if (IsPixelMonochrome(p) == MagickFalse)
1097 if (type == UndefinedType)
1100 image_view=DestroyCacheView(image_view);
1101 if (type == BilevelType)
1103 return(MagickFalse);
1138 MagickExport ImageType IdentifyImageType(
const Image *image,
1141 assert(image != (
Image *) NULL);
1142 assert(image->signature == MagickCoreSignature);
1143 if (IsEventLogging() != MagickFalse)
1144 (void) LogMagickEvent(TraceEvent,GetMagickModule(),
"%s",image->filename);
1145 if (image->colorspace == CMYKColorspace)
1147 if (image->matte == MagickFalse)
1148 return(ColorSeparationType);
1149 return(ColorSeparationMatteType);
1151 if (IdentifyImageMonochrome(image,exception) != MagickFalse)
1152 return(BilevelType);
1153 if (IdentifyImageGray(image,exception) != UndefinedType)
1155 if (image->matte != MagickFalse)
1156 return(GrayscaleMatteType);
1157 return(GrayscaleType);
1159 if (IdentifyPaletteImage(image,exception) != MagickFalse)
1161 if (image->matte != MagickFalse)
1162 return(PaletteMatteType);
1163 return(PaletteType);
1165 if (image->matte != MagickFalse)
1166 return(TrueColorMatteType);
1167 return(TrueColorType);
1196 MagickExport MagickBooleanType IsGrayImage(
const Image *image,
1199 assert(image != (
Image *) NULL);
1200 assert(image->signature == MagickCoreSignature);
1201 magick_unreferenced(exception);
1202 if ((image->type == BilevelType) || (image->type == GrayscaleType) ||
1203 (image->type == GrayscaleMatteType))
1205 return(MagickFalse);
1233 MagickExport MagickBooleanType IsMonochromeImage(
const Image *image,
1236 assert(image != (
Image *) NULL);
1237 assert(image->signature == MagickCoreSignature);
1238 magick_unreferenced(exception);
1239 if (image->type == BilevelType)
1241 return(MagickFalse);
1270 MagickExport MagickBooleanType IsOpaqueImage(
const Image *image,
1288 assert(image != (
Image *) NULL);
1289 assert(image->signature == MagickCoreSignature);
1290 if (IsEventLogging() != MagickFalse)
1291 (void) LogMagickEvent(TraceEvent,GetMagickModule(),
"%s",image->filename);
1292 if (image->matte == MagickFalse)
1294 image_view=AcquireVirtualCacheView(image,exception);
1295 for (y=0; y < (ssize_t) image->rows; y++)
1297 p=GetCacheViewVirtualPixels(image_view,0,y,image->columns,1,exception);
1300 for (x=0; x < (ssize_t) image->columns; x++)
1302 if (GetPixelOpacity(p) != OpaqueOpacity)
1306 if (x < (ssize_t) image->columns)
1309 image_view=DestroyCacheView(image_view);
1310 return(y < (ssize_t) image->rows ? MagickFalse : MagickTrue);
1342 MagickExport MagickBooleanType SetImageDepth(
Image *image,
1345 return(SetImageChannelDepth(image,CompositeChannels,depth));
1348 MagickExport MagickBooleanType SetImageChannelDepth(
Image *image,
1349 const ChannelType channel,
const size_t depth)
1366 assert(image != (
Image *) NULL);
1367 if (IsEventLogging() != MagickFalse)
1368 (void) LogMagickEvent(TraceEvent,GetMagickModule(),
"...");
1369 assert(image->signature == MagickCoreSignature);
1370 if (depth >= MAGICKCORE_QUANTUM_DEPTH)
1375 range=GetQuantumRange(depth);
1376 if (image->storage_class == PseudoClass)
1381 #if defined(MAGICKCORE_OPENMP_SUPPORT)
1382 #pragma omp parallel for schedule(static) shared(status) \
1383 magick_number_threads(image,image,image->rows,1)
1385 for (i=0; i < (ssize_t) image->colors; i++)
1387 if ((channel & RedChannel) != 0)
1388 image->colormap[i].red=ScaleAnyToQuantum(ScaleQuantumToAny(
1389 ClampPixel((MagickRealType) image->colormap[i].red),range),range);
1390 if ((channel & GreenChannel) != 0)
1391 image->colormap[i].green=ScaleAnyToQuantum(ScaleQuantumToAny(
1392 ClampPixel((MagickRealType) image->colormap[i].green),range),range);
1393 if ((channel & BlueChannel) != 0)
1394 image->colormap[i].blue=ScaleAnyToQuantum(ScaleQuantumToAny(
1395 ClampPixel((MagickRealType) image->colormap[i].blue),range),range);
1396 if ((channel & OpacityChannel) != 0)
1397 image->colormap[i].opacity=ScaleAnyToQuantum(ScaleQuantumToAny(
1398 ClampPixel((MagickRealType) image->colormap[i].opacity),range),
1403 exception=(&image->exception);
1404 image_view=AcquireAuthenticCacheView(image,exception);
1405 #if !defined(MAGICKCORE_HDRI_SUPPORT)
1406 DisableMSCWarning(4127)
1407 if (1UL*QuantumRange <= MaxMap)
1419 depth_map=(Quantum *) AcquireQuantumMemory(MaxMap+1,
sizeof(*depth_map));
1420 if (depth_map == (Quantum *) NULL)
1421 ThrowFatalException(ResourceLimitFatalError,
"MemoryAllocationFailed");
1422 for (i=0; i <= (ssize_t) MaxMap; i++)
1423 depth_map[i]=ScaleAnyToQuantum(ScaleQuantumToAny((Quantum) i,range),
1425 #if defined(MAGICKCORE_OPENMP_SUPPORT)
1426 #pragma omp parallel for schedule(static) shared(status) \
1427 magick_number_threads(image,image,image->rows,1)
1429 for (y=0; y < (ssize_t) image->rows; y++)
1437 if (status == MagickFalse)
1439 q=GetCacheViewAuthenticPixels(image_view,0,y,image->columns,1,
1446 for (x=0; x < (ssize_t) image->columns; x++)
1448 if ((channel & RedChannel) != 0)
1449 SetPixelRed(q,depth_map[ScaleQuantumToMap(GetPixelRed(q))]);
1450 if ((channel & GreenChannel) != 0)
1451 SetPixelGreen(q,depth_map[ScaleQuantumToMap(GetPixelGreen(q))]);
1452 if ((channel & BlueChannel) != 0)
1453 SetPixelBlue(q,depth_map[ScaleQuantumToMap(GetPixelBlue(q))]);
1454 if (((channel & OpacityChannel) != 0) &&
1455 (image->matte != MagickFalse))
1456 SetPixelOpacity(q,depth_map[ScaleQuantumToMap(GetPixelOpacity(q))]);
1459 if (SyncCacheViewAuthenticPixels(image_view,exception) == MagickFalse)
1465 image_view=DestroyCacheView(image_view);
1466 depth_map=(Quantum *) RelinquishMagickMemory(depth_map);
1467 if (status != MagickFalse)
1475 #if defined(MAGICKCORE_OPENMP_SUPPORT)
1476 #pragma omp parallel for schedule(static) shared(status) \
1477 magick_number_threads(image,image,image->rows,1)
1479 for (y=0; y < (ssize_t) image->rows; y++)
1487 if (status == MagickFalse)
1489 q=GetCacheViewAuthenticPixels(image_view,0,y,image->columns,1,exception);
1495 for (x=0; x < (ssize_t) image->columns; x++)
1497 if ((channel & RedChannel) != 0)
1498 SetPixelRed(q,ScaleAnyToQuantum(ScaleQuantumToAny(ClampPixel(
1499 (MagickRealType) GetPixelRed(q)),range),range));
1500 if ((channel & GreenChannel) != 0)
1501 SetPixelGreen(q,ScaleAnyToQuantum(ScaleQuantumToAny(ClampPixel(
1502 (MagickRealType) GetPixelGreen(q)),range),range));
1503 if ((channel & BlueChannel) != 0)
1504 SetPixelBlue(q,ScaleAnyToQuantum(ScaleQuantumToAny(ClampPixel(
1505 (MagickRealType) GetPixelBlue(q)),range),range));
1506 if (((channel & OpacityChannel) != 0) && (image->matte != MagickFalse))
1507 SetPixelOpacity(q,ScaleAnyToQuantum(ScaleQuantumToAny(ClampPixel(
1508 (MagickRealType) GetPixelOpacity(q)),range),range));
1511 if (SyncCacheViewAuthenticPixels(image_view,exception) == MagickFalse)
1517 image_view=DestroyCacheView(image_view);
1518 if (status != MagickFalse)
1551 MagickExport MagickBooleanType SetImageType(
Image *image,
const ImageType type)
1565 assert(image != (
Image *) NULL);
1566 if (IsEventLogging() != MagickFalse)
1567 (void) LogMagickEvent(TraceEvent,GetMagickModule(),
"...");
1568 assert(image->signature == MagickCoreSignature);
1570 image_info=AcquireImageInfo();
1571 image_info->dither=image->dither;
1572 artifact=GetImageArtifact(image,
"dither");
1573 if (artifact != (
const char *) NULL)
1574 (void) SetImageOption(image_info,
"dither",artifact);
1579 if (IsGrayColorspace(image->colorspace) == MagickFalse)
1580 status=TransformImageColorspace(image,GRAYColorspace);
1581 (void) NormalizeImage(image);
1582 (void) BilevelImage(image,(
double) QuantumRange/2.0);
1583 quantize_info=AcquireQuantizeInfo(image_info);
1584 quantize_info->number_colors=2;
1585 quantize_info->colorspace=GRAYColorspace;
1586 status=QuantizeImage(quantize_info,image);
1587 quantize_info=DestroyQuantizeInfo(quantize_info);
1588 image->matte=MagickFalse;
1593 if (IsGrayColorspace(image->colorspace) == MagickFalse)
1594 status=TransformImageColorspace(image,GRAYColorspace);
1595 image->matte=MagickFalse;
1598 case GrayscaleMatteType:
1600 if (IsGrayColorspace(image->colorspace) == MagickFalse)
1601 status=TransformImageColorspace(image,GRAYColorspace);
1602 if (image->matte == MagickFalse)
1603 (void) SetImageAlphaChannel(image,OpaqueAlphaChannel);
1608 if (IssRGBCompatibleColorspace(image->colorspace) == MagickFalse)
1609 status=TransformImageColorspace(image,sRGBColorspace);
1610 if ((image->storage_class == DirectClass) || (image->colors > 256))
1612 quantize_info=AcquireQuantizeInfo(image_info);
1613 quantize_info->number_colors=256;
1614 status=QuantizeImage(quantize_info,image);
1615 quantize_info=DestroyQuantizeInfo(quantize_info);
1617 image->matte=MagickFalse;
1620 case PaletteBilevelMatteType:
1622 if (IssRGBCompatibleColorspace(image->colorspace) == MagickFalse)
1623 status=TransformImageColorspace(image,sRGBColorspace);
1624 if (image->matte == MagickFalse)
1625 (void) SetImageAlphaChannel(image,OpaqueAlphaChannel);
1626 (void) BilevelImageChannel(image,AlphaChannel,(
double) QuantumRange/2.0);
1627 quantize_info=AcquireQuantizeInfo(image_info);
1628 status=QuantizeImage(quantize_info,image);
1629 quantize_info=DestroyQuantizeInfo(quantize_info);
1632 case PaletteMatteType:
1634 if (IssRGBCompatibleColorspace(image->colorspace) == MagickFalse)
1635 status=TransformImageColorspace(image,sRGBColorspace);
1636 if (image->matte == MagickFalse)
1637 (void) SetImageAlphaChannel(image,OpaqueAlphaChannel);
1638 quantize_info=AcquireQuantizeInfo(image_info);
1639 quantize_info->colorspace=TransparentColorspace;
1640 status=QuantizeImage(quantize_info,image);
1641 quantize_info=DestroyQuantizeInfo(quantize_info);
1646 if (IssRGBCompatibleColorspace(image->colorspace) == MagickFalse)
1647 status=TransformImageColorspace(image,sRGBColorspace);
1648 if (image->storage_class != DirectClass)
1649 status=SetImageStorageClass(image,DirectClass);
1650 image->matte=MagickFalse;
1653 case TrueColorMatteType:
1655 if (IssRGBCompatibleColorspace(image->colorspace) == MagickFalse)
1656 status=TransformImageColorspace(image,sRGBColorspace);
1657 if (image->storage_class != DirectClass)
1658 status=SetImageStorageClass(image,DirectClass);
1659 if (image->matte == MagickFalse)
1660 (void) SetImageAlphaChannel(image,OpaqueAlphaChannel);
1663 case ColorSeparationType:
1665 if (image->colorspace != CMYKColorspace)
1666 status=TransformImageColorspace(image,CMYKColorspace);
1667 if (image->storage_class != DirectClass)
1668 status=SetImageStorageClass(image,DirectClass);
1669 image->matte=MagickFalse;
1672 case ColorSeparationMatteType:
1674 if (image->colorspace != CMYKColorspace)
1675 status=TransformImageColorspace(image,CMYKColorspace);
1676 if (image->storage_class != DirectClass)
1677 status=SetImageStorageClass(image,DirectClass);
1678 if (image->matte == MagickFalse)
1679 (void) SetImageAlphaChannel(image,OpaqueAlphaChannel);
1686 image_info=DestroyImageInfo(image_info);
1687 if (status == MagickFalse)
1688 return(MagickFalse);