/*
- Copyright 1999-2012 ImageMagick Studio LLC, a non-profit organization
+ Copyright 1999-2014 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.
#ifndef _MAGICKCORE_PIXEL_ACCESSOR_H
#define _MAGICKCORE_PIXEL_ACCESSOR_H
+#include "MagickCore/cache.h"
+#include "MagickCore/cache-view.h"
+#include "MagickCore/color.h"
+#include "MagickCore/colorspace.h"
+#include "MagickCore/gem.h"
+#include "MagickCore/image.h"
+
#if defined(__cplusplus) || defined(c_plusplus)
extern "C" {
#endif
-#include <math.h>
-#include <MagickCore/cache.h>
-#include <MagickCore/cache-view.h>
-#include <MagickCore/color.h>
-#include <MagickCore/colorspace.h>
-#include <MagickCore/image.h>
-
#undef index
-static inline double InversesRGBCompandor(const double pixel)
-{
- if (pixel <= (0.04045*QuantumRange))
- return(pixel/12.92);
- return(QuantumRange*pow((QuantumScale*pixel+0.055)/1.055,2.4));
-}
-
-static inline double sRGBCompandor(const double pixel)
-{
- if (pixel <= (0.0031308*QuantumRange))
- return(12.92*pixel);
- return(QuantumRange*(1.055*pow(QuantumScale*pixel,1.0/2.4)-0.055));
-}
-
static inline Quantum GetPixela(const Image *restrict image,
const Quantum *restrict pixel)
{
return(pixel[image->channel_map[channel].offset]);
}
-static inline PixelChannel GetPixelChannelMapChannel(
- const Image *restrict image,const ssize_t offset)
+static inline PixelChannel GetPixelChannelChannel(const Image *restrict image,
+ const ssize_t offset)
{
return(image->channel_map[offset].channel);
}
-static inline ssize_t GetPixelChannelMapOffset(const Image *restrict image,
+static inline ssize_t GetPixelChannelOffset(const Image *restrict image,
const PixelChannel channel)
{
return(image->channel_map[channel].offset);
}
-static inline PixelTrait GetPixelChannelMapTraits(const Image *restrict image,
+static inline PixelTrait GetPixelChannelTraits(const Image *restrict image,
const PixelChannel channel)
{
return(image->channel_map[channel].traits);
return(image->channel_map[IndexPixelChannel].traits);
}
-static inline double GetPixelInfoChannel(const PixelInfo *restrict pixel_info,
- const PixelChannel channel)
+static inline MagickRealType GetPixelInfoChannel(
+ const PixelInfo *restrict pixel_info,const PixelChannel channel)
{
switch (channel)
{
case BlackPixelChannel: return(pixel_info->black);
case AlphaPixelChannel: return(pixel_info->alpha);
case IndexPixelChannel: return(pixel_info->index);
- default: return(0.0);
+ default: return((MagickRealType) 0.0);
}
}
-static inline double GetPixelInfoIntensity(const PixelInfo *restrict pixel_info)
+static inline MagickRealType GetPixelInfoIntensity(
+ const PixelInfo *restrict pixel_info)
{
- double
- blue,
- green,
- red;
-
if (pixel_info->colorspace == GRAYColorspace)
return(pixel_info->red);
- if (pixel_info->colorspace != sRGBColorspace)
- return(0.298839*pixel_info->red+0.586811*pixel_info->green+
- 0.114350*pixel_info->blue);
- red=InversesRGBCompandor(pixel_info->red);
- green=InversesRGBCompandor(pixel_info->green);
- blue=InversesRGBCompandor(pixel_info->blue);
- return(0.298839*red+0.586811*green+0.114350*blue);
+ return(0.212656*pixel_info->red+0.715158*pixel_info->green+0.072186*
+ pixel_info->blue);
}
-static inline double GetPixelInfoLuminance(const PixelInfo *restrict pixel_info)
+static inline MagickRealType GetPixelInfoLuma(const PixelInfo *restrict pixel)
{
- double
+ MagickRealType
blue,
green,
red;
- if (pixel_info->colorspace == GRAYColorspace)
- return(pixel_info->red);
- if (pixel_info->colorspace != sRGBColorspace)
- return(0.21267*pixel_info->red+0.71516*pixel_info->green+
- 0.07217*pixel_info->blue);
- red=InversesRGBCompandor(pixel_info->red);
- green=InversesRGBCompandor(pixel_info->green);
- blue=InversesRGBCompandor(pixel_info->blue);
- return(0.21267*red+0.71516*green+0.07217*blue);
+ if (pixel->colorspace == GRAYColorspace)
+ return(pixel->red);
+ if (pixel->colorspace == sRGBColorspace)
+ return(0.212656*pixel->red+0.715158*pixel->green+0.072186*pixel->blue);
+ red=EncodePixelGamma(pixel->red);
+ green=EncodePixelGamma(pixel->green);
+ blue=EncodePixelGamma(pixel->blue);
+ return(0.212656*red+0.715158*green+0.072186*blue);
}
-static inline Quantum GetPixelIntensity(const Image *restrict image,
- const Quantum *restrict pixel)
+static inline MagickRealType GetPixelInfoLuminance(
+ const PixelInfo *restrict pixel)
{
- double
+ MagickRealType
blue,
green,
red;
- if (image->colorspace == GRAYColorspace)
- return(pixel[image->channel_map[GrayPixelChannel].offset]);
- if (image->colorspace != sRGBColorspace)
- return(ClampToQuantum(
- 0.298839*pixel[image->channel_map[RedPixelChannel].offset]+
- 0.586811*pixel[image->channel_map[GreenPixelChannel].offset]+
- 0.114350*pixel[image->channel_map[BluePixelChannel].offset]));
- red=InversesRGBCompandor((double)
- pixel[image->channel_map[RedPixelChannel].offset]);
- green=InversesRGBCompandor((double)
- pixel[image->channel_map[GreenPixelChannel].offset]);
- blue=InversesRGBCompandor((double)
- pixel[image->channel_map[BluePixelChannel].offset]);
- return(ClampToQuantum(0.298839*red+0.586811*green+0.114350*blue));
+ if (pixel->colorspace == GRAYColorspace)
+ return(pixel->red);
+ if (pixel->colorspace != sRGBColorspace)
+ return(0.212656*pixel->red+0.715158*pixel->green+0.072186*pixel->blue);
+ red=DecodePixelGamma(pixel->red);
+ green=DecodePixelGamma(pixel->green);
+ blue=DecodePixelGamma(pixel->blue);
+ return(0.212656*red+0.715158*green+0.072186*blue);
}
static inline Quantum GetPixelL(const Image *restrict image,
return(pixel[image->channel_map[LPixelChannel].offset]);
}
-static inline Quantum GetPixelLuminance(const Image *restrict image,
+static inline MagickRealType GetPixelLuma(const Image *restrict image,
const Quantum *restrict pixel)
{
- double
+ if (image->colorspace == GRAYColorspace)
+ return((MagickRealType) pixel[image->channel_map[GrayPixelChannel].offset]);
+ return(0.212656f*pixel[image->channel_map[RedPixelChannel].offset]+
+ 0.715158f*pixel[image->channel_map[GreenPixelChannel].offset]+
+ 0.072186f*pixel[image->channel_map[BluePixelChannel].offset]); /* Rec709 */
+}
+
+static inline MagickRealType GetPixelLuminance(const Image *restrict image,
+ const Quantum *restrict pixel)
+{
+ MagickRealType
blue,
green,
red;
if (image->colorspace == GRAYColorspace)
- return(pixel[image->channel_map[GrayPixelChannel].offset]);
+ return((MagickRealType) pixel[image->channel_map[GrayPixelChannel].offset]);
if (image->colorspace != sRGBColorspace)
- return(ClampToQuantum(
- 0.298839*pixel[image->channel_map[RedPixelChannel].offset]+
- 0.586811*pixel[image->channel_map[GreenPixelChannel].offset]+
- 0.114350*pixel[image->channel_map[BluePixelChannel].offset]));
- red=InversesRGBCompandor((double)
+ return(0.212656*pixel[image->channel_map[RedPixelChannel].offset]+
+ 0.715158*pixel[image->channel_map[GreenPixelChannel].offset]+
+ 0.072186*pixel[image->channel_map[BluePixelChannel].offset]);
+ red=DecodePixelGamma((MagickRealType)
pixel[image->channel_map[RedPixelChannel].offset]);
- green=InversesRGBCompandor((double)
+ green=DecodePixelGamma((MagickRealType)
pixel[image->channel_map[GreenPixelChannel].offset]);
- blue=InversesRGBCompandor((double)
+ blue=DecodePixelGamma((MagickRealType)
pixel[image->channel_map[BluePixelChannel].offset]);
- return(ClampToQuantum(0.21267*red+0.71516*green+0.07217*blue));
+ return(0.212656*red+0.715158*green+0.072186*blue); /* Rec709 */
}
static inline Quantum GetPixelMagenta(const Image *restrict image,
return(image->channel_map[MagentaPixelChannel].traits);
}
-static inline Quantum GetPixelMask(const Image *restrict image,
+static inline Quantum GetPixelReadMask(const Image *restrict image,
const Quantum *restrict pixel)
{
- if (image->channel_map[MaskPixelChannel].traits == UndefinedPixelTrait)
- return((Quantum) 0);
- return(pixel[image->channel_map[MaskPixelChannel].offset]);
+ if (image->channel_map[ReadMaskPixelChannel].traits == UndefinedPixelTrait)
+ return((Quantum) QuantumRange);
+ return(pixel[image->channel_map[ReadMaskPixelChannel].offset]);
+}
+
+static inline Quantum GetPixelWriteMask(const Image *restrict image,
+ const Quantum *restrict pixel)
+{
+ if (image->channel_map[WriteMaskPixelChannel].traits == UndefinedPixelTrait)
+ return((Quantum) QuantumRange);
+ return(pixel[image->channel_map[WriteMaskPixelChannel].offset]);
}
-static inline PixelTrait GetPixelMaskTraits(const Image *restrict image)
+static inline PixelTrait GetPixelReadMaskTraits(const Image *restrict image)
{
- return(image->channel_map[MaskPixelChannel].traits);
+ return(image->channel_map[ReadMaskPixelChannel].traits);
}
static inline size_t GetPixelMetaChannels(const Image *restrict image)
static inline void GetPixelInfoPixel(const Image *restrict image,
const Quantum *restrict pixel,PixelInfo *restrict pixel_info)
{
- pixel_info->red=(double)
+ pixel_info->red=(MagickRealType)
pixel[image->channel_map[RedPixelChannel].offset];
- pixel_info->green=(double)
+ pixel_info->green=(MagickRealType)
pixel[image->channel_map[GreenPixelChannel].offset];
- pixel_info->blue=(double)
+ pixel_info->blue=(MagickRealType)
pixel[image->channel_map[BluePixelChannel].offset];
- pixel_info->black=0.0;
+ pixel_info->black=0.0f;
if (image->channel_map[BlackPixelChannel].traits != UndefinedPixelTrait)
- pixel_info->black=(double)
+ pixel_info->black=(MagickRealType)
pixel[image->channel_map[BlackPixelChannel].offset];
- pixel_info->alpha=OpaqueAlpha;
+ pixel_info->alpha=(MagickRealType) OpaqueAlpha;
if (image->channel_map[AlphaPixelChannel].traits != UndefinedPixelTrait)
- pixel_info->alpha=(double)
+ pixel_info->alpha=(MagickRealType)
pixel[image->channel_map[AlphaPixelChannel].offset];
- pixel_info->index=0.0;
+ pixel_info->index=0.0f;
if (image->channel_map[IndexPixelChannel].traits != UndefinedPixelTrait)
- pixel_info->index=(double)
+ pixel_info->index=(MagickRealType)
pixel[image->channel_map[IndexPixelChannel].offset];
}
return(image->channel_map[YellowPixelChannel].traits);
}
+static inline MagickRealType AbsolutePixelValue(const MagickRealType x)
+{
+ return(x < 0.0f ? -x : x);
+}
+
+static inline MagickBooleanType IsPixelAtDepth(const Quantum pixel,
+ const QuantumAny range)
+{
+ Quantum
+ quantum;
+
+#if !defined(MAGICKCORE_HDRI_SUPPORT)
+ quantum=(Quantum) (((MagickRealType) QuantumRange*((QuantumAny)
+ (((MagickRealType) range*pixel)/QuantumRange+0.5)))/range+0.5);
+#else
+ quantum=(Quantum) (((MagickRealType) QuantumRange*((QuantumAny)
+ (((MagickRealType) range*pixel)/QuantumRange+0.5)))/range);
+#endif
+ return(pixel == quantum ? MagickTrue : MagickFalse);
+}
+
static inline MagickBooleanType IsPixelEquivalent(const Image *restrict image,
const Quantum *restrict p,const PixelInfo *restrict q)
{
- double
+ MagickRealType
blue,
green,
red;
- red=(double) p[image->channel_map[RedPixelChannel].offset];
- green=(double) p[image->channel_map[GreenPixelChannel].offset];
- blue=(double) p[image->channel_map[BluePixelChannel].offset];
- if ((fabs(red-q->red) < MagickEpsilon) &&
- (fabs(green-q->green) < MagickEpsilon) &&
- (fabs(blue-q->blue) < MagickEpsilon))
+ red=(MagickRealType) p[image->channel_map[RedPixelChannel].offset];
+ green=(MagickRealType) p[image->channel_map[GreenPixelChannel].offset];
+ blue=(MagickRealType) p[image->channel_map[BluePixelChannel].offset];
+ if ((AbsolutePixelValue(red-q->red) < MagickEpsilon) &&
+ (AbsolutePixelValue(green-q->green) < MagickEpsilon) &&
+ (AbsolutePixelValue(blue-q->blue) < MagickEpsilon))
return(MagickTrue);
return(MagickFalse);
}
static inline MagickBooleanType IsPixelGray(const Image *restrict image,
const Quantum *restrict pixel)
{
- double
+ MagickRealType
blue,
green,
red;
- red=(double) pixel[image->channel_map[RedPixelChannel].offset];
- green=(double) pixel[image->channel_map[GreenPixelChannel].offset];
- blue=(double) pixel[image->channel_map[BluePixelChannel].offset];
- if ((fabs(red-green) < MagickEpsilon) && (fabs(green-blue) < MagickEpsilon))
+ red=(MagickRealType) pixel[image->channel_map[RedPixelChannel].offset];
+ green=(MagickRealType) pixel[image->channel_map[GreenPixelChannel].offset];
+ blue=(MagickRealType) pixel[image->channel_map[BluePixelChannel].offset];
+ if ((AbsolutePixelValue(red-green) < MagickEpsilon) &&
+ (AbsolutePixelValue(green-blue) < MagickEpsilon))
return(MagickTrue);
return(MagickFalse);
}
static inline MagickBooleanType IsPixelInfoEquivalent(
const PixelInfo *restrict p,const PixelInfo *restrict q)
{
- if ((p->matte != MagickFalse) && (q->matte == MagickFalse) &&
- (fabs(p->alpha-OpaqueAlpha) >= MagickEpsilon))
+ if ((p->alpha_trait == BlendPixelTrait) &&
+ (q->alpha_trait != BlendPixelTrait) &&
+ (AbsolutePixelValue(p->alpha-OpaqueAlpha) >= MagickEpsilon))
return(MagickFalse);
- if ((q->matte != MagickFalse) && (p->matte == MagickFalse) &&
- (fabs(q->alpha-OpaqueAlpha)) >= MagickEpsilon)
+ if ((q->alpha_trait == BlendPixelTrait) &&
+ (p->alpha_trait != BlendPixelTrait) &&
+ (AbsolutePixelValue(q->alpha-OpaqueAlpha)) >= MagickEpsilon)
return(MagickFalse);
- if ((p->matte != MagickFalse) && (q->matte != MagickFalse))
+ if ((p->alpha_trait == BlendPixelTrait) &&
+ (q->alpha_trait == BlendPixelTrait))
{
- if (fabs(p->alpha-q->alpha) >= MagickEpsilon)
+ if (AbsolutePixelValue(p->alpha-q->alpha) >= MagickEpsilon)
return(MagickFalse);
- if (fabs(p->alpha-TransparentAlpha) < MagickEpsilon)
+ if (AbsolutePixelValue(p->alpha-TransparentAlpha) < MagickEpsilon)
return(MagickTrue);
}
- if (fabs(p->red-q->red) >= MagickEpsilon)
+ if (AbsolutePixelValue(p->red-q->red) >= MagickEpsilon)
return(MagickFalse);
- if (fabs(p->green-q->green) >= MagickEpsilon)
+ if (AbsolutePixelValue(p->green-q->green) >= MagickEpsilon)
return(MagickFalse);
- if (fabs(p->blue-q->blue) >= MagickEpsilon)
+ if (AbsolutePixelValue(p->blue-q->blue) >= MagickEpsilon)
return(MagickFalse);
if ((p->colorspace == CMYKColorspace) &&
- (fabs(p->black-q->black) >= MagickEpsilon))
+ (AbsolutePixelValue(p->black-q->black) >= MagickEpsilon))
return(MagickFalse);
return(MagickTrue);
}
static inline MagickBooleanType IsPixelMonochrome(const Image *restrict image,
const Quantum *restrict pixel)
{
- double
+ MagickRealType
blue,
green,
red;
- red=(double) pixel[image->channel_map[RedPixelChannel].offset];
- if ((fabs(red) >= MagickEpsilon) || (fabs(red-QuantumRange) >= MagickEpsilon))
+ red=(MagickRealType) pixel[image->channel_map[RedPixelChannel].offset];
+ if ((AbsolutePixelValue(red) >= MagickEpsilon) ||
+ (AbsolutePixelValue(red-QuantumRange) >= MagickEpsilon))
return(MagickFalse);
- green=(double) pixel[image->channel_map[GreenPixelChannel].offset];
- blue=(double) pixel[image->channel_map[BluePixelChannel].offset];
- if ((fabs(red-green) < MagickEpsilon) && (fabs(green-blue) < MagickEpsilon))
+ green=(MagickRealType) pixel[image->channel_map[GreenPixelChannel].offset];
+ blue=(MagickRealType) pixel[image->channel_map[BluePixelChannel].offset];
+ if ((AbsolutePixelValue(red-green) < MagickEpsilon) &&
+ (AbsolutePixelValue(green-blue) < MagickEpsilon))
return(MagickTrue);
return(MagickFalse);
}
if ((pixel_info->colorspace != GRAYColorspace) &&
(pixel_info->colorspace != RGBColorspace))
return(MagickFalse);
- if ((fabs(pixel_info->red-pixel_info->green) < MagickEpsilon) &&
- (fabs(pixel_info->green-pixel_info->blue) < MagickEpsilon))
+ if ((AbsolutePixelValue(pixel_info->red-pixel_info->green) < MagickEpsilon) &&
+ (AbsolutePixelValue(pixel_info->green-pixel_info->blue) < MagickEpsilon))
return(MagickTrue);
return(MagickFalse);
}
if ((pixel_info->colorspace != GRAYColorspace) &&
(pixel_info->colorspace != RGBColorspace))
return(MagickFalse);
- if ((fabs(pixel_info->red) >= MagickEpsilon) ||
- (fabs(pixel_info->red-QuantumRange) >= MagickEpsilon))
+ if ((AbsolutePixelValue(pixel_info->red) >= MagickEpsilon) ||
+ (AbsolutePixelValue(pixel_info->red-QuantumRange) >= MagickEpsilon))
return(MagickFalse);
- if ((fabs(pixel_info->red-pixel_info->green) < MagickEpsilon) &&
- (fabs(pixel_info->green-pixel_info->blue) < MagickEpsilon))
+ if ((AbsolutePixelValue(pixel_info->red-pixel_info->green) < MagickEpsilon) &&
+ (AbsolutePixelValue(pixel_info->green-pixel_info->blue) < MagickEpsilon))
return(MagickTrue);
return(MagickFalse);
}
pixel[image->channel_map[bPixelChannel].offset]=b;
}
+static inline void SetPixelBackgoundColor(const Image *restrict image,
+ Quantum *restrict pixel)
+{
+ register ssize_t
+ i;
+
+ for (i=0; i < (ssize_t) GetPixelChannels(image); i++)
+ pixel[i]=0;
+ pixel[image->channel_map[RedPixelChannel].offset]=
+ ClampToQuantum(image->background_color.red);
+ pixel[image->channel_map[GreenPixelChannel].offset]=
+ ClampToQuantum(image->background_color.green);
+ pixel[image->channel_map[BluePixelChannel].offset]=
+ ClampToQuantum(image->background_color.blue);
+ if (image->channel_map[BlackPixelChannel].traits != UndefinedPixelTrait)
+ pixel[image->channel_map[BlackPixelChannel].offset]=
+ ClampToQuantum(image->background_color.black);
+ if (image->channel_map[AlphaPixelChannel].traits != UndefinedPixelTrait)
+ pixel[image->channel_map[AlphaPixelChannel].offset]=
+ image->background_color.alpha_trait != BlendPixelTrait ? OpaqueAlpha :
+ ClampToQuantum(image->background_color.alpha);
+}
+
static inline void SetPixelBlack(const Image *restrict image,
const Quantum black,Quantum *restrict pixel)
{
pixel[image->channel_map[channel].offset]=quantum;
}
-static inline void SetPixelChannelMapChannel(const Image *restrict image,
- const PixelChannel channel,const ssize_t offset)
+static inline void SetPixelChannelAttributes(const Image *restrict image,
+ const PixelChannel channel,const PixelTrait traits,const ssize_t offset)
{
image->channel_map[offset].channel=channel;
image->channel_map[channel].offset=offset;
+ image->channel_map[channel].traits=traits;
}
-static inline void SetPixelChannelMap(const Image *restrict image,
- const PixelChannel channel,const PixelTrait traits,const ssize_t offset)
+static inline void SetPixelChannelChannel(const Image *restrict image,
+ const PixelChannel channel,const ssize_t offset)
{
image->channel_map[offset].channel=channel;
image->channel_map[channel].offset=offset;
- image->channel_map[channel].traits=traits;
}
static inline void SetPixelChannels(Image *image,const size_t number_channels)
image->channel_map[channel].traits=traits;
}
-static inline void SetPixelChannelMapTraits(Image *image,
- const PixelChannel channel,const PixelTrait traits)
-{
- image->channel_map[channel].traits=traits;
-}
-
static inline void SetPixelCr(const Image *restrict image,const Quantum cr,
Quantum *restrict pixel)
{
pixel[image->channel_map[BlackPixelChannel].offset]=
ClampToQuantum(pixel_info->black);
if (image->channel_map[AlphaPixelChannel].traits != UndefinedPixelTrait)
- pixel[image->channel_map[AlphaPixelChannel].offset]=pixel_info->matte ==
- MagickFalse ? OpaqueAlpha : ClampToQuantum(pixel_info->alpha);
+ pixel[image->channel_map[AlphaPixelChannel].offset]=
+ pixel_info->alpha_trait != BlendPixelTrait ? OpaqueAlpha :
+ ClampToQuantum(pixel_info->alpha);
}
-static inline void SetPixelL(const Image *restrict image,
- const Quantum L,Quantum *restrict pixel)
+static inline void SetPixelL(const Image *restrict image,const Quantum L,
+ Quantum *restrict pixel)
{
if (image->channel_map[LPixelChannel].traits != UndefinedPixelTrait)
pixel[image->channel_map[LPixelChannel].offset]=L;
image->channel_map[MagentaPixelChannel].traits=traits;
}
-static inline void SetPixelMask(const Image *restrict image,
+static inline void SetPixelReadMask(const Image *restrict image,
+ const Quantum mask,Quantum *restrict pixel)
+{
+ if (image->channel_map[ReadMaskPixelChannel].traits != UndefinedPixelTrait)
+ pixel[image->channel_map[ReadMaskPixelChannel].offset]=mask;
+}
+
+static inline void SetPixelWriteMask(const Image *restrict image,
const Quantum mask,Quantum *restrict pixel)
{
- if (image->channel_map[MaskPixelChannel].traits != UndefinedPixelTrait)
- pixel[image->channel_map[MaskPixelChannel].offset]=mask;
+ if (image->channel_map[WriteMaskPixelChannel].traits != UndefinedPixelTrait)
+ pixel[image->channel_map[WriteMaskPixelChannel].offset]=mask;
}
static inline void SetPixelMetacontentExtent(Image *image,const size_t extent)