% %
% %
% %
-% I n t e r p o l a t e M a g i c k P i x e l P a c k e t %
+% I n t e r p o l a t e P i x e l C h a n n e l %
% %
% %
% %
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%
-% InterpolatePixelInfo() applies bi-linear or tri-linear interpolation
-% between a floating point coordinate and the pixels surrounding that
-% coordinate. No pixel area resampling, or scaling of the result is
-% performed.
+% InterpolatePixelChannel() applies a pixel interpolation method between a
+% floating point coordinate and the pixels surrounding that coordinate. No
+% pixel area resampling, or scaling of the result is performed.
+%
+% The format of the InterpolatePixelChannel method is:
+%
+% MagickBooleanType InterpolatePixelChannel(const Image *image,
+% const PixelChannel channel,const CacheView *image_view,
+% const InterpolatePixelMethod method,const double x,const double y,
+% double *pixel,ExceptionInfo *exception)
+%
+% A description of each parameter follows:
+%
+% o image: the image.
+%
+% o image_view: the image view.
+%
+% o channel: the pixel channel to interpolate.
+%
+% o method: the pixel color interpolation method.
+%
+% o x,y: A double representing the current (x,y) position of the pixel.
+%
+% o pixel: return the interpolated pixel here.
+%
+% o exception: return any errors or warnings in this structure.
+%
+*/
+
+static inline double MagickMax(const MagickRealType x,const MagickRealType y)
+{
+ if (x > y)
+ return(x);
+ return(y);
+}
+
+static inline MagickRealType CubicWeightingFunction(const MagickRealType x)
+{
+ MagickRealType
+ alpha,
+ gamma;
+
+ alpha=MagickMax(x+2.0,0.0);
+ gamma=1.0*alpha*alpha*alpha;
+ alpha=MagickMax(x+1.0,0.0);
+ gamma-=4.0*alpha*alpha*alpha;
+ alpha=MagickMax(x+0.0,0.0);
+ gamma+=6.0*alpha*alpha*alpha;
+ alpha=MagickMax(x-1.0,0.0);
+ gamma-=4.0*alpha*alpha*alpha;
+ return(gamma/6.0);
+}
+
+static inline double MeshInterpolate(const PointInfo *delta,const double p,
+ const double x,const double y)
+{
+ return(delta->x*x+delta->y*y+(1.0-delta->x-delta->y)*p);
+}
+
+static inline ssize_t NearestNeighbor(const MagickRealType x)
+{
+ if (x >= 0.0)
+ return((ssize_t) (x+0.5));
+ return((ssize_t) (x-0.5));
+}
+
+MagickExport MagickBooleanType InterpolatePixelChannel(const Image *image,
+ const CacheView *image_view,const PixelChannel channel,
+ const InterpolatePixelMethod method,const double x,const double y,
+ double *pixel,ExceptionInfo *exception)
+{
+ MagickBooleanType
+ status;
+
+ MagickRealType
+ alpha[16],
+ gamma,
+ pixels[16];
+
+ PixelTrait
+ traits;
+
+ register const Quantum
+ *p;
+
+ register ssize_t
+ i;
+
+ ssize_t
+ x_offset,
+ y_offset;
+
+ assert(image != (Image *) NULL);
+ assert(image != (Image *) NULL);
+ assert(image->signature == MagickSignature);
+ assert(image_view != (CacheView *) NULL);
+ status=MagickTrue;
+ *pixel=0.0;
+ traits=GetPixelChannelMapTraits(image,channel);
+ x_offset=(ssize_t) floor(x);
+ y_offset=(ssize_t) floor(y);
+ switch (method == UndefinedInterpolatePixel ? image->interpolate : method)
+ {
+ case AverageInterpolatePixel:
+ {
+ p=GetCacheViewVirtualPixels(image_view,x_offset-1,y_offset-1,4,4,
+ exception);
+ if (p == (const Quantum *) NULL)
+ {
+ status=MagickFalse;
+ break;
+ }
+ if (((traits & BlendPixelTrait) == 0) ||
+ (GetPixelAlphaTraits(image) == UndefinedPixelTrait) ||
+ (image->matte == MagickFalse))
+ for (i=0; i < 16; i++)
+ {
+ alpha[i]=1.0;
+ pixels[i]=(MagickRealType) p[i*GetPixelChannels(image)+channel];
+ }
+ else
+ for (i=0; i < 16; i++)
+ {
+ alpha[i]=QuantumScale*GetPixelAlpha(image,p+i*
+ GetPixelChannels(image));
+ pixels[i]=alpha[i]*p[i*GetPixelChannels(image)+channel];
+ }
+ for (i=0; i < 16; i++)
+ {
+ gamma=1.0/(fabs((double) alpha[i]) <= MagickEpsilon ? 1.0 : alpha[i]);
+ *pixel+=gamma*0.0625*pixels[i];
+ }
+ break;
+ }
+ case BicubicInterpolatePixel:
+ {
+ MagickRealType
+ u[4],
+ v[4];
+
+ PointInfo
+ delta;
+
+ p=GetCacheViewVirtualPixels(image_view,x_offset-1,y_offset-1,4,4,
+ exception);
+ if (p == (const Quantum *) NULL)
+ {
+ status=MagickFalse;
+ break;
+ }
+ if (((traits & BlendPixelTrait) == 0) ||
+ (GetPixelAlphaTraits(image) == UndefinedPixelTrait) ||
+ (image->matte == MagickFalse))
+ for (i=0; i < 16; i++)
+ {
+ alpha[i]=1.0;
+ pixels[i]=(MagickRealType) p[i*GetPixelChannels(image)+channel];
+ }
+ else
+ for (i=0; i < 16; i++)
+ {
+ alpha[i]=QuantumScale*GetPixelAlpha(image,p+i*
+ GetPixelChannels(image));
+ pixels[i]=alpha[i]*p[i*GetPixelChannels(image)+channel];
+ }
+ delta.x=x-x_offset;
+ delta.y=y-y_offset;
+ for (i=0; i < 4; i++)
+ {
+ u[0]=(pixels[4*i+3]-pixels[4*i+2])-(pixels[4*i+0]-pixels[4*i+1]);
+ u[1]=(pixels[4*i+0]-pixels[4*i+1])-u[0];
+ u[2]=pixels[4*i+2]-pixels[4*i+0];
+ u[3]=pixels[4*i+1];
+ v[i]=(delta.x*delta.x*delta.x*u[0])+(delta.x*delta.x*u[1])+(delta.x*
+ u[2])+u[3];
+ }
+ u[0]=(v[3]-v[2])-(v[0]-v[1]);
+ u[1]=(v[0]-v[1])-u[0];
+ u[2]=v[2]-v[0];
+ u[3]=v[1];
+ *pixel=(delta.y*delta.y*delta.y*u[0])+(delta.y*delta.y*u[1])+(delta.y*
+ u[2])+u[3];
+ break;
+ }
+ case BilinearInterpolatePixel:
+ default:
+ {
+ PointInfo
+ delta,
+ epsilon;
+
+ p=GetCacheViewVirtualPixels(image_view,x_offset,y_offset,2,2,exception);
+ if (p == (const Quantum *) NULL)
+ {
+ status=MagickFalse;
+ break;
+ }
+ if (((traits & BlendPixelTrait) == 0) ||
+ (GetPixelAlphaTraits(image) == UndefinedPixelTrait) ||
+ (image->matte == MagickFalse))
+ for (i=0; i < 4; i++)
+ {
+ alpha[i]=1.0;
+ pixels[i]=(MagickRealType) p[i*GetPixelChannels(image)+channel];
+ }
+ else
+ for (i=0; i < 4; i++)
+ {
+ alpha[i]=QuantumScale*GetPixelAlpha(image,p+i*
+ GetPixelChannels(image));
+ pixels[i]=alpha[i]*p[i*GetPixelChannels(image)+channel];
+ }
+ delta.x=x-x_offset;
+ delta.y=y-y_offset;
+ epsilon.x=1.0-delta.x;
+ epsilon.y=1.0-delta.y;
+ gamma=((epsilon.y*(epsilon.x*alpha[0]+delta.x*alpha[1])+delta.y*
+ (epsilon.x*alpha[2]+delta.x*alpha[3])));
+ gamma=1.0/(fabs((double) gamma) <= MagickEpsilon ? 1.0 : gamma);
+ *pixel=gamma*(epsilon.y*(epsilon.x*pixels[0]+delta.x*pixels[1])+delta.y*
+ (epsilon.x*pixels[2]+delta.x*pixels[3]));
+ break;
+ }
+ case FilterInterpolatePixel:
+ {
+ CacheView
+ *filter_view;
+
+ Image
+ *excerpt_image,
+ *filter_image;
+
+ RectangleInfo
+ geometry;
+
+ geometry.width=4L;
+ geometry.height=4L;
+ geometry.x=x_offset-1;
+ geometry.y=y_offset-1;
+ excerpt_image=ExcerptImage(image,&geometry,exception);
+ if (excerpt_image == (Image *) NULL)
+ {
+ status=MagickFalse;
+ break;
+ }
+ filter_image=ResizeImage(excerpt_image,1,1,image->filter,image->blur,
+ exception);
+ excerpt_image=DestroyImage(excerpt_image);
+ if (filter_image == (Image *) NULL)
+ break;
+ filter_view=AcquireCacheView(filter_image);
+ p=GetCacheViewVirtualPixels(filter_view,0,0,1,1,exception);
+ if (p == (const Quantum *) NULL)
+ status=MagickFalse;
+ else
+ *pixel=(double) p[channel];
+ filter_view=DestroyCacheView(filter_view);
+ filter_image=DestroyImage(filter_image);
+ break;
+ }
+ case IntegerInterpolatePixel:
+ {
+ p=GetCacheViewVirtualPixels(image_view,x_offset,y_offset,1,1,exception);
+ if (p == (const Quantum *) NULL)
+ {
+ status=MagickFalse;
+ break;
+ }
+ *pixel=(double) p[channel];
+ break;
+ }
+ case NearestNeighborInterpolatePixel:
+ {
+ p=GetCacheViewVirtualPixels(image_view,NearestNeighbor(x),
+ NearestNeighbor(y),1,1,exception);
+ if (p == (const Quantum *) NULL)
+ {
+ status=MagickFalse;
+ break;
+ }
+ *pixel=(double) p[channel];
+ break;
+ }
+ case MeshInterpolatePixel:
+ {
+ PointInfo
+ delta,
+ luminance;
+
+ p=GetCacheViewVirtualPixels(image_view,x_offset,y_offset,2,2,exception);
+ if (p == (const Quantum *) NULL)
+ {
+ status=MagickFalse;
+ break;
+ }
+ if (((traits & BlendPixelTrait) == 0) ||
+ (GetPixelAlphaTraits(image) == UndefinedPixelTrait) ||
+ (image->matte == MagickFalse))
+ for (i=0; i < 4; i++)
+ {
+ alpha[i]=1.0;
+ pixels[i]=(MagickRealType) p[i*GetPixelChannels(image)+channel];
+ }
+ else
+ for (i=0; i < 4; i++)
+ {
+ alpha[i]=QuantumScale*GetPixelAlpha(image,p+i*
+ GetPixelChannels(image));
+ pixels[i]=alpha[i]*p[i*GetPixelChannels(image)+channel];
+ }
+ delta.x=x-x_offset;
+ delta.y=y-y_offset;
+ luminance.x=GetPixelLuminance(image,p)-(double)
+ GetPixelLuminance(image,p+3*GetPixelChannels(image));
+ luminance.y=GetPixelLuminance(image,p+1*GetPixelChannels(image))-(double)
+ GetPixelLuminance(image,p+2*GetPixelChannels(image));
+ if (fabs(luminance.x) < fabs(luminance.y))
+ {
+ /*
+ Diagonal 0-3 NW-SE.
+ */
+ if (delta.x <= delta.y)
+ {
+ /*
+ Bottom-left triangle (pixel: 2, diagonal: 0-3).
+ */
+ delta.y=1.0-delta.y;
+ gamma=MeshInterpolate(&delta,alpha[2],alpha[3],alpha[0]);
+ gamma=1.0/(fabs((double) gamma) <= MagickEpsilon ? 1.0 : gamma);
+ *pixel=gamma*MeshInterpolate(&delta,pixels[2],pixels[3],
+ pixels[0]);
+ }
+ else
+ {
+ /*
+ Top-right triangle (pixel: 1, diagonal: 0-3).
+ */
+ delta.x=1.0-delta.x;
+ gamma=MeshInterpolate(&delta,alpha[1],alpha[0],alpha[3]);
+ gamma=1.0/(fabs((double) gamma) <= MagickEpsilon ? 1.0 : gamma);
+ *pixel=gamma*MeshInterpolate(&delta,pixels[1],pixels[0],
+ pixels[3]);
+ }
+ }
+ else
+ {
+ /*
+ Diagonal 1-2 NE-SW.
+ */
+ if (delta.x <= (1.0-delta.y))
+ {
+ /*
+ Top-left triangle (pixel: 0, diagonal: 1-2).
+ */
+ gamma=MeshInterpolate(&delta,alpha[0],alpha[1],alpha[2]);
+ gamma=1.0/(fabs((double) gamma) <= MagickEpsilon ? 1.0 : gamma);
+ *pixel=gamma*MeshInterpolate(&delta,pixels[0],pixels[1],
+ pixels[2]);
+ }
+ else
+ {
+ /*
+ Bottom-right triangle (pixel: 3, diagonal: 1-2).
+ */
+ delta.x=1.0-delta.x;
+ delta.y=1.0-delta.y;
+ gamma=MeshInterpolate(&delta,alpha[3],alpha[2],alpha[1]);
+ gamma=1.0/(fabs((double) gamma) <= MagickEpsilon ? 1.0 : gamma);
+ *pixel=gamma*MeshInterpolate(&delta,pixels[3],pixels[2],
+ pixels[1]);
+ }
+ }
+ break;
+ }
+ case SplineInterpolatePixel:
+ {
+ MagickRealType
+ dx,
+ dy;
+
+ PointInfo
+ delta;
+
+ ssize_t
+ j,
+ n;
+
+ p=GetCacheViewVirtualPixels(image_view,x_offset-1,y_offset-1,4,4,
+ exception);
+ if (p == (const Quantum *) NULL)
+ {
+ status=MagickFalse;
+ break;
+ }
+ if (((traits & BlendPixelTrait) == 0) ||
+ (GetPixelAlphaTraits(image) == UndefinedPixelTrait) ||
+ (image->matte == MagickFalse))
+ for (i=0; i < 16; i++)
+ {
+ alpha[i]=1.0;
+ pixels[i]=(MagickRealType) p[i*GetPixelChannels(image)+channel];
+ }
+ else
+ for (i=0; i < 16; i++)
+ {
+ alpha[i]=QuantumScale*GetPixelAlpha(image,p+i*
+ GetPixelChannels(image));
+ pixels[i]=alpha[i]*p[i*GetPixelChannels(image)+channel];
+ }
+ delta.x=x-x_offset;
+ delta.y=y-y_offset;
+ n=0;
+ for (i=(-1); i < 3L; i++)
+ {
+ dy=CubicWeightingFunction((MagickRealType) i-delta.y);
+ for (j=(-1); j < 3L; j++)
+ {
+ dx=CubicWeightingFunction(delta.x-(MagickRealType) j);
+ gamma=1.0/(fabs((double) alpha[n]) <= MagickEpsilon ? 1.0 : alpha[n]);
+ *pixel+=gamma*dx*dy*pixels[n];
+ n++;
+ }
+ }
+ break;
+ }
+ }
+ return(status);
+}
+\f
+/*
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+% %
+% %
+% %
+% I n t e r p o l a t e P i x e l I n f o %
+% %
+% %
+% %
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%
+% InterpolatePixelInfo() applies a pixel interpolation method between a
+% floating point coordinate and the pixels surrounding that coordinate. No
+% pixel area resampling, or scaling of the result is performed.
%
% The format of the InterpolatePixelInfo method is:
%
}
}
-static inline double MagickMax(const MagickRealType x,const MagickRealType y)
-{
- if (x > y)
- return(x);
- return(y);
-}
-
-static inline MagickRealType CubicWeightingFunction(const MagickRealType x)
-{
- MagickRealType
- alpha,
- gamma;
-
- alpha=MagickMax(x+2.0,0.0);
- gamma=1.0*alpha*alpha*alpha;
- alpha=MagickMax(x+1.0,0.0);
- gamma-=4.0*alpha*alpha*alpha;
- alpha=MagickMax(x+0.0,0.0);
- gamma+=6.0*alpha*alpha*alpha;
- alpha=MagickMax(x-1.0,0.0);
- gamma-=4.0*alpha*alpha*alpha;
- return(gamma/6.0);
-}
-
-static inline double MeshInterpolate(const PointInfo *delta,const double p,
- const double x,const double y)
-{
- return(delta->x*x+delta->y*y+(1.0-delta->x-delta->y)*p);
-}
-
-static inline ssize_t NearestNeighbor(const MagickRealType x)
-{
- if (x >= 0.0)
- return((ssize_t) (x+0.5));
- return((ssize_t) (x-0.5));
-}
-
MagickExport MagickBooleanType InterpolatePixelInfo(const Image *image,
const CacheView *image_view,const InterpolatePixelMethod method,
const double x,const double y,PixelInfo *pixel,ExceptionInfo *exception)
pixel->black=gamma*(epsilon.y*(epsilon.x*pixels[0].black+delta.x*
pixels[1].black)+delta.y*(epsilon.x*pixels[2].black+delta.x*
pixels[3].black));
+ gamma=((epsilon.y*(epsilon.x+delta.x)+delta.y*(epsilon.x+delta.x)));
+ gamma=1.0/(fabs((double) gamma) <= MagickEpsilon ? 1.0 : gamma);
pixel->alpha=(epsilon.y*(epsilon.x*pixels[0].alpha+delta.x*
pixels[1].alpha)+delta.y*(epsilon.x*pixels[2].alpha+delta.x*
pixels[3].alpha));
delta,
luminance;
- p=GetCacheViewVirtualPixels(image_view,x_offset,y_offset,2,2,
- exception);
+ p=GetCacheViewVirtualPixels(image_view,x_offset,y_offset,2,2,exception);
if (p == (const Quantum *) NULL)
{
status=MagickFalse;
break;
}
+ delta.x=x-x_offset;
+ delta.y=y-y_offset;
+ luminance.x=GetPixelLuminance(image,p)-(double)
+ GetPixelLuminance(image,p+3*GetPixelChannels(image));
+ luminance.y=GetPixelLuminance(image,p+1*GetPixelChannels(image))-(double)
+ GetPixelLuminance(image,p+2*GetPixelChannels(image));
AlphaBlendPixelInfo(image,p,pixels+0,alpha+0);
AlphaBlendPixelInfo(image,p+1*GetPixelChannels(image),pixels+1,alpha+1);
AlphaBlendPixelInfo(image,p+2*GetPixelChannels(image),pixels+2,alpha+2);
AlphaBlendPixelInfo(image,p+3*GetPixelChannels(image),pixels+3,alpha+3);
- delta.x=x-x_offset;
- delta.y=y-y_offset;
- luminance.x=GetPixelInfoLuminance(pixels+0)-(double)
- GetPixelInfoLuminance(pixels+3);
- luminance.y=GetPixelInfoLuminance(pixels+1)-(double)
- GetPixelInfoLuminance(pixels+2);
if (fabs(luminance.x) < fabs(luminance.y))
{
/*
if (delta.x <= delta.y)
{
/*
- Bottom-left triangle (pixel:2, diagonal: 0-3).
+ Bottom-left triangle (pixel: 2, diagonal: 0-3).
*/
delta.y=1.0-delta.y;
gamma=MeshInterpolate(&delta,alpha[2],alpha[3],alpha[0]);
if (image->colorspace == CMYKColorspace)
pixel->black=gamma*MeshInterpolate(&delta,pixels[2].black,
pixels[3].black,pixels[0].black);
+ gamma=MeshInterpolate(&delta,1.0,1.0,1.0);
pixel->alpha=gamma*MeshInterpolate(&delta,pixels[2].alpha,
pixels[3].alpha,pixels[0].alpha);
}
else
{
/*
- Top-right triangle (pixel:1, diagonal: 0-3).
+ Top-right triangle (pixel:1 , diagonal: 0-3).
*/
delta.x=1.0-delta.x;
gamma=MeshInterpolate(&delta,alpha[1],alpha[0],alpha[3]);
if (image->colorspace == CMYKColorspace)
pixel->black=gamma*MeshInterpolate(&delta,pixels[1].black,
pixels[0].black,pixels[3].black);
+ gamma=MeshInterpolate(&delta,1.0,1.0,1.0);
pixel->alpha=gamma*MeshInterpolate(&delta,pixels[1].alpha,
pixels[0].alpha,pixels[3].alpha);
}
if (delta.x <= (1.0-delta.y))
{
/*
- Top-left triangle (pixel 0, diagonal: 1-2).
+ Top-left triangle (pixel: 0, diagonal: 1-2).
*/
gamma=MeshInterpolate(&delta,alpha[0],alpha[1],alpha[2]);
gamma=1.0/(fabs((double) gamma) <= MagickEpsilon ? 1.0 : gamma);
if (image->colorspace == CMYKColorspace)
pixel->black=gamma*MeshInterpolate(&delta,pixels[0].black,
pixels[1].black,pixels[2].black);
+ gamma=MeshInterpolate(&delta,1.0,1.0,1.0);
pixel->alpha=gamma*MeshInterpolate(&delta,pixels[0].alpha,
pixels[1].alpha,pixels[2].alpha);
}
if (image->colorspace == CMYKColorspace)
pixel->black=gamma*MeshInterpolate(&delta,pixels[3].black,
pixels[2].black,pixels[1].black);
+ gamma=MeshInterpolate(&delta,1.0,1.0,1.0);
pixel->alpha=gamma*MeshInterpolate(&delta,pixels[3].alpha,
pixels[2].alpha,pixels[1].alpha);
}
MagickExport void SetPixelChannelMap(Image *image,
const ChannelType channel_mask)
{
+#define GetChannelBit(alpha,i) (((size_t) (alpha) >> (size_t) (i)) & 0x01)
+
register ssize_t
i;
- for (i=0; i < MaxPixelChannels; i++)
+ for (i=0; i < (ssize_t) GetPixelChannels(image); i++)
+ SetPixelChannelMapTraits(image,(PixelChannel) i,
+ GetChannelBit(channel_mask,i) ? UpdatePixelTrait : CopyPixelTrait);
+ for ( ; i < MaxPixelChannels; i++)
SetPixelChannelMapTraits(image,(PixelChannel) i,UndefinedPixelTrait);
- image->sync=(channel_mask & SyncChannels) != 0 ? MagickTrue : MagickFalse;
- if ((channel_mask & RedChannel) != 0)
- SetPixelRedTraits(image,UpdatePixelTrait);
- if ((channel_mask & GreenChannel) != 0)
- SetPixelGreenTraits(image,UpdatePixelTrait);
- if ((channel_mask & BlueChannel) != 0)
- SetPixelBlueTraits(image,UpdatePixelTrait);
- if ((channel_mask & BlackChannel) != 0)
- SetPixelBlackTraits(image,UpdatePixelTrait);
- if ((channel_mask & AlphaChannel) != 0)
- SetPixelAlphaTraits(image,UpdatePixelTrait);
}
\f
/*
*/
MagickExport void StandardPixelChannelMap(Image *image)
{
+ register ssize_t
+ i;
+
+ for (i=0; i < (ssize_t) GetPixelChannels(image); i++)
+ SetPixelChannelMapTraits(image,(PixelChannel) i,UndefinedPixelTrait);
image->number_channels=4;
SetPixelChannelMapComponent(image,RedPixelChannel,RedPixelChannel);
SetPixelChannelMapTraits(image,RedPixelChannel,(PixelTrait)
(UpdatePixelTrait | BlendPixelTrait));
SetPixelChannelMapComponent(image,AlphaPixelChannel,AlphaPixelChannel);
SetPixelChannelMapTraits(image,AlphaPixelChannel,UpdatePixelTrait);
+ if (0 && image->colorspace == GRAYColorspace)
+ {
+ image->number_channels=2;
+ SetPixelChannelMapComponent(image,GreenPixelChannel,RedPixelChannel);
+ SetPixelChannelMapComponent(image,BluePixelChannel,RedPixelChannel);
+ }
if (image->colorspace == CMYKColorspace)
{
image->number_channels++;
SetPixelChannelMapComponent(image,IndexPixelChannel,IndexPixelChannel);
SetPixelChannelMapTraits(image,IndexPixelChannel,CopyPixelTrait);
}
+ image->number_channels+=image->number_meta_channels;
}