% MagickCore Get / Set Image Attributes %
% %
% Software Design %
-% John Cristy %
+% Cristy %
% October 2002 %
% %
% %
-% Copyright 1999-2011 ImageMagick Studio LLC, a non-profit organization %
+% Copyright 1999-2015 ImageMagick Studio LLC, a non-profit organization %
% dedicated to making software imaging solutions freely available. %
% %
% You may not use this file except in compliance with the License. You may %
Include declarations.
*/
#include "MagickCore/studio.h"
+#include "MagickCore/artifact.h"
#include "MagickCore/attribute.h"
#include "MagickCore/blob.h"
#include "MagickCore/blob-private.h"
#include "MagickCore/cache.h"
+#include "MagickCore/cache-private.h"
#include "MagickCore/cache-view.h"
+#include "MagickCore/channel.h"
#include "MagickCore/client.h"
#include "MagickCore/color.h"
#include "MagickCore/color-private.h"
#include "MagickCore/magick.h"
#include "MagickCore/monitor.h"
#include "MagickCore/monitor-private.h"
+#include "MagickCore/option.h"
#include "MagickCore/paint.h"
#include "MagickCore/pixel.h"
#include "MagickCore/pixel-accessor.h"
y;
assert(image != (Image *) NULL);
- assert(image->signature == MagickSignature);
+ assert(image->signature == MagickCoreSignature);
if (image->debug != MagickFalse)
(void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
bounds.width=0;
bounds.x=(ssize_t) image->columns;
bounds.y=(ssize_t) image->rows;
GetPixelInfo(image,&target[0]);
- image_view=AcquireCacheView(image);
+ image_view=AcquireVirtualCacheView(image,exception);
p=GetCacheViewVirtualPixels(image_view,0,0,1,1,exception);
if (p == (const Quantum *) NULL)
{
GetPixelInfo(image,&target[1]);
p=GetCacheViewVirtualPixels(image_view,(ssize_t) image->columns-1,0,1,1,
exception);
- GetPixelInfoPixel(image,p,&target[1]);
+ if (p != (const Quantum *) NULL)
+ GetPixelInfoPixel(image,p,&target[1]);
GetPixelInfo(image,&target[2]);
p=GetCacheViewVirtualPixels(image_view,0,(ssize_t) image->rows-1,1,1,
exception);
- GetPixelInfoPixel(image,p,&target[2]);
+ if (p != (const Quantum *) NULL)
+ GetPixelInfoPixel(image,p,&target[2]);
status=MagickTrue;
GetPixelInfo(image,&zero);
#if defined(MAGICKCORE_OPENMP_SUPPORT)
- #pragma omp parallel for schedule(dynamic,4) shared(status)
+ #pragma omp parallel for schedule(static,4) shared(status) \
+ magick_threads(image,image,image->rows,1)
#endif
for (y=0; y < (ssize_t) image->rows; y++)
{
}
}
image_view=DestroyCacheView(image_view);
- if ((bounds.width == 0) || (bounds.height == 0))
+ if ((bounds.width == 0) && (bounds.height == 0))
(void) ThrowMagickException(exception,GetMagickModule(),OptionWarning,
"GeometryDoesNotContainImage","`%s'",image->filename);
else
% o exception: return any errors or warnings in this structure.
%
*/
-MagickExport size_t GetImageDepth(const Image *image,
- ExceptionInfo *exception)
+MagickExport size_t GetImageDepth(const Image *image,ExceptionInfo *exception)
{
CacheView
*image_view;
status;
register ssize_t
- id;
+ i;
size_t
*current_depth,
Compute image depth.
*/
assert(image != (Image *) NULL);
- assert(image->signature == MagickSignature);
+ assert(image->signature == MagickCoreSignature);
if (image->debug != MagickFalse)
(void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
- number_threads=GetOpenMPMaximumThreads();
+ number_threads=(size_t) GetMagickResourceLimit(ThreadResource);
current_depth=(size_t *) AcquireQuantumMemory(number_threads,
sizeof(*current_depth));
if (current_depth == (size_t *) NULL)
ThrowFatalException(ResourceLimitFatalError,"MemoryAllocationFailed");
status=MagickTrue;
- for (id=0; id < (ssize_t) number_threads; id++)
- current_depth[id]=1;
- if ((image->storage_class == PseudoClass) && (image->matte == MagickFalse))
+ for (i=0; i < (ssize_t) number_threads; i++)
+ current_depth[i]=1;
+ if ((image->storage_class == PseudoClass) &&
+ (image->alpha_trait == UndefinedPixelTrait))
{
- register const PixelInfo
- *restrict p;
-
- register ssize_t
- i;
-
- p=image->colormap;
#if defined(MAGICKCORE_OPENMP_SUPPORT)
- #pragma omp parallel for schedule(dynamic,4) shared(status)
+ #pragma omp parallel for schedule(static,4) shared(status) \
+ if ((image->colors) > 256) \
+ num_threads(GetMagickResourceLimit(ThreadResource))
#endif
for (i=0; i < (ssize_t) image->colors; i++)
{
const int
id = GetOpenMPThreadId();
- if (status == MagickFalse)
- continue;
while (current_depth[id] < MAGICKCORE_QUANTUM_DEPTH)
{
- MagickStatusType
- status;
+ MagickBooleanType
+ atDepth;
QuantumAny
range;
- status=0;
+ atDepth=MagickTrue;
range=GetQuantumRange(current_depth[id]);
- if ((GetPixelRedTraits(image) & UpdatePixelTrait) != 0)
- status|=p->red != ScaleAnyToQuantum(ScaleQuantumToAny(p->red,
- range),range);
- if ((GetPixelGreenTraits(image) & UpdatePixelTrait) != 0)
- status|=p->green != ScaleAnyToQuantum(ScaleQuantumToAny(p->green,
- range),range);
- if ((GetPixelBlueTraits(image) & UpdatePixelTrait) != 0)
- status|=p->blue != ScaleAnyToQuantum(ScaleQuantumToAny(p->blue,
- range),range);
- if (status == 0)
+ if ((atDepth != MagickFalse) &&
+ (GetPixelRedTraits(image) & UpdatePixelTrait) != 0)
+ if (IsPixelAtDepth(image->colormap[i].red,range) == MagickFalse)
+ atDepth=MagickFalse;
+ if ((atDepth != MagickFalse) &&
+ (GetPixelGreenTraits(image) & UpdatePixelTrait) != 0)
+ if (IsPixelAtDepth(image->colormap[i].green,range) == MagickFalse)
+ atDepth=MagickFalse;
+ if ((atDepth != MagickFalse) &&
+ (GetPixelBlueTraits(image) & UpdatePixelTrait) != 0)
+ if (IsPixelAtDepth(image->colormap[i].blue,range) == MagickFalse)
+ atDepth=MagickFalse;
+ if ((atDepth != MagickFalse))
break;
current_depth[id]++;
}
- p++;
}
depth=current_depth[0];
- for (id=1; id < (ssize_t) number_threads; id++)
- if (depth < current_depth[id])
- depth=current_depth[id];
+ for (i=1; i < (ssize_t) number_threads; i++)
+ if (depth < current_depth[i])
+ depth=current_depth[i];
current_depth=(size_t *) RelinquishMagickMemory(current_depth);
return(depth);
}
- image_view=AcquireCacheView(image);
+ image_view=AcquireVirtualCacheView(image,exception);
+#if !defined(MAGICKCORE_HDRI_SUPPORT)
+ if (QuantumRange <= MaxMap)
+ {
+ size_t
+ *depth_map;
+
+ /*
+ Scale pixels to desired (optimized with depth map).
+ */
+ depth_map=(size_t *) AcquireQuantumMemory(MaxMap+1,sizeof(*depth_map));
+ if (depth_map == (size_t *) NULL)
+ ThrowFatalException(ResourceLimitFatalError,"MemoryAllocationFailed");
+ for (i=0; i <= (ssize_t) MaxMap; i++)
+ {
+ unsigned int
+ depth;
+
+ for (depth=1; depth < MAGICKCORE_QUANTUM_DEPTH; depth++)
+ {
+ Quantum
+ pixel;
+
+ QuantumAny
+ range;
+
+ range=GetQuantumRange(depth);
+ pixel=(Quantum) i;
+ if (pixel == ScaleAnyToQuantum(ScaleQuantumToAny(pixel,range),range))
+ break;
+ }
+ depth_map[i]=depth;
+ }
+#if defined(MAGICKCORE_OPENMP_SUPPORT)
+ #pragma omp parallel for schedule(static,4) shared(status) \
+ magick_threads(image,image,image->rows,1)
+#endif
+ for (y=0; y < (ssize_t) image->rows; y++)
+ {
+ const int
+ id = GetOpenMPThreadId();
+
+ register const Quantum
+ *restrict p;
+
+ register ssize_t
+ x;
+
+ if (status == MagickFalse)
+ continue;
+ p=GetCacheViewVirtualPixels(image_view,0,y,image->columns,1,exception);
+ if (p == (const Quantum *) NULL)
+ continue;
+ for (x=0; x < (ssize_t) image->columns; x++)
+ {
+ if (GetPixelReadMask(image,p) == 0)
+ {
+ p+=GetPixelChannels(image);
+ continue;
+ }
+ for (i=0; i < (ssize_t) GetPixelChannels(image); i++)
+ {
+ PixelChannel channel=GetPixelChannelChannel(image,i);
+ PixelTrait traits=GetPixelChannelTraits(image,channel);
+ if ((traits == UndefinedPixelTrait) ||
+ (channel == IndexPixelChannel) ||
+ (channel == ReadMaskPixelChannel) ||
+ (channel == MetaPixelChannel))
+ continue;
+ if (depth_map[ScaleQuantumToMap(p[i])] > current_depth[id])
+ current_depth[id]=depth_map[ScaleQuantumToMap(p[i])];
+ }
+ p+=GetPixelChannels(image);
+ }
+ if (current_depth[id] == MAGICKCORE_QUANTUM_DEPTH)
+ status=MagickFalse;
+ }
+ image_view=DestroyCacheView(image_view);
+ depth=current_depth[0];
+ for (i=1; i < (ssize_t) number_threads; i++)
+ if (depth < current_depth[i])
+ depth=current_depth[i];
+ depth_map=(size_t *) RelinquishMagickMemory(depth_map);
+ current_depth=(size_t *) RelinquishMagickMemory(current_depth);
+ return(depth);
+ }
+#endif
+ /*
+ Compute pixel depth.
+ */
#if defined(MAGICKCORE_OPENMP_SUPPORT)
- #pragma omp parallel for schedule(dynamic,4) shared(status)
+ #pragma omp parallel for schedule(static,4) shared(status) \
+ magick_threads(image,image,image->rows,1)
#endif
for (y=0; y < (ssize_t) image->rows; y++)
{
continue;
for (x=0; x < (ssize_t) image->columns; x++)
{
- register ssize_t
- i;
-
+ if (GetPixelReadMask(image,p) == 0)
+ {
+ p+=GetPixelChannels(image);
+ continue;
+ }
for (i=0; i < (ssize_t) GetPixelChannels(image); i++)
{
PixelChannel
PixelTrait
traits;
- channel=GetPixelChannelMapChannel(image,i);
- traits=GetPixelChannelMapTraits(image,channel);
- if (traits == UndefinedPixelTrait)
+ channel=GetPixelChannelChannel(image,i);
+ traits=GetPixelChannelTraits(image,channel);
+ if ((traits == UndefinedPixelTrait) || (channel == IndexPixelChannel) ||
+ (channel == ReadMaskPixelChannel))
continue;
while (current_depth[id] < MAGICKCORE_QUANTUM_DEPTH)
{
- MagickStatusType
- status;
-
QuantumAny
range;
- status=0;
range=GetQuantumRange(current_depth[id]);
- status|=p[i] != ScaleAnyToQuantum(ScaleQuantumToAny(p[i],range),
- range);
- if (status == 0)
+ if (p[i] == ScaleAnyToQuantum(ScaleQuantumToAny(p[i],range),range))
break;
current_depth[id]++;
}
}
image_view=DestroyCacheView(image_view);
depth=current_depth[0];
- for (id=1; id < (ssize_t) number_threads; id++)
- if (depth < current_depth[id])
- depth=current_depth[id];
+ for (i=1; i < (ssize_t) number_threads; i++)
+ if (depth < current_depth[i])
+ depth=current_depth[i];
current_depth=(size_t *) RelinquishMagickMemory(current_depth);
return(depth);
}
% a maximum of MAGICKCORE_QUANTUM_DEPTH.
%
*/
-
-static inline double MagickMin(const double x,const double y)
-{
- if (x < y)
- return(x);
- return(y);
-}
-
MagickExport size_t GetImageQuantumDepth(const Image *image,
const MagickBooleanType constrain)
{
if (depth <= 64)
depth=64;
if (constrain != MagickFalse)
- depth=(size_t) MagickMin((double) depth,(double)
- MAGICKCORE_QUANTUM_DEPTH);
+ depth=(size_t) MagickMin((double) depth,(double) MAGICKCORE_QUANTUM_DEPTH);
return(depth);
}
\f
% %
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%
-% GetImageType() returns the potential type of image:
+% GetImageType() returns the type of image:
%
% Bilevel Grayscale GrayscaleMatte
% Palette PaletteMatte TrueColor
% TrueColorMatte ColorSeparation ColorSeparationMatte
%
-% To ensure the image type matches its potential, use SetImageType():
-%
-% (void) SetImageType(image,GetImageType(image));
-%
% The format of the GetImageType method is:
%
-% ImageType GetImageType(const Image *image,ExceptionInfo *exception)
+% ImageType GetImageType(const Image *image)
%
% A description of each parameter follows:
%
% o image: the image.
%
-% o exception: return any errors or warnings in this structure.
-%
*/
-MagickExport ImageType GetImageType(const Image *image,ExceptionInfo *exception)
+MagickExport ImageType GetImageType(const Image *image)
{
assert(image != (Image *) NULL);
- assert(image->signature == MagickSignature);
- if (image->debug != MagickFalse)
- (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
+ assert(image->signature == MagickCoreSignature);
if (image->colorspace == CMYKColorspace)
{
- if (image->matte == MagickFalse)
+ if (image->alpha_trait == UndefinedPixelTrait)
return(ColorSeparationType);
- return(ColorSeparationMatteType);
+ return(ColorSeparationAlphaType);
}
- if (IsImageMonochrome(image,exception) != MagickFalse)
+ if (IsImageMonochrome(image) != MagickFalse)
return(BilevelType);
- if (IsImageGray(image,exception) != MagickFalse)
+ if (IsImageGray(image) != MagickFalse)
{
- if (image->matte != MagickFalse)
- return(GrayscaleMatteType);
+ if (image->alpha_trait != UndefinedPixelTrait)
+ return(GrayscaleAlphaType);
return(GrayscaleType);
}
- if (IsPaletteImage(image,exception) != MagickFalse)
+ if (IsPaletteImage(image) != MagickFalse)
{
- if (image->matte != MagickFalse)
- return(PaletteMatteType);
+ if (image->alpha_trait != UndefinedPixelTrait)
+ return(PaletteAlphaType);
return(PaletteType);
}
- if (image->matte != MagickFalse)
- return(TrueColorMatteType);
+ if (image->alpha_trait != UndefinedPixelTrait)
+ return(TrueColorAlphaType);
return(TrueColorType);
}
-\f
+
/*
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% %
% %
% %
-% I s I m a g e G r a y %
+% I d e n t i f y I m a g e G r a y %
% %
% %
% %
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%
-% IsImageGray() returns MagickTrue if all the pixels in the image have the
-% same red, green, and blue intensities.
+% IdentifyImageGray() returns grayscale if all the pixels in the image have
+% the same red, green, and blue intensities, and bi-level is the intensity is
+% either 0 or QuantumRange. Otherwise undefined is returned.
%
-% The format of the IsImageGray method is:
+% The format of the IdentifyImageGray method is:
%
-% MagickBooleanType IsImageGray(const Image *image,
-% ExceptionInfo *exception)
+% ImageType IdentifyImageGray(const Image *image,ExceptionInfo *exception)
%
% A description of each parameter follows:
%
% o exception: return any errors or warnings in this structure.
%
*/
-MagickExport MagickBooleanType IsImageGray(const Image *image,
+MagickExport ImageType IdentifyImageGray(const Image *image,
ExceptionInfo *exception)
{
CacheView
y;
assert(image != (Image *) NULL);
- assert(image->signature == MagickSignature);
+ assert(image->signature == MagickCoreSignature);
if (image->debug != MagickFalse)
(void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
if ((image->type == BilevelType) || (image->type == GrayscaleType) ||
- (image->type == GrayscaleMatteType))
- return(MagickTrue);
- if (IsRGBColorspace(image->colorspace) == MagickFalse)
- return(MagickFalse);
+ (image->type == GrayscaleAlphaType))
+ return(image->type);
+ if (IssRGBCompatibleColorspace(image->colorspace) == MagickFalse)
+ return(UndefinedType);
type=BilevelType;
- image_view=AcquireCacheView(image);
+ image_view=AcquireVirtualCacheView(image,exception);
for (y=0; y < (ssize_t) image->rows; y++)
{
p=GetCacheViewVirtualPixels(image_view,0,y,image->columns,1,exception);
break;
}
image_view=DestroyCacheView(image_view);
- if (type == UndefinedType)
- return(MagickFalse);
- ((Image *) image)->type=type;
- if ((type == GrayscaleType) && (image->matte != MagickFalse))
- ((Image *) image)->type=GrayscaleMatteType;
- return(MagickTrue);
+ if ((type == GrayscaleType) && (image->alpha_trait != UndefinedPixelTrait))
+ type=GrayscaleAlphaType;
+ return(type);
}
-\f
+
/*
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% %
% %
% %
-% I s I m a g e M o n o c h r o m e %
+% I d e n t i f y I m a g e M o n o c h r o m e %
% %
% %
% %
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%
-% IsImageMonochrome() returns MagickTrue if all the pixels in the image have
-% the same red, green, and blue intensities and the intensity is either
+% IdentifyImageMonochrome() returns MagickTrue if all the pixels in the image
+% have the same red, green, and blue intensities and the intensity is either
% 0 or QuantumRange.
%
-% The format of the IsImageMonochrome method is:
+% The format of the IdentifyImageMonochrome method is:
%
-% MagickBooleanType IsImageMonochrome(const Image *image,
+% MagickBooleanType IdentifyImageMonochrome(const Image *image,
% ExceptionInfo *exception)
%
% A description of each parameter follows:
% o exception: return any errors or warnings in this structure.
%
*/
-MagickExport MagickBooleanType IsImageMonochrome(const Image *image,
+MagickExport MagickBooleanType IdentifyImageMonochrome(const Image *image,
ExceptionInfo *exception)
{
CacheView
y;
assert(image != (Image *) NULL);
- assert(image->signature == MagickSignature);
+ assert(image->signature == MagickCoreSignature);
if (image->debug != MagickFalse)
(void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
if (image->type == BilevelType)
return(MagickTrue);
- if (IsRGBColorspace(image->colorspace) == MagickFalse)
+ if (IssRGBCompatibleColorspace(image->colorspace) == MagickFalse)
return(MagickFalse);
type=BilevelType;
- image_view=AcquireCacheView(image);
+ image_view=AcquireVirtualCacheView(image,exception);
for (y=0; y < (ssize_t) image->rows; y++)
{
p=GetCacheViewVirtualPixels(image_view,0,y,image->columns,1,exception);
break;
}
image_view=DestroyCacheView(image_view);
- if (type == UndefinedType)
- return(MagickFalse);
- ((Image *) image)->type=type;
- return(MagickTrue);
+ if (type == BilevelType)
+ return(MagickTrue);
+ return(MagickFalse);
+}
+
+/*
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+% %
+% %
+% %
+% I d e n t i f y I m a g e T y p e %
+% %
+% %
+% %
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%
+% IdentifyImageType() returns the potential type of image:
+%
+% Bilevel Grayscale GrayscaleMatte
+% Palette PaletteMatte TrueColor
+% TrueColorMatte ColorSeparation ColorSeparationMatte
+%
+% To ensure the image type matches its potential, use SetImageType():
+%
+% (void) SetImageType(image,IdentifyImageType(image,exception),exception);
+%
+% The format of the IdentifyImageType method is:
+%
+% ImageType IdentifyImageType(const Image *image,ExceptionInfo *exception)
+%
+% A description of each parameter follows:
+%
+% o image: the image.
+%
+% o exception: return any errors or warnings in this structure.
+%
+*/
+MagickExport ImageType IdentifyImageType(const Image *image,
+ ExceptionInfo *exception)
+{
+ assert(image != (Image *) NULL);
+ assert(image->signature == MagickCoreSignature);
+ if (image->debug != MagickFalse)
+ (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
+ if (image->colorspace == CMYKColorspace)
+ {
+ if (image->alpha_trait == UndefinedPixelTrait)
+ return(ColorSeparationType);
+ return(ColorSeparationAlphaType);
+ }
+ if (IdentifyImageMonochrome(image,exception) != MagickFalse)
+ return(BilevelType);
+ if (IdentifyImageGray(image,exception) != UndefinedType)
+ {
+ if (image->alpha_trait != UndefinedPixelTrait)
+ return(GrayscaleAlphaType);
+ return(GrayscaleType);
+ }
+ if (IdentifyPaletteImage(image,exception) != MagickFalse)
+ {
+ if (image->alpha_trait != UndefinedPixelTrait)
+ return(PaletteAlphaType);
+ return(PaletteType);
+ }
+ if (image->alpha_trait != UndefinedPixelTrait)
+ return(TrueColorAlphaType);
+ return(TrueColorType);
+}
+
+/*
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+% %
+% %
+% %
+% I s I m a g e G r a y %
+% %
+% %
+% %
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%
+% IsImageGray() returns MagickTrue if the type of the image is grayscale or
+% bi-level.
+%
+% The format of the IsImageGray method is:
+%
+% MagickBooleanType IsImageGray(const Image *image)
+%
+% A description of each parameter follows:
+%
+% o image: the image.
+%
+*/
+MagickExport MagickBooleanType IsImageGray(const Image *image)
+{
+ assert(image != (Image *) NULL);
+ assert(image->signature == MagickCoreSignature);
+ if ((image->type == BilevelType) || (image->type == GrayscaleType) ||
+ (image->type == GrayscaleAlphaType))
+ return(MagickTrue);
+ return(MagickFalse);
+}
+\f
+/*
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+% %
+% %
+% %
+% I s I m a g e M o n o c h r o m e %
+% %
+% %
+% %
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%
+% IsImageMonochrome() returns MagickTrue if type of the image is bi-level.
+%
+% The format of the IsImageMonochrome method is:
+%
+% MagickBooleanType IsImageMonochrome(const Image *image)
+%
+% A description of each parameter follows:
+%
+% o image: the image.
+%
+*/
+MagickExport MagickBooleanType IsImageMonochrome(const Image *image)
+{
+ assert(image != (Image *) NULL);
+ assert(image->signature == MagickCoreSignature);
+ if (image->type == BilevelType)
+ return(MagickTrue);
+ return(MagickFalse);
}
\f
/*
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%
% IsImageOpaque() returns MagickTrue if none of the pixels in the image have
-% an opacity value other than opaque (0).
+% an alpha value other than OpaqueAlpha (QuantumRange).
+%
+% Will return true immediatally is alpha channel is not available.
%
% The format of the IsImageOpaque method is:
%
Determine if image is opaque.
*/
assert(image != (Image *) NULL);
- assert(image->signature == MagickSignature);
+ assert(image->signature == MagickCoreSignature);
if (image->debug != MagickFalse)
(void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
- if (image->matte == MagickFalse)
+ if (image->alpha_trait == UndefinedPixelTrait)
return(MagickTrue);
- image_view=AcquireCacheView(image);
+ image_view=AcquireVirtualCacheView(image,exception);
for (y=0; y < (ssize_t) image->rows; y++)
{
p=GetCacheViewVirtualPixels(image_view,0,y,image->columns,1,exception);
p+=GetPixelChannels(image);
}
if (x < (ssize_t) image->columns)
- break;
+ break;
}
image_view=DestroyCacheView(image_view);
return(y < (ssize_t) image->rows ? MagickFalse : MagickTrue);
assert(image != (Image *) NULL);
if (image->debug != MagickFalse)
(void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
- assert(image->signature == MagickSignature);
- if (GetImageDepth(image,exception) <= (size_t)
- MagickMin((double) depth,(double) MAGICKCORE_QUANTUM_DEPTH))
+ assert(image->signature == MagickCoreSignature);
+ if (depth >= MAGICKCORE_QUANTUM_DEPTH)
{
image->depth=depth;
return(MagickTrue);
}
+ range=GetQuantumRange(depth);
+ if (image->storage_class == PseudoClass)
+ {
+ register ssize_t
+ i;
+
+#if defined(MAGICKCORE_OPENMP_SUPPORT)
+ #pragma omp parallel for schedule(static,4) shared(status) \
+ magick_threads(image,image,1,1)
+#endif
+ for (i=0; i < (ssize_t) image->colors; i++)
+ {
+ if ((GetPixelRedTraits(image) & UpdatePixelTrait) != 0)
+ image->colormap[i].red=(double) ScaleAnyToQuantum(ScaleQuantumToAny(
+ ClampPixel(image->colormap[i].red),range),range);
+ if ((GetPixelGreenTraits(image) & UpdatePixelTrait) != 0)
+ image->colormap[i].green=(double) ScaleAnyToQuantum(ScaleQuantumToAny(
+ ClampPixel(image->colormap[i].green),range),range);
+ if ((GetPixelBlueTraits(image) & UpdatePixelTrait) != 0)
+ image->colormap[i].blue=(double) ScaleAnyToQuantum(ScaleQuantumToAny(
+ ClampPixel(image->colormap[i].blue),range),range);
+ if ((GetPixelAlphaTraits(image) & UpdatePixelTrait) != 0)
+ image->colormap[i].alpha=(double) ScaleAnyToQuantum(ScaleQuantumToAny(
+ ClampPixel(image->colormap[i].alpha),range),range);
+ }
+ }
+ status=MagickTrue;
+ image_view=AcquireAuthenticCacheView(image,exception);
+#if !defined(MAGICKCORE_HDRI_SUPPORT)
+ if (QuantumRange <= MaxMap)
+ {
+ Quantum
+ *depth_map;
+
+ register ssize_t
+ i;
+
+ /*
+ Scale pixels to desired (optimized with depth map).
+ */
+ depth_map=(Quantum *) AcquireQuantumMemory(MaxMap+1,sizeof(*depth_map));
+ if (depth_map == (Quantum *) NULL)
+ ThrowFatalException(ResourceLimitFatalError,"MemoryAllocationFailed");
+ for (i=0; i <= (ssize_t) MaxMap; i++)
+ depth_map[i]=ScaleAnyToQuantum(ScaleQuantumToAny((Quantum) i,range),
+ range);
+#if defined(MAGICKCORE_OPENMP_SUPPORT)
+ #pragma omp parallel for schedule(static,4) shared(status) \
+ magick_threads(image,image,image->rows,1)
+#endif
+ for (y=0; y < (ssize_t) image->rows; y++)
+ {
+ register ssize_t
+ x;
+
+ register Quantum
+ *restrict q;
+
+ if (status == MagickFalse)
+ continue;
+ q=GetCacheViewAuthenticPixels(image_view,0,y,image->columns,1,
+ exception);
+ if (q == (Quantum *) NULL)
+ {
+ status=MagickFalse;
+ continue;
+ }
+ for (x=0; x < (ssize_t) image->columns; x++)
+ {
+ register ssize_t
+ i;
+
+ if (GetPixelReadMask(image,q) == 0)
+ {
+ q+=GetPixelChannels(image);
+ continue;
+ }
+ for (i=0; i < (ssize_t) GetPixelChannels(image); i++)
+ {
+ PixelChannel
+ channel;
+
+ PixelTrait
+ traits;
+
+ channel=GetPixelChannelChannel(image,i);
+ traits=GetPixelChannelTraits(image,channel);
+ if ((traits == UndefinedPixelTrait) ||
+ (channel == IndexPixelChannel) ||
+ (channel == ReadMaskPixelChannel))
+ continue;
+ q[i]=depth_map[ScaleQuantumToMap(q[i])];
+ }
+ q+=GetPixelChannels(image);
+ }
+ if (SyncCacheViewAuthenticPixels(image_view,exception) == MagickFalse)
+ {
+ status=MagickFalse;
+ continue;
+ }
+ }
+ image_view=DestroyCacheView(image_view);
+ depth_map=(Quantum *) RelinquishMagickMemory(depth_map);
+ if (status != MagickFalse)
+ image->depth=depth;
+ return(status);
+ }
+#endif
/*
Scale pixels to desired depth.
*/
- status=MagickTrue;
- range=GetQuantumRange(depth);
- image_view=AcquireCacheView(image);
#if defined(MAGICKCORE_OPENMP_SUPPORT)
- #pragma omp parallel for schedule(dynamic,4) shared(status)
+ #pragma omp parallel for schedule(static,4) shared(status) \
+ magick_threads(image,image,image->rows,1)
#endif
for (y=0; y < (ssize_t) image->rows; y++)
{
register ssize_t
i;
+ if (GetPixelReadMask(image,q) == 0)
+ {
+ q+=GetPixelChannels(image);
+ continue;
+ }
for (i=0; i < (ssize_t) GetPixelChannels(image); i++)
{
PixelChannel
PixelTrait
traits;
- channel=GetPixelChannelMapChannel(image,i);
- traits=GetPixelChannelMapTraits(image,channel);
- if (traits == UndefinedPixelTrait)
+ channel=GetPixelChannelChannel(image,i);
+ traits=GetPixelChannelTraits(image,channel);
+ if ((traits == UndefinedPixelTrait) || (channel == IndexPixelChannel) ||
+ (channel == ReadMaskPixelChannel))
continue;
- q[i]=ScaleAnyToQuantum(ScaleQuantumToAny(q[i],range),range);
+ q[i]=ScaleAnyToQuantum(ScaleQuantumToAny(ClampPixel(q[i]),range),range);
}
q+=GetPixelChannels(image);
}
}
}
image_view=DestroyCacheView(image_view);
- if (image->storage_class == PseudoClass)
- {
- register PixelInfo
- *restrict p;
+ if (status != MagickFalse)
+ image->depth=depth;
+ return(status);
+}
+\f
+/*
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+% %
+% %
+% %
+% S e t I m a g e T y p e %
+% %
+% %
+% %
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%
+% SetImageType() sets the type of image. Choose from these types:
+%
+% Bilevel Grayscale GrayscaleMatte
+% Palette PaletteMatte TrueColor
+% TrueColorMatte ColorSeparation ColorSeparationMatte
+% OptimizeType
+%
+% The format of the SetImageType method is:
+%
+% MagickBooleanType SetImageType(Image *image,const ImageType type,
+% ExceptionInfo *exception)
+%
+% A description of each parameter follows:
+%
+% o image: the image.
+%
+% o type: Image type.
+%
+% o exception: return any errors or warnings in this structure.
+%
+*/
+MagickExport MagickBooleanType SetImageType(Image *image,const ImageType type,
+ ExceptionInfo *exception)
+{
+ const char
+ *artifact;
- register ssize_t
- i;
+ ImageInfo
+ *image_info;
- p=image->colormap;
-#if defined(MAGICKCORE_OPENMP_SUPPORT)
- #pragma omp parallel for schedule(dynamic,4) shared(status)
-#endif
- for (i=0; i < (ssize_t) image->colors; i++)
- {
- if ((GetPixelRedTraits(image) & UpdatePixelTrait) != 0)
- p->red=ScaleAnyToQuantum(ScaleQuantumToAny(p->red,range),range);
- if ((GetPixelGreenTraits(image) & UpdatePixelTrait) != 0)
- p->green=ScaleAnyToQuantum(ScaleQuantumToAny(p->green,range),range);
- if ((GetPixelBlueTraits(image) & UpdatePixelTrait) != 0)
- p->blue=ScaleAnyToQuantum(ScaleQuantumToAny(p->blue,range),range);
- if ((GetPixelAlphaTraits(image) & UpdatePixelTrait) != 0)
- p->alpha=ScaleAnyToQuantum(ScaleQuantumToAny(p->alpha,range),range);
- p++;
- }
+ MagickBooleanType
+ status;
+
+ QuantizeInfo
+ *quantize_info;
+
+ assert(image != (Image *) NULL);
+ if (image->debug != MagickFalse)
+ (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
+ assert(image->signature == MagickCoreSignature);
+ status=MagickTrue;
+ image_info=AcquireImageInfo();
+ image_info->dither=image->dither;
+ artifact=GetImageArtifact(image,"dither");
+ if (artifact != (const char *) NULL)
+ (void) SetImageOption(image_info,"dither",artifact);
+ switch (type)
+ {
+ case BilevelType:
+ {
+ if (SetImageMonochrome(image,exception) == MagickFalse)
+ {
+ status=TransformImageColorspace(image,GRAYColorspace,exception);
+ (void) NormalizeImage(image,exception);
+ quantize_info=AcquireQuantizeInfo(image_info);
+ quantize_info->number_colors=2;
+ quantize_info->colorspace=GRAYColorspace;
+ status=QuantizeImage(quantize_info,image,exception);
+ quantize_info=DestroyQuantizeInfo(quantize_info);
+ }
+ image->colors=2;
+ image->alpha_trait=UndefinedPixelTrait;
+ break;
}
- image->depth=depth;
- return(status);
+ case GrayscaleType:
+ {
+ if (SetImageGray(image,exception) == MagickFalse)
+ status=TransformImageColorspace(image,GRAYColorspace,exception);
+ image->alpha_trait=UndefinedPixelTrait;
+ break;
+ }
+ case GrayscaleAlphaType:
+ {
+ if (SetImageGray(image,exception) == MagickFalse)
+ status=TransformImageColorspace(image,GRAYColorspace,exception);
+ if (image->alpha_trait == UndefinedPixelTrait)
+ (void) SetImageAlphaChannel(image,OpaqueAlphaChannel,exception);
+ break;
+ }
+ case PaletteType:
+ {
+ if (IssRGBCompatibleColorspace(image->colorspace) == MagickFalse)
+ status=TransformImageColorspace(image,sRGBColorspace,exception);
+ if ((image->storage_class == DirectClass) || (image->colors > 256))
+ {
+ quantize_info=AcquireQuantizeInfo(image_info);
+ quantize_info->number_colors=256;
+ status=QuantizeImage(quantize_info,image,exception);
+ quantize_info=DestroyQuantizeInfo(quantize_info);
+ }
+ image->alpha_trait=UndefinedPixelTrait;
+ break;
+ }
+ case PaletteBilevelAlphaType:
+ {
+ ChannelType
+ channel_mask;
+
+ if (IssRGBCompatibleColorspace(image->colorspace) == MagickFalse)
+ status=TransformImageColorspace(image,sRGBColorspace,exception);
+ if (image->alpha_trait == UndefinedPixelTrait)
+ (void) SetImageAlphaChannel(image,OpaqueAlphaChannel,exception);
+ channel_mask=SetImageChannelMask(image,AlphaChannel);
+ (void) BilevelImage(image,(double) QuantumRange/2.0,exception);
+ (void) SetImageChannelMask(image,channel_mask);
+ quantize_info=AcquireQuantizeInfo(image_info);
+ status=QuantizeImage(quantize_info,image,exception);
+ quantize_info=DestroyQuantizeInfo(quantize_info);
+ break;
+ }
+ case PaletteAlphaType:
+ {
+ if (IssRGBCompatibleColorspace(image->colorspace) == MagickFalse)
+ status=TransformImageColorspace(image,sRGBColorspace,exception);
+ if (image->alpha_trait == UndefinedPixelTrait)
+ (void) SetImageAlphaChannel(image,OpaqueAlphaChannel,exception);
+ quantize_info=AcquireQuantizeInfo(image_info);
+ quantize_info->colorspace=TransparentColorspace;
+ status=QuantizeImage(quantize_info,image,exception);
+ quantize_info=DestroyQuantizeInfo(quantize_info);
+ break;
+ }
+ case TrueColorType:
+ {
+ if (IssRGBCompatibleColorspace(image->colorspace) == MagickFalse)
+ status=TransformImageColorspace(image,sRGBColorspace,exception);
+ if (image->storage_class != DirectClass)
+ status=SetImageStorageClass(image,DirectClass,exception);
+ image->alpha_trait=UndefinedPixelTrait;
+ break;
+ }
+ case TrueColorAlphaType:
+ {
+ if (IssRGBCompatibleColorspace(image->colorspace) == MagickFalse)
+ status=TransformImageColorspace(image,sRGBColorspace,exception);
+ if (image->storage_class != DirectClass)
+ status=SetImageStorageClass(image,DirectClass,exception);
+ if (image->alpha_trait == UndefinedPixelTrait)
+ (void) SetImageAlphaChannel(image,OpaqueAlphaChannel,exception);
+ break;
+ }
+ case ColorSeparationType:
+ {
+ if (image->colorspace != CMYKColorspace)
+ {
+ if (IssRGBCompatibleColorspace(image->colorspace) == MagickFalse)
+ status=TransformImageColorspace(image,sRGBColorspace,exception);
+ status=TransformImageColorspace(image,CMYKColorspace,exception);
+ }
+ if (image->storage_class != DirectClass)
+ status=SetImageStorageClass(image,DirectClass,exception);
+ image->alpha_trait=UndefinedPixelTrait;
+ break;
+ }
+ case ColorSeparationAlphaType:
+ {
+ if (image->colorspace != CMYKColorspace)
+ {
+ if (IssRGBCompatibleColorspace(image->colorspace) == MagickFalse)
+ status=TransformImageColorspace(image,sRGBColorspace,exception);
+ status=TransformImageColorspace(image,CMYKColorspace,exception);
+ }
+ if (image->storage_class != DirectClass)
+ status=SetImageStorageClass(image,DirectClass,exception);
+ if (image->alpha_trait == UndefinedPixelTrait)
+ status=SetImageAlphaChannel(image,OpaqueAlphaChannel,exception);
+ break;
+ }
+ case OptimizeType:
+ case UndefinedType:
+ break;
+ }
+ image_info=DestroyImageInfo(image_info);
+ if (status == MagickFalse)
+ return(status);
+ image->type=type;
+ return(MagickTrue);
}