]> granicus.if.org Git - imagemagick/blobdiff - MagickCore/pixel-accessor.h
(no commit message)
[imagemagick] / MagickCore / pixel-accessor.h
index fa8c800d7165e5b2f5ff97f86fc62dd5b2dacd21..d6054083ee1a37ba91a086dba01f89d496f23cad 100644 (file)
@@ -1,5 +1,5 @@
 /*
-  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 CompandsRGB(const double intensity)
-{
-  if (intensity <= 0.0031308)
-    return(intensity*12.92);
-  return(1.055*pow(intensity,1.0/2.4)-0.055);
-}
-
-static inline double DecompandsRGB(const double intensity)
+static inline Quantum GetPixela(const Image *restrict image,
+  const Quantum *restrict pixel)
 {
-  if (intensity <= 0.04045)
-    return(intensity/12.92);
-  return(pow((intensity+0.055)/1.055,2.4));
+  return(pixel[image->channel_map[aPixelChannel].offset]);
 }
 
 static inline Quantum GetPixelAlpha(const Image *restrict image,
@@ -58,11 +50,17 @@ static inline PixelTrait GetPixelAlphaTraits(const Image *restrict image)
   return(image->channel_map[AlphaPixelChannel].traits);
 }
 
+static inline Quantum GetPixelb(const Image *restrict image,
+  const Quantum *restrict pixel)
+{
+  return(pixel[image->channel_map[bPixelChannel].offset]);
+}
+
 static inline Quantum GetPixelBlack(const Image *restrict image,
   const Quantum *restrict pixel)
 {
   if (image->channel_map[BlackPixelChannel].traits == UndefinedPixelTrait)
-    return(0);
+    return((Quantum) 0);
   return(pixel[image->channel_map[BlackPixelChannel].offset]);
 }
 
@@ -97,23 +95,23 @@ static inline Quantum GetPixelChannel(const Image *restrict image,
   const PixelChannel channel,const Quantum *restrict pixel)
 {
   if (image->channel_map[channel].traits == UndefinedPixelTrait)
-    return(0);
+    return((Quantum) 0);
   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);
@@ -172,7 +170,7 @@ static inline Quantum GetPixelIndex(const Image *restrict image,
   const Quantum *restrict pixel)
 {
   if (image->channel_map[IndexPixelChannel].traits == UndefinedPixelTrait)
-    return(0);
+    return((Quantum) 0);
   return(pixel[image->channel_map[IndexPixelChannel].offset]);
 }
 
@@ -181,8 +179,8 @@ static inline PixelTrait GetPixelIndexTraits(const Image *restrict image)
   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)
   {
@@ -192,92 +190,91 @@ static inline double GetPixelInfoChannel(const PixelInfo *restrict pixel_info,
     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=QuantumRange*DecompandsRGB(QuantumScale*pixel_info->red);
-  green=QuantumRange*DecompandsRGB(QuantumScale*pixel_info->green);
-  blue=QuantumRange*DecompandsRGB(QuantumScale*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=QuantumRange*DecompandsRGB(QuantumScale*pixel_info->red);
-  green=QuantumRange*DecompandsRGB(QuantumScale*pixel_info->green);
-  blue=QuantumRange*DecompandsRGB(QuantumScale*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 (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,
+  const Quantum *restrict pixel)
+{
+  return(pixel[image->channel_map[LPixelChannel].offset]);
+}
+
+static inline MagickRealType GetPixelLuma(const Image *restrict image,
+  const Quantum *restrict pixel)
+{
   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=QuantumRange*DecompandsRGB(QuantumScale*
-    pixel[image->channel_map[RedPixelChannel].offset]);
-  green=QuantumRange*DecompandsRGB(QuantumScale*
-    pixel[image->channel_map[GreenPixelChannel].offset]);
-  blue=QuantumRange*DecompandsRGB(QuantumScale*
-    pixel[image->channel_map[BluePixelChannel].offset]);
-  return(ClampToQuantum(0.298839*red+0.586811*green+0.114350*blue));
+    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 Quantum GetPixelLuminance(const Image *restrict image,
+static inline MagickRealType GetPixelLuminance(const Image *restrict image,
   const Quantum *restrict pixel)
 {
-  double
+  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=QuantumRange*DecompandsRGB(QuantumScale*
+    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=QuantumRange*DecompandsRGB(QuantumScale*
+  green=DecodePixelGamma((MagickRealType)
     pixel[image->channel_map[GreenPixelChannel].offset]);
-  blue=QuantumRange*DecompandsRGB(QuantumScale*
+  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,
@@ -291,17 +288,25 @@ static inline PixelTrait GetPixelMagentaTraits(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[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[MaskPixelChannel].traits == UndefinedPixelTrait)
-    return(0);
-  return(pixel[image->channel_map[MaskPixelChannel].offset]);
+  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)
@@ -336,23 +341,23 @@ static inline PixelTrait GetPixelRedTraits(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];
 }
 
@@ -384,20 +389,41 @@ static inline PixelTrait GetPixelYellowTraits(const Image *restrict image)
   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);
 }
@@ -405,15 +431,16 @@ static inline MagickBooleanType IsPixelEquivalent(const Image *restrict image,
 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);
 }
@@ -421,27 +448,30 @@ static inline MagickBooleanType IsPixelGray(const Image *restrict image,
 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);
 }
@@ -449,17 +479,19 @@ static inline MagickBooleanType IsPixelInfoEquivalent(
 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);
 }
@@ -470,8 +502,8 @@ static inline MagickBooleanType IsPixelInfoGray(
   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);
 }
@@ -482,15 +514,22 @@ static inline MagickBooleanType IsPixelInfoMonochrome(
   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);
 }
 
+static inline void SetPixela(const Image *restrict image,
+  const Quantum a,Quantum *restrict pixel)
+{
+  if (image->channel_map[aPixelChannel].traits != UndefinedPixelTrait)
+    pixel[image->channel_map[aPixelChannel].offset]=a;
+}
+
 static inline void SetPixelAlpha(const Image *restrict image,
   const Quantum alpha,Quantum *restrict pixel)
 {
@@ -503,6 +542,36 @@ static inline void SetPixelAlphaTraits(Image *image,const PixelTrait traits)
   image->channel_map[AlphaPixelChannel].traits=traits;
 }
 
+static inline void SetPixelb(const Image *restrict image,
+  const Quantum b,Quantum *restrict pixel)
+{
+  if (image->channel_map[bPixelChannel].traits != UndefinedPixelTrait)
+    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)
 {
@@ -544,19 +613,19 @@ static inline void SetPixelChannel(const Image *restrict image,
     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)
@@ -570,12 +639,6 @@ static inline void SetPixelChannelTraits(Image *image,
   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)
 {
@@ -640,8 +703,16 @@ static inline void SetPixelInfoPixel(const Image *restrict image,
     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)
+{
+  if (image->channel_map[LPixelChannel].traits != UndefinedPixelTrait)
+    pixel[image->channel_map[LPixelChannel].offset]=L;
 }
 
 static inline void SetPixelMagenta(const Image *restrict image,
@@ -655,11 +726,18 @@ static inline void SetPixelMagentaTraits(Image *image,const PixelTrait traits)
   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)