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"
136static 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);
243static 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));
577MagickExport
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)
657DisableMSCWarning(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);
864MagickExport
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);
974MagickExport ImageType IdentifyImageGray(
const Image *image,
989 assert(image != (
Image *) NULL);
990 assert(image->signature == MagickCoreSignature);
991 if (IsEventLogging() != MagickFalse)
992 (void) LogMagickEvent(TraceEvent,GetMagickModule(),
"%s",image->filename);
993 if ((image->type == BilevelType) || (image->type == GrayscaleType) ||
994 (image->type == GrayscaleMatteType))
996 if (IssRGBCompatibleColorspace(image->colorspace) == MagickFalse)
997 return(UndefinedType);
998 image_view=AcquireVirtualCacheView(image,exception);
999#if defined(MAGICKCORE_OPENMP_SUPPORT)
1000 #pragma omp parallel for schedule(static) shared(status,type) \
1001 magick_number_threads(image,image,image->rows,2)
1003 for (y=0; y < (ssize_t) image->rows; y++)
1011 if (status == MagickFalse)
1013 p=GetCacheViewVirtualPixels(image_view,0,y,image->columns,1,exception);
1019 for (x=0; x < (ssize_t) image->columns; x++)
1021 if (IsPixelGray(p) == MagickFalse)
1026 if ((type == BilevelType) && (IsPixelMonochrome(p) == MagickFalse))
1031 image_view=DestroyCacheView(image_view);
1032 if ((type == GrayscaleType) && (image->matte != MagickFalse))
1033 type=GrayscaleMatteType;
1034 if (status == MagickFalse)
1035 return(UndefinedType);
1066MagickExport MagickBooleanType IdentifyImageMonochrome(
const Image *image,
1078 assert(image != (
Image *) NULL);
1079 assert(image->signature == MagickCoreSignature);
1080 if (IsEventLogging() != MagickFalse)
1081 (void) LogMagickEvent(TraceEvent,GetMagickModule(),
"%s",image->filename);
1082 if (image->type == BilevelType)
1084 if (IssRGBCompatibleColorspace(image->colorspace) == MagickFalse)
1085 return(MagickFalse);
1086 image_view=AcquireVirtualCacheView(image,exception);
1087#if defined(MAGICKCORE_OPENMP_SUPPORT)
1088 #pragma omp parallel for schedule(static) shared(type) \
1089 magick_number_threads(image,image,image->rows,2)
1091 for (y=0; y < (ssize_t) image->rows; y++)
1099 if (type == UndefinedType)
1101 p=GetCacheViewVirtualPixels(image_view,0,y,image->columns,1,exception);
1107 for (x=0; x < (ssize_t) image->columns; x++)
1109 if (IsPixelMonochrome(p) == MagickFalse)
1117 image_view=DestroyCacheView(image_view);
1118 return(type == BilevelType ? MagickTrue : MagickFalse);
1153MagickExport ImageType IdentifyImageType(
const Image *image,
1156 assert(image != (
Image *) NULL);
1157 assert(image->signature == MagickCoreSignature);
1158 if (IsEventLogging() != MagickFalse)
1159 (void) LogMagickEvent(TraceEvent,GetMagickModule(),
"%s",image->filename);
1160 if (image->colorspace == CMYKColorspace)
1162 if (image->matte == MagickFalse)
1163 return(ColorSeparationType);
1164 return(ColorSeparationMatteType);
1166 if (IdentifyImageMonochrome(image,exception) != MagickFalse)
1167 return(BilevelType);
1168 if (IdentifyImageGray(image,exception) != UndefinedType)
1170 if (image->matte != MagickFalse)
1171 return(GrayscaleMatteType);
1172 return(GrayscaleType);
1174 if (IdentifyPaletteImage(image,exception) != MagickFalse)
1176 if (image->matte != MagickFalse)
1177 return(PaletteMatteType);
1178 return(PaletteType);
1180 if (image->matte != MagickFalse)
1181 return(TrueColorMatteType);
1182 return(TrueColorType);
1211MagickExport MagickBooleanType IsGrayImage(
const Image *image,
1214 assert(image != (
Image *) NULL);
1215 assert(image->signature == MagickCoreSignature);
1216 magick_unreferenced(exception);
1217 if ((image->type == BilevelType) || (image->type == GrayscaleType) ||
1218 (image->type == GrayscaleMatteType))
1220 return(MagickFalse);
1248MagickExport MagickBooleanType IsMonochromeImage(
const Image *image,
1251 assert(image != (
Image *) NULL);
1252 assert(image->signature == MagickCoreSignature);
1253 magick_unreferenced(exception);
1254 if (image->type == BilevelType)
1256 return(MagickFalse);
1285MagickExport MagickBooleanType IsOpaqueImage(
const Image *image,
1292 opaque = MagickTrue;
1300 assert(image != (
Image *) NULL);
1301 assert(image->signature == MagickCoreSignature);
1302 if (IsEventLogging() != MagickFalse)
1303 (void) LogMagickEvent(TraceEvent,GetMagickModule(),
"%s",image->filename);
1304 if (image->matte == MagickFalse)
1306 image_view=AcquireVirtualCacheView(image,exception);
1307#if defined(MAGICKCORE_OPENMP_SUPPORT)
1308 #pragma omp parallel for schedule(static) shared(opaque) \
1309 magick_number_threads(image,image,image->rows,2)
1311 for (y=0; y < (ssize_t) image->rows; y++)
1319 if (opaque == MagickFalse)
1321 p=GetCacheViewVirtualPixels(image_view,0,y,image->columns,1,exception);
1327 for (x=0; x < (ssize_t) image->columns; x++)
1329 if (GetPixelOpacity(p) != OpaqueOpacity)
1337 image_view=DestroyCacheView(image_view);
1370MagickExport MagickBooleanType SetImageDepth(
Image *image,
1373 return(SetImageChannelDepth(image,CompositeChannels,depth));
1376MagickExport MagickBooleanType SetImageChannelDepth(
Image *image,
1377 const ChannelType channel,
const size_t depth)
1394 assert(image != (
Image *) NULL);
1395 if (IsEventLogging() != MagickFalse)
1396 (void) LogMagickEvent(TraceEvent,GetMagickModule(),
"...");
1397 assert(image->signature == MagickCoreSignature);
1398 if (depth >= MAGICKCORE_QUANTUM_DEPTH)
1403 range=GetQuantumRange(depth);
1404 if (image->storage_class == PseudoClass)
1409#if defined(MAGICKCORE_OPENMP_SUPPORT)
1410 #pragma omp parallel for schedule(static) shared(status) \
1411 magick_number_threads(image,image,image->rows,1)
1413 for (i=0; i < (ssize_t) image->colors; i++)
1415 if ((channel & RedChannel) != 0)
1416 image->colormap[i].red=ScaleAnyToQuantum(ScaleQuantumToAny(
1417 ClampPixel((MagickRealType) image->colormap[i].red),range),range);
1418 if ((channel & GreenChannel) != 0)
1419 image->colormap[i].green=ScaleAnyToQuantum(ScaleQuantumToAny(
1420 ClampPixel((MagickRealType) image->colormap[i].green),range),range);
1421 if ((channel & BlueChannel) != 0)
1422 image->colormap[i].blue=ScaleAnyToQuantum(ScaleQuantumToAny(
1423 ClampPixel((MagickRealType) image->colormap[i].blue),range),range);
1424 if ((channel & OpacityChannel) != 0)
1425 image->colormap[i].opacity=ScaleAnyToQuantum(ScaleQuantumToAny(
1426 ClampPixel((MagickRealType) image->colormap[i].opacity),range),
1431 exception=(&image->exception);
1432 image_view=AcquireAuthenticCacheView(image,exception);
1433#if !defined(MAGICKCORE_HDRI_SUPPORT)
1434DisableMSCWarning(4127)
1435 if (1UL*QuantumRange <= MaxMap)
1447 depth_map=(Quantum *) AcquireQuantumMemory(MaxMap+1,
sizeof(*depth_map));
1448 if (depth_map == (Quantum *) NULL)
1449 ThrowFatalException(ResourceLimitFatalError,
"MemoryAllocationFailed");
1450 for (i=0; i <= (ssize_t) MaxMap; i++)
1451 depth_map[i]=ScaleAnyToQuantum(ScaleQuantumToAny((Quantum) i,range),
1453#if defined(MAGICKCORE_OPENMP_SUPPORT)
1454 #pragma omp parallel for schedule(static) shared(status) \
1455 magick_number_threads(image,image,image->rows,2)
1457 for (y=0; y < (ssize_t) image->rows; y++)
1465 if (status == MagickFalse)
1467 q=GetCacheViewAuthenticPixels(image_view,0,y,image->columns,1,
1474 for (x=0; x < (ssize_t) image->columns; x++)
1476 if ((channel & RedChannel) != 0)
1477 SetPixelRed(q,depth_map[ScaleQuantumToMap(GetPixelRed(q))]);
1478 if ((channel & GreenChannel) != 0)
1479 SetPixelGreen(q,depth_map[ScaleQuantumToMap(GetPixelGreen(q))]);
1480 if ((channel & BlueChannel) != 0)
1481 SetPixelBlue(q,depth_map[ScaleQuantumToMap(GetPixelBlue(q))]);
1482 if (((channel & OpacityChannel) != 0) &&
1483 (image->matte != MagickFalse))
1484 SetPixelOpacity(q,depth_map[ScaleQuantumToMap(GetPixelOpacity(q))]);
1487 if (SyncCacheViewAuthenticPixels(image_view,exception) == MagickFalse)
1493 image_view=DestroyCacheView(image_view);
1494 depth_map=(Quantum *) RelinquishMagickMemory(depth_map);
1495 if (status != MagickFalse)
1503#if defined(MAGICKCORE_OPENMP_SUPPORT)
1504 #pragma omp parallel for schedule(static) shared(status) \
1505 magick_number_threads(image,image,image->rows,2)
1507 for (y=0; y < (ssize_t) image->rows; y++)
1515 if (status == MagickFalse)
1517 q=GetCacheViewAuthenticPixels(image_view,0,y,image->columns,1,exception);
1523 for (x=0; x < (ssize_t) image->columns; x++)
1525 if ((channel & RedChannel) != 0)
1526 SetPixelRed(q,ScaleAnyToQuantum(ScaleQuantumToAny(ClampPixel(
1527 (MagickRealType) GetPixelRed(q)),range),range));
1528 if ((channel & GreenChannel) != 0)
1529 SetPixelGreen(q,ScaleAnyToQuantum(ScaleQuantumToAny(ClampPixel(
1530 (MagickRealType) GetPixelGreen(q)),range),range));
1531 if ((channel & BlueChannel) != 0)
1532 SetPixelBlue(q,ScaleAnyToQuantum(ScaleQuantumToAny(ClampPixel(
1533 (MagickRealType) GetPixelBlue(q)),range),range));
1534 if (((channel & OpacityChannel) != 0) && (image->matte != MagickFalse))
1535 SetPixelOpacity(q,ScaleAnyToQuantum(ScaleQuantumToAny(ClampPixel(
1536 (MagickRealType) GetPixelOpacity(q)),range),range));
1539 if (SyncCacheViewAuthenticPixels(image_view,exception) == MagickFalse)
1545 image_view=DestroyCacheView(image_view);
1546 if (status != MagickFalse)
1579MagickExport MagickBooleanType SetImageType(
Image *image,
const ImageType type)
1593 assert(image != (
Image *) NULL);
1594 if (IsEventLogging() != MagickFalse)
1595 (void) LogMagickEvent(TraceEvent,GetMagickModule(),
"...");
1596 assert(image->signature == MagickCoreSignature);
1598 image_info=AcquireImageInfo();
1599 image_info->dither=image->dither;
1600 artifact=GetImageArtifact(image,
"dither");
1601 if (artifact != (
const char *) NULL)
1602 (void) SetImageOption(image_info,
"dither",artifact);
1607 if (IsGrayColorspace(image->colorspace) == MagickFalse)
1608 status=TransformImageColorspace(image,GRAYColorspace);
1609 (void) NormalizeImage(image);
1610 (void) BilevelImage(image,(
double) QuantumRange/2.0);
1611 quantize_info=AcquireQuantizeInfo(image_info);
1612 quantize_info->number_colors=2;
1613 quantize_info->colorspace=GRAYColorspace;
1614 status=QuantizeImage(quantize_info,image);
1615 quantize_info=DestroyQuantizeInfo(quantize_info);
1616 image->matte=MagickFalse;
1621 if (IsGrayColorspace(image->colorspace) == MagickFalse)
1622 status=TransformImageColorspace(image,GRAYColorspace);
1623 image->matte=MagickFalse;
1626 case GrayscaleMatteType:
1628 if (IsGrayColorspace(image->colorspace) == MagickFalse)
1629 status=TransformImageColorspace(image,GRAYColorspace);
1630 if (image->matte == MagickFalse)
1631 (void) SetImageAlphaChannel(image,OpaqueAlphaChannel);
1636 if (IssRGBCompatibleColorspace(image->colorspace) == MagickFalse)
1637 status=TransformImageColorspace(image,sRGBColorspace);
1638 if ((image->storage_class == DirectClass) || (image->colors > 256))
1640 quantize_info=AcquireQuantizeInfo(image_info);
1641 quantize_info->number_colors=256;
1642 status=QuantizeImage(quantize_info,image);
1643 quantize_info=DestroyQuantizeInfo(quantize_info);
1645 image->matte=MagickFalse;
1648 case PaletteBilevelMatteType:
1650 if (IssRGBCompatibleColorspace(image->colorspace) == MagickFalse)
1651 status=TransformImageColorspace(image,sRGBColorspace);
1652 if (image->matte == MagickFalse)
1653 (void) SetImageAlphaChannel(image,OpaqueAlphaChannel);
1654 (void) BilevelImageChannel(image,AlphaChannel,(
double) QuantumRange/2.0);
1655 quantize_info=AcquireQuantizeInfo(image_info);
1656 status=QuantizeImage(quantize_info,image);
1657 quantize_info=DestroyQuantizeInfo(quantize_info);
1660 case PaletteMatteType:
1662 if (IssRGBCompatibleColorspace(image->colorspace) == MagickFalse)
1663 status=TransformImageColorspace(image,sRGBColorspace);
1664 if (image->matte == MagickFalse)
1665 (void) SetImageAlphaChannel(image,OpaqueAlphaChannel);
1666 quantize_info=AcquireQuantizeInfo(image_info);
1667 quantize_info->colorspace=TransparentColorspace;
1668 status=QuantizeImage(quantize_info,image);
1669 quantize_info=DestroyQuantizeInfo(quantize_info);
1674 if (IssRGBCompatibleColorspace(image->colorspace) == MagickFalse)
1675 status=TransformImageColorspace(image,sRGBColorspace);
1676 if (image->storage_class != DirectClass)
1677 status=SetImageStorageClass(image,DirectClass);
1678 image->matte=MagickFalse;
1681 case TrueColorMatteType:
1683 if (IssRGBCompatibleColorspace(image->colorspace) == MagickFalse)
1684 status=TransformImageColorspace(image,sRGBColorspace);
1685 if (image->storage_class != DirectClass)
1686 status=SetImageStorageClass(image,DirectClass);
1687 if (image->matte == MagickFalse)
1688 (void) SetImageAlphaChannel(image,OpaqueAlphaChannel);
1691 case ColorSeparationType:
1693 if (image->colorspace != CMYKColorspace)
1694 status=TransformImageColorspace(image,CMYKColorspace);
1695 if (image->storage_class != DirectClass)
1696 status=SetImageStorageClass(image,DirectClass);
1697 image->matte=MagickFalse;
1700 case ColorSeparationMatteType:
1702 if (image->colorspace != CMYKColorspace)
1703 status=TransformImageColorspace(image,CMYKColorspace);
1704 if (image->storage_class != DirectClass)
1705 status=SetImageStorageClass(image,DirectClass);
1706 if (image->matte == MagickFalse)
1707 (void) SetImageAlphaChannel(image,OpaqueAlphaChannel);
1714 image_info=DestroyImageInfo(image_info);
1715 if (status == MagickFalse)
1716 return(MagickFalse);