43#include "MagickCore/studio.h"
44#include "MagickCore/artifact.h"
45#include "MagickCore/attribute.h"
46#include "MagickCore/blob.h"
47#include "MagickCore/blob-private.h"
48#include "MagickCore/cache.h"
49#include "MagickCore/cache-private.h"
50#include "MagickCore/cache-view.h"
51#include "MagickCore/channel.h"
52#include "MagickCore/client.h"
53#include "MagickCore/color.h"
54#include "MagickCore/color-private.h"
55#include "MagickCore/colormap.h"
56#include "MagickCore/colormap-private.h"
57#include "MagickCore/colorspace.h"
58#include "MagickCore/colorspace-private.h"
59#include "MagickCore/composite.h"
60#include "MagickCore/composite-private.h"
61#include "MagickCore/constitute.h"
62#include "MagickCore/draw.h"
63#include "MagickCore/draw-private.h"
64#include "MagickCore/effect.h"
65#include "MagickCore/enhance.h"
66#include "MagickCore/exception.h"
67#include "MagickCore/exception-private.h"
68#include "MagickCore/geometry.h"
69#include "MagickCore/histogram.h"
70#include "MagickCore/identify.h"
71#include "MagickCore/image.h"
72#include "MagickCore/image-private.h"
73#include "MagickCore/list.h"
74#include "MagickCore/log.h"
75#include "MagickCore/memory_.h"
76#include "MagickCore/magick.h"
77#include "MagickCore/monitor.h"
78#include "MagickCore/monitor-private.h"
79#include "MagickCore/option.h"
80#include "MagickCore/paint.h"
81#include "MagickCore/pixel.h"
82#include "MagickCore/pixel-accessor.h"
83#include "MagickCore/property.h"
84#include "MagickCore/quantize.h"
85#include "MagickCore/quantum-private.h"
86#include "MagickCore/random_.h"
87#include "MagickCore/resource_.h"
88#include "MagickCore/semaphore.h"
89#include "MagickCore/segment.h"
90#include "MagickCore/splay-tree.h"
91#include "MagickCore/string_.h"
92#include "MagickCore/string-private.h"
93#include "MagickCore/thread-private.h"
94#include "MagickCore/threshold.h"
95#include "MagickCore/transform.h"
96#include "MagickCore/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,
200 if (p == (
const Quantum *) NULL)
202 GetPixelInfoPixel(image,p,&background);
203 artifact=GetImageArtifact(image,
"background");
204 if (artifact != (
const char *) NULL)
205 (void) QueryColorCompliance(artifact,AllCompliance,&background,exception);
206 artifact=GetImageArtifact(image,
"trim:background-color");
207 if (artifact != (
const char *) NULL)
208 (void) QueryColorCompliance(artifact,AllCompliance,&background,exception);
209 edge_geometry.width=width;
210 edge_geometry.height=height;
211 edge_geometry.x=x_offset;
212 edge_geometry.y=y_offset;
213 GravityAdjustGeometry(image->columns,image->rows,gravity,&edge_geometry);
214 edge_image=CropImage(image,&edge_geometry,exception);
215 if (edge_image == (
Image *) NULL)
218 edge_view=AcquireVirtualCacheView(edge_image,exception);
219 for (y=0; y < (ssize_t) edge_image->rows; y++)
224 p=GetCacheViewVirtualPixels(edge_view,0,y,edge_image->columns,1,exception);
225 if (p == (
const Quantum *) NULL)
227 for (x=0; x < (ssize_t) edge_image->columns; x++)
229 GetPixelInfoPixel(edge_image,p,&pixel);
230 if (IsFuzzyEquivalencePixelInfo(&pixel,&background) == MagickFalse)
232 p+=GetPixelChannels(edge_image);
235 census/=((double) edge_image->columns*edge_image->rows);
236 edge_view=DestroyCacheView(edge_view);
237 edge_image=DestroyImage(edge_image);
241static inline double GetMinEdgeBackgroundCensus(
const CensusInfo *edge)
246 census=MagickMin(MagickMin(MagickMin(edge->left,edge->right),edge->top),
277 assert(image != (
Image *) NULL);
278 assert(image->signature == MagickCoreSignature);
279 if (IsEventLogging() != MagickFalse)
280 (void) LogMagickEvent(TraceEvent,GetMagickModule(),
"%s",image->filename);
281 SetGeometry(image,&bounds);
282 edge_image=CloneImage(image,0,0,MagickTrue,exception);
283 if (edge_image == (
Image *) NULL)
285 (void) ParseAbsoluteGeometry(
"0x0+0+0",&edge_image->page);
286 (void) memset(&vertex,0,
sizeof(vertex));
287 edge_view=AcquireVirtualCacheView(edge_image,exception);
288 edge.left=GetEdgeBackgroundCensus(edge_image,edge_view,WestGravity,
290 edge.right=GetEdgeBackgroundCensus(edge_image,edge_view,EastGravity,
292 edge.top=GetEdgeBackgroundCensus(edge_image,edge_view,NorthGravity,
294 edge.bottom=GetEdgeBackgroundCensus(edge_image,edge_view,SouthGravity,
296 percent_background=1.0;
297 artifact=GetImageArtifact(edge_image,
"trim:percent-background");
298 if (artifact != (
const char *) NULL)
299 percent_background=StringToDouble(artifact,(
char **) NULL)/100.0;
300 percent_background=MagickMin(MagickMax(1.0-percent_background,MagickEpsilon),
302 background_census=GetMinEdgeBackgroundCensus(&edge);
303 for ( ; background_census < percent_background;
304 background_census=GetMinEdgeBackgroundCensus(&edge))
306 if ((bounds.width == 0) || (bounds.height == 0))
308 if (fabs(edge.left-background_census) < MagickEpsilon)
315 edge.left=GetEdgeBackgroundCensus(edge_image,edge_view,
316 NorthWestGravity,1,bounds.height,(ssize_t) vertex.left,(ssize_t)
317 vertex.top,exception);
318 edge.top=GetEdgeBackgroundCensus(edge_image,edge_view,
319 NorthWestGravity,bounds.width,1,(ssize_t) vertex.left,(ssize_t)
320 vertex.top,exception);
321 edge.bottom=GetEdgeBackgroundCensus(edge_image,edge_view,
322 SouthWestGravity,bounds.width,1,(ssize_t) vertex.left,(ssize_t)
323 vertex.bottom,exception);
326 if (fabs(edge.right-background_census) < MagickEpsilon)
333 edge.right=GetEdgeBackgroundCensus(edge_image,edge_view,
334 NorthEastGravity,1,bounds.height,(ssize_t) vertex.right,(ssize_t)
335 vertex.top,exception);
336 edge.top=GetEdgeBackgroundCensus(edge_image,edge_view,
337 NorthWestGravity,bounds.width,1,(ssize_t) vertex.left,(ssize_t)
338 vertex.top,exception);
339 edge.bottom=GetEdgeBackgroundCensus(edge_image,edge_view,
340 SouthWestGravity,bounds.width,1,(ssize_t) vertex.left,(ssize_t)
341 vertex.bottom,exception);
344 if (fabs(edge.top-background_census) < MagickEpsilon)
351 edge.left=GetEdgeBackgroundCensus(edge_image,edge_view,
352 NorthWestGravity,1,bounds.height,(ssize_t) vertex.left,(ssize_t)
353 vertex.top,exception);
354 edge.right=GetEdgeBackgroundCensus(edge_image,edge_view,
355 NorthEastGravity,1,bounds.height,(ssize_t) vertex.right,(ssize_t)
356 vertex.top,exception);
357 edge.top=GetEdgeBackgroundCensus(edge_image,edge_view,
358 NorthWestGravity,bounds.width,1,(ssize_t) vertex.left,(ssize_t)
359 vertex.top,exception);
362 if (fabs(edge.bottom-background_census) < MagickEpsilon)
369 edge.left=GetEdgeBackgroundCensus(edge_image,edge_view,
370 NorthWestGravity,1,bounds.height,(ssize_t) vertex.left,(ssize_t)
371 vertex.top,exception);
372 edge.right=GetEdgeBackgroundCensus(edge_image,edge_view,
373 NorthEastGravity,1,bounds.height,(ssize_t) vertex.right,(ssize_t)
374 vertex.top,exception);
375 edge.bottom=GetEdgeBackgroundCensus(edge_image,edge_view,
376 SouthWestGravity,bounds.width,1,(ssize_t) vertex.left,(ssize_t)
377 vertex.bottom,exception);
381 edge_view=DestroyCacheView(edge_view);
382 edge_image=DestroyImage(edge_image);
383 bounds.x=(ssize_t) vertex.left;
384 bounds.y=(ssize_t) vertex.top;
385 if ((bounds.width == 0) || (bounds.height == 0))
386 (void) ThrowMagickException(exception,GetMagickModule(),OptionWarning,
387 "GeometryDoesNotContainImage",
"`%s'",image->filename);
416 assert(image != (
Image *) NULL);
417 assert(image->signature == MagickCoreSignature);
418 if (IsEventLogging() != MagickFalse)
419 (void) LogMagickEvent(TraceEvent,GetMagickModule(),
"%s",image->filename);
420 artifact=GetImageArtifact(image,
"trim:percent-background");
421 if (artifact != (
const char *) NULL)
422 return(GetEdgeBoundingBox(image,exception));
423 artifact=GetImageArtifact(image,
"trim:edges");
424 if (artifact == (
const char *) NULL)
426 bounds.width=(size_t) (image->columns == 1 ? 1 : 0);
427 bounds.height=(size_t) (image->rows == 1 ? 1 : 0);
428 bounds.x=(ssize_t) image->columns;
429 bounds.y=(ssize_t) image->rows;
438 bounds.width=(size_t) image->columns;
439 bounds.height=(size_t) image->rows;
442 edges=AcquireString(artifact);
444 while ((q=StringToken(
",",&r)) != (
char *) NULL)
446 if (LocaleCompare(q,
"north") == 0)
447 bounds.y=(ssize_t) image->rows;
448 if (LocaleCompare(q,
"east") == 0)
450 if (LocaleCompare(q,
"south") == 0)
452 if (LocaleCompare(q,
"west") == 0)
453 bounds.x=(ssize_t) image->columns;
455 edges=DestroyString(edges);
457 GetPixelInfo(image,&target[0]);
458 image_view=AcquireVirtualCacheView(image,exception);
459 p=GetCacheViewVirtualPixels(image_view,0,0,1,1,exception);
460 if (p == (
const Quantum *) NULL)
462 image_view=DestroyCacheView(image_view);
465 GetPixelInfoPixel(image,p,&target[0]);
466 GetPixelInfo(image,&target[1]);
467 p=GetCacheViewVirtualPixels(image_view,(ssize_t) image->columns-1,0,1,1,
469 if (p != (
const Quantum *) NULL)
470 GetPixelInfoPixel(image,p,&target[1]);
471 GetPixelInfo(image,&target[2]);
472 p=GetCacheViewVirtualPixels(image_view,0,(ssize_t) image->rows-1,1,1,
474 if (p != (
const Quantum *) NULL)
475 GetPixelInfoPixel(image,p,&target[2]);
476 GetPixelInfo(image,&target[3]);
477 p=GetCacheViewVirtualPixels(image_view,(ssize_t) image->columns-1,(ssize_t)
478 image->rows-1,1,1,exception);
479 if (p != (
const Quantum *) NULL)
480 GetPixelInfoPixel(image,p,&target[3]);
482 GetPixelInfo(image,&zero);
483#if defined(MAGICKCORE_OPENMP_SUPPORT)
484 #pragma omp parallel for schedule(static) shared(status) \
485 magick_number_threads(image,image,image->rows,2)
487 for (y=0; y < (ssize_t) image->rows; y++)
501 if (status == MagickFalse)
503#if defined(MAGICKCORE_OPENMP_SUPPORT)
504# pragma omp critical (MagickCore_GetImageBoundingBox)
507 q=GetCacheViewVirtualPixels(image_view,0,y,image->columns,1,exception);
508 if (q == (
const Quantum *) NULL)
514 for (x=0; x < (ssize_t) image->columns; x++)
516 GetPixelInfoPixel(image,q,&pixel);
517 if ((x < bounding_box.x) &&
518 (IsFuzzyEquivalencePixelInfo(&pixel,&target[0]) == MagickFalse))
520 if ((x > (ssize_t) bounding_box.width) &&
521 (IsFuzzyEquivalencePixelInfo(&pixel,&target[1]) == MagickFalse))
522 bounding_box.width=(size_t) x;
523 if ((y < bounding_box.y) &&
524 (IsFuzzyEquivalencePixelInfo(&pixel,&target[0]) == MagickFalse))
526 if ((y > (ssize_t) bounding_box.height) &&
527 (IsFuzzyEquivalencePixelInfo(&pixel,&target[2]) == MagickFalse))
528 bounding_box.height=(size_t) y;
529 if ((x < (ssize_t) bounding_box.width) &&
530 (y > (ssize_t) bounding_box.height) &&
531 (IsFuzzyEquivalencePixelInfo(&pixel,&target[3]) == MagickFalse))
533 bounding_box.width=(size_t) x;
534 bounding_box.height=(size_t) y;
536 q+=GetPixelChannels(image);
538#if defined(MAGICKCORE_OPENMP_SUPPORT)
539# pragma omp critical (MagickCore_GetImageBoundingBox)
542 if (bounding_box.x < bounds.x)
543 bounds.x=bounding_box.x;
544 if (bounding_box.y < bounds.y)
545 bounds.y=bounding_box.y;
546 if (bounding_box.width > bounds.width)
547 bounds.width=bounding_box.width;
548 if (bounding_box.height > bounds.height)
549 bounds.height=bounding_box.height;
552 image_view=DestroyCacheView(image_view);
553 if ((bounds.width == 0) || (bounds.height == 0))
554 (void) ThrowMagickException(exception,GetMagickModule(),OptionWarning,
555 "GeometryDoesNotContainImage",
"`%s'",image->filename);
558 bounds.width-=(size_t) (bounds.x-1);
559 bounds.height-=(size_t) (bounds.y-1);
597 return((b->x-a->x)*(c->y-a->y)-(b->y-a->y)*(c->x-a->x));
620 memset(&edge_background,0,
sizeof(edge_background));
621 artifact=GetImageArtifact(image,
"convex-hull:background-color");
622 if (artifact == (
const char *) NULL)
623 artifact=GetImageArtifact(image,
"background");
624#if defined(MAGICKCORE_OPENMP_SUPPORT)
625 #pragma omp parallel for schedule(static)
627 for (i=0; i < 4; i++)
651 (void) memset(&edge_geometry,0,
sizeof(edge_geometry));
657 p=GetCacheViewVirtualPixels(image_view,0,(ssize_t) image->rows-1,1,1,
660 edge_geometry.width=1;
661 edge_geometry.height=0;
666 p=GetCacheViewVirtualPixels(image_view,(ssize_t) image->columns-1,0,1,1,
669 edge_geometry.width=1;
670 edge_geometry.height=0;
675 p=GetCacheViewVirtualPixels(image_view,0,0,1,1,exception);
676 gravity=NorthGravity;
677 edge_geometry.width=0;
678 edge_geometry.height=1;
683 p=GetCacheViewVirtualPixels(image_view,(ssize_t) image->columns-1,
684 (ssize_t) image->rows-1,1,1,exception);
685 gravity=SouthGravity;
686 edge_geometry.width=0;
687 edge_geometry.height=1;
691 GetPixelInfoPixel(image,p,background+i);
692 if (artifact != (
const char *) NULL)
693 (void) QueryColorCompliance(artifact,AllCompliance,background+i,
695 GravityAdjustGeometry(image->columns,image->rows,gravity,&edge_geometry);
696 edge_image=CropImage(image,&edge_geometry,exception);
697 if (edge_image == (
Image *) NULL)
699 edge_view=AcquireVirtualCacheView(edge_image,exception);
700 for (y=0; y < (ssize_t) edge_image->rows; y++)
705 p=GetCacheViewVirtualPixels(edge_view,0,y,edge_image->columns,1,
707 if (p == (
const Quantum *) NULL)
709 for (x=0; x < (ssize_t) edge_image->columns; x++)
711 GetPixelInfoPixel(edge_image,p,&pixel);
712 if (IsFuzzyEquivalencePixelInfo(&pixel,background+i) == MagickFalse)
714 p+=GetPixelChannels(edge_image);
717 edge_view=DestroyCacheView(edge_view);
718 edge_image=DestroyImage(edge_image);
721 for (i=0; i < 4; i++)
722 if (census[i] > edge_census)
724 edge_background=background[i];
725 edge_census=census[i];
727 return(edge_background);
730void TraceConvexHull(
PointInfo *vertices,
size_t number_vertices,
731 PointInfo ***monotone_chain,
size_t *chain_length)
746 chain=(*monotone_chain);
748 for (i=0; i < (ssize_t) number_vertices; i++)
751 (LexicographicalOrder(chain[n-2],chain[n-1],&vertices[i]) <= 0.0))
753 chain[n++]=(&vertices[i]);
756 for (i=(ssize_t) number_vertices-2; i >= 0; i--)
758 while ((n >= demark) &&
759 (LexicographicalOrder(chain[n-2],chain[n-1],&vertices[i]) <= 0.0))
761 chain[n++]=(&vertices[i]);
796 assert(image != (
Image *) NULL);
797 assert(image->signature == MagickCoreSignature);
798 if (IsEventLogging() != MagickFalse)
799 (void) LogMagickEvent(TraceEvent,GetMagickModule(),
"%s",image->filename);
801 vertices_info=AcquireVirtualMemory(image->columns,image->rows*
803 monotone_info=AcquireVirtualMemory(2*image->columns,2*
804 image->rows*
sizeof(*monotone_chain));
809 monotone_info=(
MemoryInfo *) RelinquishVirtualMemory(monotone_info);
811 vertices_info=RelinquishVirtualMemory(vertices_info);
814 vertices=(
PointInfo *) GetVirtualMemoryBlob(vertices_info);
815 monotone_chain=(
PointInfo **) GetVirtualMemoryBlob(monotone_info);
816 image_view=AcquireVirtualCacheView(image,exception);
817 background=GetEdgeBackgroundColor(image,image_view,exception);
820 for (y=0; y < (ssize_t) image->rows; y++)
828 if (status == MagickFalse)
830 p=GetCacheViewVirtualPixels(image_view,0,y,image->columns,1,exception);
831 if (p == (
const Quantum *) NULL)
836 for (x=0; x < (ssize_t) image->columns; x++)
841 GetPixelInfoPixel(image,p,&pixel);
842 if (IsFuzzyEquivalencePixelInfo(&pixel,&background) == MagickFalse)
844 vertices[n].x=(double) x;
845 vertices[n].y=(double) y;
848 p+=GetPixelChannels(image);
851 image_view=DestroyCacheView(image_view);
855 TraceConvexHull(vertices,n,&monotone_chain,number_vertices);
856 convex_hull=(
PointInfo *) AcquireQuantumMemory(*number_vertices,
857 sizeof(*convex_hull));
859 for (n=0; n < *number_vertices; n++)
860 convex_hull[n]=(*monotone_chain[n]);
861 monotone_info=RelinquishVirtualMemory(monotone_info);
862 vertices_info=RelinquishVirtualMemory(vertices_info);
912 assert(image != (
Image *) NULL);
913 assert(image->signature == MagickCoreSignature);
914 if (IsEventLogging() != MagickFalse)
915 (void) LogMagickEvent(TraceEvent,GetMagickModule(),
"%s",image->filename);
916 number_threads=(size_t) GetMagickResourceLimit(ThreadResource);
917 current_depth=(
size_t *) AcquireQuantumMemory(number_threads,
918 sizeof(*current_depth));
919 if (current_depth == (
size_t *) NULL)
920 ThrowFatalException(ResourceLimitFatalError,
"MemoryAllocationFailed");
922 for (i=0; i < (ssize_t) number_threads; i++)
924 if ((image->storage_class == PseudoClass) &&
925 ((image->alpha_trait & BlendPixelTrait) == 0))
927 for (i=0; i < (ssize_t) image->colors; i++)
930 id = GetOpenMPThreadId();
932 while (current_depth[
id] < MAGICKCORE_QUANTUM_DEPTH)
941 range=GetQuantumRange(current_depth[
id]);
942 if ((GetPixelRedTraits(image) & UpdatePixelTrait) != 0)
943 if (IsPixelAtDepth(ClampToQuantum(image->colormap[i].red),range) == MagickFalse)
945 if ((atDepth != MagickFalse) &&
946 (GetPixelGreenTraits(image) & UpdatePixelTrait) != 0)
947 if (IsPixelAtDepth(ClampToQuantum(image->colormap[i].green),range) == MagickFalse)
949 if ((atDepth != MagickFalse) &&
950 (GetPixelBlueTraits(image) & UpdatePixelTrait) != 0)
951 if (IsPixelAtDepth(ClampToQuantum(image->colormap[i].blue),range) == MagickFalse)
953 if ((atDepth != MagickFalse))
958 depth=current_depth[0];
959 for (i=1; i < (ssize_t) number_threads; i++)
960 if (depth < current_depth[i])
961 depth=current_depth[i];
962 current_depth=(
size_t *) RelinquishMagickMemory(current_depth);
965 image_view=AcquireVirtualCacheView(image,exception);
966#if !defined(MAGICKCORE_HDRI_SUPPORT)
967 DisableMSCWarning(4127)
968 if ((1UL*QuantumRange) <= MaxMap)
977 depth_map=(
size_t *) AcquireQuantumMemory(MaxMap+1,
sizeof(*depth_map));
978 if (depth_map == (
size_t *) NULL)
979 ThrowFatalException(ResourceLimitFatalError,
"MemoryAllocationFailed");
980 for (i=0; i <= (ssize_t) MaxMap; i++)
982 for (depth=1; depth < (size_t) MAGICKCORE_QUANTUM_DEPTH; depth++)
990 range=GetQuantumRange(depth);
992 if (pixel == ScaleAnyToQuantum(ScaleQuantumToAny(pixel,range),range))
997#if defined(MAGICKCORE_OPENMP_SUPPORT)
998 #pragma omp parallel for schedule(static) shared(status) \
999 magick_number_threads(image,image,image->rows,1)
1001 for (y=0; y < (ssize_t) image->rows; y++)
1004 id = GetOpenMPThreadId();
1012 if (status == MagickFalse)
1014 p=GetCacheViewVirtualPixels(image_view,0,y,image->columns,1,exception);
1015 if (p == (
const Quantum *) NULL)
1017 for (x=0; x < (ssize_t) image->columns; x++)
1022 for (j=0; j < (ssize_t) GetPixelChannels(image); j++)
1024 PixelChannel channel = GetPixelChannelChannel(image,j);
1025 PixelTrait traits = GetPixelChannelTraits(image,channel);
1026 if ((traits & UpdatePixelTrait) == 0)
1028 if (depth_map[ScaleQuantumToMap(p[j])] > current_depth[
id])
1029 current_depth[id]=depth_map[ScaleQuantumToMap(p[j])];
1031 p+=GetPixelChannels(image);
1033 if (current_depth[
id] == MAGICKCORE_QUANTUM_DEPTH)
1036 image_view=DestroyCacheView(image_view);
1037 depth=current_depth[0];
1038 for (i=1; i < (ssize_t) number_threads; i++)
1039 if (depth < current_depth[i])
1040 depth=current_depth[i];
1041 depth_map=(
size_t *) RelinquishMagickMemory(depth_map);
1042 current_depth=(
size_t *) RelinquishMagickMemory(current_depth);
1049#if defined(MAGICKCORE_OPENMP_SUPPORT)
1050 #pragma omp parallel for schedule(static) shared(status) \
1051 magick_number_threads(image,image,image->rows,1)
1053 for (y=0; y < (ssize_t) image->rows; y++)
1056 id = GetOpenMPThreadId();
1064 if (status == MagickFalse)
1066 p=GetCacheViewVirtualPixels(image_view,0,y,image->columns,1,exception);
1067 if (p == (
const Quantum *) NULL)
1069 for (x=0; x < (ssize_t) image->columns; x++)
1074 for (j=0; j < (ssize_t) GetPixelChannels(image); j++)
1082 channel=GetPixelChannelChannel(image,j);
1083 traits=GetPixelChannelTraits(image,channel);
1084 if ((traits & UpdatePixelTrait) == 0)
1086 while (current_depth[
id] < MAGICKCORE_QUANTUM_DEPTH)
1091 range=GetQuantumRange(current_depth[
id]);
1092 if (p[j] == ScaleAnyToQuantum(ScaleQuantumToAny(p[j],range),range))
1094 current_depth[id]++;
1097 p+=GetPixelChannels(image);
1099 if (current_depth[
id] == MAGICKCORE_QUANTUM_DEPTH)
1102 image_view=DestroyCacheView(image_view);
1103 depth=current_depth[0];
1104 for (i=1; i < (ssize_t) number_threads; i++)
1105 if (depth < current_depth[i])
1106 depth=current_depth[i];
1107 current_depth=(
size_t *) RelinquishMagickMemory(current_depth);
1162 return(RadiansToDegrees(atan2(q->y-p->y,q->x-p->x)));
1170 distance=hypot(p->x-q->x,p->y-q->y);
1171 return(distance*distance);
1182 distance=getDistance(p,q);
1183 if (distance < MagickEpsilon)
1185 return((q->x-p->x)*(v->x-p->x)+(v->y-p->y)*(q->y-p->y))/sqrt(distance);
1196 distance=getDistance(p,q);
1197 if (distance < MagickEpsilon)
1199 return((q->x-p->x)*(v->y-p->y)-(v->x-p->x)*(q->y-p->y))/sqrt(distance);
1221 number_hull_vertices;
1229 assert(image != (
Image *) NULL);
1230 assert(image->signature == MagickCoreSignature);
1231 if (IsEventLogging() != MagickFalse)
1232 (void) LogMagickEvent(TraceEvent,GetMagickModule(),
"%s",image->filename);
1234 vertices=GetImageConvexHull(image,&number_hull_vertices,exception);
1238 bounding_box=(
PointInfo *) AcquireQuantumMemory(*number_vertices,
1239 sizeof(*bounding_box));
1242 vertices=(
PointInfo *) RelinquishMagickMemory(vertices);
1245 caliper_info.area=2.0*image->columns*image->rows;
1246 caliper_info.width=(double) image->columns+image->rows;
1247 caliper_info.height=0.0;
1248 caliper_info.projection=0.0;
1249 caliper_info.p=(-1);
1250 caliper_info.q=(-1);
1251 caliper_info.v=(-1);
1252 for (i=0; i < (ssize_t) number_hull_vertices; i++)
1256 max_projection = 0.0,
1257 min_diameter = -1.0,
1258 min_projection = 0.0;
1269 for (j=0; j < (ssize_t) number_hull_vertices; j++)
1271 diameter=fabs(getFeretDiameter(&vertices[i],
1272 &vertices[(i+1) % (ssize_t) number_hull_vertices],&vertices[j]));
1273 if (min_diameter < diameter)
1275 min_diameter=diameter;
1277 q=(i+1) % (ssize_t) number_hull_vertices;
1281 for (k=0; k < (ssize_t) number_hull_vertices; k++)
1289 projection=getProjection(&vertices[p],&vertices[q],&vertices[k]);
1290 min_projection=MagickMin(min_projection,projection);
1291 max_projection=MagickMax(max_projection,projection);
1293 area=min_diameter*(max_projection-min_projection);
1294 if (caliper_info.area > area)
1296 caliper_info.area=area;
1297 caliper_info.width=min_diameter;
1298 caliper_info.height=max_projection-min_projection;
1299 caliper_info.projection=max_projection;
1308 diameter=getFeretDiameter(&vertices[caliper_info.p],
1309 &vertices[caliper_info.q],&vertices[caliper_info.v]);
1310 angle=atan2(vertices[caliper_info.q].y-vertices[caliper_info.p].y,
1311 vertices[caliper_info.q].x-vertices[caliper_info.p].x);
1312 bounding_box[0].x=vertices[caliper_info.p].x+cos(angle)*
1313 caliper_info.projection;
1314 bounding_box[0].y=vertices[caliper_info.p].y+sin(angle)*
1315 caliper_info.projection;
1316 bounding_box[1].x=floor(bounding_box[0].x+cos(angle+MagickPI/2.0)*diameter+
1318 bounding_box[1].y=floor(bounding_box[0].y+sin(angle+MagickPI/2.0)*diameter+
1320 bounding_box[2].x=floor(bounding_box[1].x+cos(angle)*(-caliper_info.height)+
1322 bounding_box[2].y=floor(bounding_box[1].y+sin(angle)*(-caliper_info.height)+
1324 bounding_box[3].x=floor(bounding_box[2].x+cos(angle+MagickPI/2.0)*(-diameter)+
1326 bounding_box[3].y=floor(bounding_box[2].y+sin(angle+MagickPI/2.0)*(-diameter)+
1331 (void) FormatImageProperty(image,
"minimum-bounding-box:area",
"%.*g",
1332 GetMagickPrecision(),caliper_info.area);
1333 (void) FormatImageProperty(image,
"minimum-bounding-box:width",
"%.*g",
1334 GetMagickPrecision(),caliper_info.width);
1335 (void) FormatImageProperty(image,
"minimum-bounding-box:height",
"%.*g",
1336 GetMagickPrecision(),caliper_info.height);
1337 (void) FormatImageProperty(image,
"minimum-bounding-box:_p",
"%.*g,%.*g",
1338 GetMagickPrecision(),vertices[caliper_info.p].x,
1339 GetMagickPrecision(),vertices[caliper_info.p].y);
1340 (void) FormatImageProperty(image,
"minimum-bounding-box:_q",
"%.*g,%.*g",
1341 GetMagickPrecision(),vertices[caliper_info.q].x,
1342 GetMagickPrecision(),vertices[caliper_info.q].y);
1343 (void) FormatImageProperty(image,
"minimum-bounding-box:_v",
"%.*g,%.*g",
1344 GetMagickPrecision(),vertices[caliper_info.v].x,
1345 GetMagickPrecision(),vertices[caliper_info.v].y);
1349 distance=hypot(bounding_box[0].x,bounding_box[0].y);
1350 angle=getAngle(&bounding_box[0],&bounding_box[1]);
1351 for (i=1; i < 4; i++)
1353 double d = hypot(bounding_box[i].x,bounding_box[i].y);
1357 angle=getAngle(&bounding_box[i],&bounding_box[(i+1) % 4]);
1360 artifact=GetImageArtifact(image,
"minimum-bounding-box:orientation");
1361 if (artifact != (
const char *) NULL)
1375 point=bounding_box[0];
1376 for (i=1; i < 4; i++)
1378 if (bounding_box[i].x < point.x)
1379 point.x=bounding_box[i].x;
1380 if (bounding_box[i].y < point.y)
1381 point.y=bounding_box[i].y;
1383 for (i=0; i < 4; i++)
1385 bounding_box[i].x-=point.x;
1386 bounding_box[i].y-=point.y;
1388 for (i=0; i < 4; i++)
1395 delta.x=bounding_box[(i+1) % 4].x-bounding_box[i].x;
1396 delta.y=bounding_box[(i+1) % 4].y-bounding_box[i].y;
1397 slope=delta.y*PerceptibleReciprocal(delta.x);
1398 intercept=bounding_box[(i+1) % 4].y-slope*bounding_box[i].x;
1399 d=fabs((slope*bounding_box[i].x-bounding_box[i].y+intercept)*
1400 PerceptibleReciprocal(sqrt(slope*slope+1.0)));
1401 if ((i == 0) || (d < distance))
1407 angle=RadiansToDegrees(atan(point.y*PerceptibleReciprocal(point.x)));
1408 length=hypot(point.x,point.y);
1409 p_length=fabs((
double) MagickMax(caliper_info.width,caliper_info.height)-
1411 q_length=fabs(length-(
double) MagickMin(caliper_info.width,
1412 caliper_info.height));
1413 if (LocaleCompare(artifact,
"landscape") == 0)
1415 if (p_length > q_length)
1416 angle+=(angle < 0.0) ? 90.0 : -90.0;
1419 if (LocaleCompare(artifact,
"portrait") == 0)
1421 if (p_length < q_length)
1422 angle+=(angle >= 0.0) ? 90.0 : -90.0;
1425 (void) FormatImageProperty(image,
"minimum-bounding-box:angle",
"%.*g",
1426 GetMagickPrecision(),angle);
1427 (void) FormatImageProperty(image,
"minimum-bounding-box:unrotate",
"%.*g",
1428 GetMagickPrecision(),-angle);
1429 vertices=(
PointInfo *) RelinquishMagickMemory(vertices);
1430 return(bounding_box);
1460MagickExport
size_t GetImageQuantumDepth(
const Image *image,
1461 const MagickBooleanType constrain)
1478 if (constrain != MagickFalse)
1479 depth=(size_t) MagickMin((
double) depth,(
double) MAGICKCORE_QUANTUM_DEPTH);
1509MagickExport ImageType GetImageType(
const Image *image)
1511 assert(image != (
Image *) NULL);
1512 assert(image->signature == MagickCoreSignature);
1513 if (image->colorspace == CMYKColorspace)
1515 if ((image->alpha_trait & BlendPixelTrait) == 0)
1516 return(ColorSeparationType);
1517 return(ColorSeparationAlphaType);
1519 if (IsImageMonochrome(image) != MagickFalse)
1520 return(BilevelType);
1521 if (IsImageGray(image) != MagickFalse)
1523 if (image->alpha_trait != UndefinedPixelTrait)
1524 return(GrayscaleAlphaType);
1525 return(GrayscaleType);
1527 if (IsPaletteImage(image) != MagickFalse)
1529 if (image->alpha_trait != UndefinedPixelTrait)
1530 return(PaletteAlphaType);
1531 return(PaletteType);
1533 if (image->alpha_trait != UndefinedPixelTrait)
1534 return(TrueColorAlphaType);
1535 return(TrueColorType);
1564MagickExport ImageType IdentifyImageGray(
const Image *image,
1574 status = MagickTrue;
1579 assert(image != (
Image *) NULL);
1580 assert(image->signature == MagickCoreSignature);
1581 if (IsEventLogging() != MagickFalse)
1582 (void) LogMagickEvent(TraceEvent,GetMagickModule(),
"%s",image->filename);
1583 if (IsImageGray(image) != MagickFalse)
1584 return(image->type);
1585 if (IssRGBCompatibleColorspace(image->colorspace) == MagickFalse)
1586 return(UndefinedType);
1587 image_view=AcquireVirtualCacheView(image,exception);
1588#if defined(MAGICKCORE_OPENMP_SUPPORT)
1589 #pragma omp parallel for schedule(static) shared(status,type) \
1590 magick_number_threads(image,image,image->rows,2)
1592 for (y=0; y < (ssize_t) image->rows; y++)
1600 if (status == MagickFalse)
1602 p=GetCacheViewVirtualPixels(image_view,0,y,image->columns,1,exception);
1603 if (p == (
const Quantum *) NULL)
1608 for (x=0; x < (ssize_t) image->columns; x++)
1610 if (IsPixelGray(image,p) == MagickFalse)
1615 if ((type == BilevelType) && (IsPixelMonochrome(image,p) == MagickFalse))
1617 p+=GetPixelChannels(image);
1620 image_view=DestroyCacheView(image_view);
1621 if ((type == GrayscaleType) && (image->alpha_trait != UndefinedPixelTrait))
1622 type=GrayscaleAlphaType;
1623 if (status == MagickFalse)
1624 return(UndefinedType);
1655MagickExport MagickBooleanType IdentifyImageMonochrome(
const Image *image,
1667 assert(image != (
Image *) NULL);
1668 assert(image->signature == MagickCoreSignature);
1669 if (IsEventLogging() != MagickFalse)
1670 (void) LogMagickEvent(TraceEvent,GetMagickModule(),
"%s",image->filename);
1671 if (image->type == BilevelType)
1673 if (IssRGBCompatibleColorspace(image->colorspace) == MagickFalse)
1674 return(MagickFalse);
1675 image_view=AcquireVirtualCacheView(image,exception);
1676#if defined(MAGICKCORE_OPENMP_SUPPORT)
1677 #pragma omp parallel for schedule(static) shared(type) \
1678 magick_number_threads(image,image,image->rows,2)
1680 for (y=0; y < (ssize_t) image->rows; y++)
1688 if (type == UndefinedType)
1690 p=GetCacheViewVirtualPixels(image_view,0,y,image->columns,1,exception);
1691 if (p == (
const Quantum *) NULL)
1696 for (x=0; x < (ssize_t) image->columns; x++)
1698 if (IsPixelMonochrome(image,p) == MagickFalse)
1703 p+=GetPixelChannels(image);
1706 image_view=DestroyCacheView(image_view);
1707 return(type == BilevelType ? MagickTrue : MagickFalse);
1742MagickExport ImageType IdentifyImageType(
const Image *image,
1748 assert(image != (
Image *) NULL);
1749 assert(image->signature == MagickCoreSignature);
1750 if (IsEventLogging() != MagickFalse)
1751 (void) LogMagickEvent(TraceEvent,GetMagickModule(),
"%s",image->filename);
1752 if (image->colorspace == CMYKColorspace)
1754 if ((image->alpha_trait & BlendPixelTrait) == 0)
1755 return(ColorSeparationType);
1756 return(ColorSeparationAlphaType);
1758 type=IdentifyImageGray(image,exception);
1759 if (IsGrayImageType(type))
1761 if (IdentifyPaletteImage(image,exception) != MagickFalse)
1763 if (image->alpha_trait != UndefinedPixelTrait)
1764 return(PaletteAlphaType);
1765 return(PaletteType);
1767 if (image->alpha_trait != UndefinedPixelTrait)
1768 return(TrueColorAlphaType);
1769 return(TrueColorType);
1795MagickExport MagickBooleanType IsImageGray(
const Image *image)
1797 assert(image != (
Image *) NULL);
1798 assert(image->signature == MagickCoreSignature);
1799 if (IsGrayImageType(image->type) != MagickFalse)
1801 return(MagickFalse);
1826MagickExport MagickBooleanType IsImageMonochrome(
const Image *image)
1828 assert(image != (
Image *) NULL);
1829 assert(image->signature == MagickCoreSignature);
1830 if (image->type == BilevelType)
1832 return(MagickFalse);
1863MagickExport MagickBooleanType IsImageOpaque(
const Image *image,
1870 opaque = MagickTrue;
1878 assert(image != (
Image *) NULL);
1879 assert(image->signature == MagickCoreSignature);
1880 if (IsEventLogging() != MagickFalse)
1881 (void) LogMagickEvent(TraceEvent,GetMagickModule(),
"%s",image->filename);
1882 if ((image->alpha_trait & BlendPixelTrait) == 0)
1884 image_view=AcquireVirtualCacheView(image,exception);
1885#if defined(MAGICKCORE_OPENMP_SUPPORT)
1886 #pragma omp parallel for schedule(static) shared(opaque) \
1887 magick_number_threads(image,image,image->rows,2)
1889 for (y=0; y < (ssize_t) image->rows; y++)
1897 if (opaque == MagickFalse)
1899 p=GetCacheViewVirtualPixels(image_view,0,y,image->columns,1,exception);
1900 if (p == (
const Quantum *) NULL)
1905 for (x=0; x < (ssize_t) image->columns; x++)
1907 if (GetPixelAlpha(image,p) != OpaqueAlpha)
1912 p+=GetPixelChannels(image);
1915 image_view=DestroyCacheView(image_view);
1949static MagickBooleanType FloydSteinbergImageDepth(
Image *image,
1973 status=SetImageStorageClass(image,DirectClass,exception);
1974 if (status == MagickFalse)
1975 return(MagickFalse);
1976 channels=GetPixelChannels(image);
1977 distortion=(
double *) AcquireQuantumMemory(image->columns,3*channels*
1978 sizeof(*distortion));
1979 if (distortion == (
double *) NULL)
1980 return(MagickFalse);
1981 (void) memset(distortion,0,3*image->columns*channels*
sizeof(*distortion));
1982 range=GetQuantumRange(depth);
1983 image_view=AcquireAuthenticCacheView(image,exception);
1984 for (y=0; y < (ssize_t) image->rows; y++)
1994 if (status == MagickFalse)
1996 q=GetCacheViewAuthenticPixels(image_view,0,y,image->columns,1,exception);
1997 if (q == (Quantum *) NULL)
2005 u=(y % 3)*(ssize_t) (image->columns*channels);
2006 (void) memset(distortion+u,0,image->columns*channels*
sizeof(*distortion));
2007 v=((y+1) % 3)*(ssize_t) (image->columns*channels);
2008 for (x=0; x < (ssize_t) image->columns; x++)
2013 for (i=0; i < (ssize_t) channels; i++)
2028 channel=GetPixelChannelChannel(image,i);
2029 traits=GetPixelChannelTraits(image,channel);
2030 if ((traits & UpdatePixelTrait) == 0)
2032 pixel=(double) q[i]+distortion[u];
2033 q[i]=ScaleAnyToQuantum(ScaleQuantumToAny(ClampPixel((MagickRealType)
2034 pixel),range),range);
2038 error=pixel-(double) q[i];
2039 if ((x+1) < (ssize_t) image->columns)
2040 distortion[u+(ssize_t) channels]+=7.0*error/16.0;
2041 if ((y+1) < (ssize_t) image->rows)
2047 distortion[v-(ssize_t) channels]+=3.0*error/16.0;
2048 distortion[v]+=5.0*error/16.0;
2049 if ((x+1) < (ssize_t) image->columns)
2050 distortion[v+(ssize_t) channels]+=1.0*error/16.0;
2055 q+=GetPixelChannels(image);
2057 if (SyncCacheViewAuthenticPixels(image_view,exception) == MagickFalse)
2063 image_view=DestroyCacheView(image_view);
2064 distortion=(
double *) RelinquishMagickMemory(distortion);
2065 if (status != MagickFalse)
2070MagickExport MagickBooleanType SetImageDepth(
Image *image,
2088 assert(image != (
Image *) NULL);
2089 if (IsEventLogging() != MagickFalse)
2090 (void) LogMagickEvent(TraceEvent,GetMagickModule(),
"...");
2091 assert(image->signature == MagickCoreSignature);
2092 if (depth >= MAGICKCORE_QUANTUM_DEPTH)
2097 artifact=GetImageArtifact(image,
"dither");
2098 if ((artifact != (
const char *) NULL) &&
2099 (LocaleCompare(artifact,
"FloydSteinberg") == 0))
2100 return(FloydSteinbergImageDepth(image,depth,exception));
2101 range=GetQuantumRange(depth);
2102 if (image->storage_class == PseudoClass)
2107#if defined(MAGICKCORE_OPENMP_SUPPORT)
2108 #pragma omp parallel for schedule(static) shared(status) \
2109 magick_number_threads(image,image,image->colors,1)
2111 for (i=0; i < (ssize_t) image->colors; i++)
2113 if ((GetPixelRedTraits(image) & UpdatePixelTrait) != 0)
2114 image->colormap[i].red=(double) ScaleAnyToQuantum(ScaleQuantumToAny(
2115 ClampPixel(image->colormap[i].red),range),range);
2116 if ((GetPixelGreenTraits(image) & UpdatePixelTrait) != 0)
2117 image->colormap[i].green=(double) ScaleAnyToQuantum(ScaleQuantumToAny(
2118 ClampPixel(image->colormap[i].green),range),range);
2119 if ((GetPixelBlueTraits(image) & UpdatePixelTrait) != 0)
2120 image->colormap[i].blue=(double) ScaleAnyToQuantum(ScaleQuantumToAny(
2121 ClampPixel(image->colormap[i].blue),range),range);
2122 if ((GetPixelAlphaTraits(image) & UpdatePixelTrait) != 0)
2123 image->colormap[i].alpha=(double) ScaleAnyToQuantum(ScaleQuantumToAny(
2124 ClampPixel(image->colormap[i].alpha),range),range);
2128 image_view=AcquireAuthenticCacheView(image,exception);
2129#if !defined(MAGICKCORE_HDRI_SUPPORT)
2130 DisableMSCWarning(4127)
2131 if ((1UL*QuantumRange) <= MaxMap)
2143 depth_map=(Quantum *) AcquireQuantumMemory(MaxMap+1,
sizeof(*depth_map));
2144 if (depth_map == (Quantum *) NULL)
2145 ThrowFatalException(ResourceLimitFatalError,
"MemoryAllocationFailed");
2146 for (i=0; i <= (ssize_t) MaxMap; i++)
2147 depth_map[i]=ScaleAnyToQuantum(ScaleQuantumToAny((Quantum) i,range),
2149#if defined(MAGICKCORE_OPENMP_SUPPORT)
2150 #pragma omp parallel for schedule(static) shared(status) \
2151 magick_number_threads(image,image,image->rows,2)
2153 for (y=0; y < (ssize_t) image->rows; y++)
2161 if (status == MagickFalse)
2163 q=GetCacheViewAuthenticPixels(image_view,0,y,image->columns,1,
2165 if (q == (Quantum *) NULL)
2170 for (x=0; x < (ssize_t) image->columns; x++)
2175 for (j=0; j < (ssize_t) GetPixelChannels(image); j++)
2183 channel=GetPixelChannelChannel(image,j);
2184 traits=GetPixelChannelTraits(image,channel);
2185 if ((traits & UpdatePixelTrait) == 0)
2187 q[j]=depth_map[ScaleQuantumToMap(q[j])];
2189 q+=GetPixelChannels(image);
2191 if (SyncCacheViewAuthenticPixels(image_view,exception) == MagickFalse)
2197 image_view=DestroyCacheView(image_view);
2198 depth_map=(Quantum *) RelinquishMagickMemory(depth_map);
2199 if (status != MagickFalse)
2207#if defined(MAGICKCORE_OPENMP_SUPPORT)
2208 #pragma omp parallel for schedule(static) shared(status) \
2209 magick_number_threads(image,image,image->rows,2)
2211 for (y=0; y < (ssize_t) image->rows; y++)
2219 if (status == MagickFalse)
2221 q=GetCacheViewAuthenticPixels(image_view,0,y,image->columns,1,exception);
2222 if (q == (Quantum *) NULL)
2227 for (x=0; x < (ssize_t) image->columns; x++)
2232 for (i=0; i < (ssize_t) GetPixelChannels(image); i++)
2240 channel=GetPixelChannelChannel(image,i);
2241 traits=GetPixelChannelTraits(image,channel);
2242 if ((traits & UpdatePixelTrait) == 0)
2244 q[i]=ScaleAnyToQuantum(ScaleQuantumToAny(ClampPixel((MagickRealType)
2245 q[i]),range),range);
2247 q+=GetPixelChannels(image);
2249 if (SyncCacheViewAuthenticPixels(image_view,exception) == MagickFalse)
2255 image_view=DestroyCacheView(image_view);
2256 if (status != MagickFalse)
2293MagickExport MagickBooleanType SetImageType(
Image *image,
const ImageType type,
2308 assert(image != (
Image *) NULL);
2309 if (IsEventLogging() != MagickFalse)
2310 (void) LogMagickEvent(TraceEvent,GetMagickModule(),
"...");
2311 assert(image->signature == MagickCoreSignature);
2313 image_info=AcquireImageInfo();
2314 image_info->dither=image->dither;
2315 artifact=GetImageArtifact(image,
"dither");
2316 if (artifact != (
const char *) NULL)
2317 (void) SetImageOption(image_info,
"dither",artifact);
2322 if (IsGrayImageType(image->type) == MagickFalse)
2323 status=TransformImageColorspace(image,GRAYColorspace,exception);
2324 (void) NormalizeImage(image,exception);
2325 (void) BilevelImage(image,(
double) QuantumRange/2.0,exception);
2326 quantize_info=AcquireQuantizeInfo(image_info);
2327 quantize_info->number_colors=2;
2328 quantize_info->colorspace=GRAYColorspace;
2329 status=QuantizeImage(quantize_info,image,exception);
2330 quantize_info=DestroyQuantizeInfo(quantize_info);
2331 image->alpha_trait=UndefinedPixelTrait;
2336 if (IsGrayImageType(image->type) == MagickFalse)
2337 status=TransformImageColorspace(image,GRAYColorspace,exception);
2338 image->alpha_trait=UndefinedPixelTrait;
2341 case GrayscaleAlphaType:
2343 if (IsGrayImageType(image->type) == MagickFalse)
2344 status=TransformImageColorspace(image,GRAYColorspace,exception);
2345 if ((image->alpha_trait & BlendPixelTrait) == 0)
2346 (void) SetImageAlphaChannel(image,OpaqueAlphaChannel,exception);
2351 if (IssRGBCompatibleColorspace(image->colorspace) == MagickFalse)
2352 status=TransformImageColorspace(image,sRGBColorspace,exception);
2353 if ((image->storage_class == DirectClass) || (image->colors > 256))
2355 quantize_info=AcquireQuantizeInfo(image_info);
2356 quantize_info->number_colors=256;
2357 status=QuantizeImage(quantize_info,image,exception);
2358 quantize_info=DestroyQuantizeInfo(quantize_info);
2360 image->alpha_trait=UndefinedPixelTrait;
2363 case PaletteBilevelAlphaType:
2368 if (IssRGBCompatibleColorspace(image->colorspace) == MagickFalse)
2369 status=TransformImageColorspace(image,sRGBColorspace,exception);
2370 if ((image->alpha_trait & BlendPixelTrait) == 0)
2371 (void) SetImageAlphaChannel(image,OpaqueAlphaChannel,exception);
2372 channel_mask=SetImageChannelMask(image,AlphaChannel);
2373 (void) BilevelImage(image,(
double) QuantumRange/2.0,exception);
2374 (void) SetImageChannelMask(image,channel_mask);
2375 quantize_info=AcquireQuantizeInfo(image_info);
2376 status=QuantizeImage(quantize_info,image,exception);
2377 quantize_info=DestroyQuantizeInfo(quantize_info);
2380 case PaletteAlphaType:
2382 if (IssRGBCompatibleColorspace(image->colorspace) == MagickFalse)
2383 status=TransformImageColorspace(image,sRGBColorspace,exception);
2384 if ((image->alpha_trait & BlendPixelTrait) == 0)
2385 (void) SetImageAlphaChannel(image,OpaqueAlphaChannel,exception);
2386 quantize_info=AcquireQuantizeInfo(image_info);
2387 quantize_info->colorspace=TransparentColorspace;
2388 status=QuantizeImage(quantize_info,image,exception);
2389 quantize_info=DestroyQuantizeInfo(quantize_info);
2394 if (IssRGBCompatibleColorspace(image->colorspace) == MagickFalse)
2395 status=TransformImageColorspace(image,sRGBColorspace,exception);
2396 if (image->storage_class != DirectClass)
2397 status=SetImageStorageClass(image,DirectClass,exception);
2398 image->alpha_trait=UndefinedPixelTrait;
2401 case TrueColorAlphaType:
2403 if (IssRGBCompatibleColorspace(image->colorspace) == MagickFalse)
2404 status=TransformImageColorspace(image,sRGBColorspace,exception);
2405 if (image->storage_class != DirectClass)
2406 status=SetImageStorageClass(image,DirectClass,exception);
2407 if ((image->alpha_trait & BlendPixelTrait) == 0)
2408 (void) SetImageAlphaChannel(image,OpaqueAlphaChannel,exception);
2411 case ColorSeparationType:
2413 if (image->colorspace != CMYKColorspace)
2414 status=TransformImageColorspace(image,CMYKColorspace,exception);
2415 if (image->storage_class != DirectClass)
2416 status=SetImageStorageClass(image,DirectClass,exception);
2417 image->alpha_trait=UndefinedPixelTrait;
2420 case ColorSeparationAlphaType:
2422 if (image->colorspace != CMYKColorspace)
2423 status=TransformImageColorspace(image,CMYKColorspace,exception);
2424 if (image->storage_class != DirectClass)
2425 status=SetImageStorageClass(image,DirectClass,exception);
2426 if ((image->alpha_trait & BlendPixelTrait) == 0)
2427 status=SetImageAlphaChannel(image,OpaqueAlphaChannel,exception);
2434 image_info=DestroyImageInfo(image_info);
2435 if (status == MagickFalse)