% o image: the image.
%
% o alpha_type: The alpha channel type: ActivateAlphaChannel,
-% CopyAlphaChannel, DeactivateAlphaChannel, ExtractAlphaChannel,
-% OpaqueAlphaChannel, SetAlphaChannel, ShapeAlphaChannel, and
-% TransparentAlphaChannel.
+% AssociateAlphaChannel, CopyAlphaChannel, DeactivateAlphaChannel,
+% DisassociateAlphaChannel, ExtractAlphaChannel, OpaqueAlphaChannel,
+% SetAlphaChannel, ShapeAlphaChannel, and TransparentAlphaChannel.
%
% o exception: return any errors or warnings in this structure.
%
MagickExport MagickBooleanType SetImageAlphaChannel(Image *image,
const AlphaChannelOption alpha_type,ExceptionInfo *exception)
{
+ CacheView
+ *image_view;
+
MagickBooleanType
status;
+ ssize_t
+ y;
+
assert(image != (Image *) NULL);
if (image->debug != MagickFalse)
(void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
image->alpha_trait=BlendPixelTrait;
break;
}
- case BackgroundAlphaChannel:
+ case AssociateAlphaChannel:
{
- CacheView
- *image_view;
+ /*
+ Associate alpha.
+ */
+ status=SetImageStorageClass(image,DirectClass,exception);
+ if (status == MagickFalse)
+ break;
+ image_view=AcquireAuthenticCacheView(image,exception);
+#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 Quantum
+ *restrict q;
- ssize_t
- y;
+ register ssize_t
+ x;
+ 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++)
+ {
+ double
+ Sa;
+
+ register ssize_t
+ i;
+
+ if (GetPixelReadMask(image,q) == 0)
+ {
+ q+=GetPixelChannels(image);
+ continue;
+ }
+ Sa=QuantumScale*GetPixelAlpha(image,q);
+ for (i=0; i < (ssize_t) GetPixelChannels(image); i++)
+ {
+ PixelChannel channel=GetPixelChannelChannel(image,i);
+ PixelTrait traits=GetPixelChannelTraits(image,channel);
+ if ((traits & UpdatePixelTrait) == 0)
+ continue;
+ q[i]=ClampToQuantum(Sa*q[i]);
+ }
+ q+=GetPixelChannels(image);
+ }
+ if (SyncCacheViewAuthenticPixels(image_view,exception) == MagickFalse)
+ status=MagickFalse;
+ }
+ image_view=DestroyCacheView(image_view);
+ image->alpha_trait=CopyPixelTrait;
+ return(status);
+ }
+ case BackgroundAlphaChannel:
+ {
/*
Set transparent pixels to background color.
*/
if (image->alpha_trait != BlendPixelTrait)
break;
- if (SetImageStorageClass(image,DirectClass,exception) == MagickFalse)
+ status=SetImageStorageClass(image,DirectClass,exception);
+ if (status == MagickFalse)
break;
image_view=AcquireAuthenticCacheView(image,exception);
#if defined(MAGICKCORE_OPENMP_SUPPORT)
image->alpha_trait=CopyPixelTrait;
break;
}
+ case DisassociateAlphaChannel:
+ {
+ /*
+ Disassociate alpha.
+ */
+ status=SetImageStorageClass(image,DirectClass,exception);
+ if (status == MagickFalse)
+ break;
+ image->alpha_trait=BlendPixelTrait;
+ image_view=AcquireAuthenticCacheView(image,exception);
+#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 Quantum
+ *restrict q;
+
+ register ssize_t
+ x;
+
+ 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++)
+ {
+ double
+ gamma,
+ Sa;
+
+ register ssize_t
+ i;
+
+ if (GetPixelReadMask(image,q) == 0)
+ {
+ q+=GetPixelChannels(image);
+ continue;
+ }
+ Sa=QuantumScale*GetPixelAlpha(image,q);
+ gamma=PerceptibleReciprocal(Sa);
+ for (i=0; i < (ssize_t) GetPixelChannels(image); i++)
+ {
+ PixelChannel channel=GetPixelChannelChannel(image,i);
+ PixelTrait traits=GetPixelChannelTraits(image,channel);
+ if ((traits & UpdatePixelTrait) == 0)
+ continue;
+ q[i]=ClampToQuantum(gamma*q[i]);
+ }
+ q+=GetPixelChannels(image);
+ }
+ if (SyncCacheViewAuthenticPixels(image_view,exception) == MagickFalse)
+ status=MagickFalse;
+ }
+ image_view=DestroyCacheView(image_view);
+ return(status);
+ }
case ExtractAlphaChannel:
{
status=CompositeImage(image,image,AlphaCompositeOp,MagickTrue,0,0,
}
case RemoveAlphaChannel:
{
- CacheView
- *image_view;
-
- ssize_t
- y;
-
/*
Remove transparency.
*/
if (image->alpha_trait != BlendPixelTrait)
break;
- if (SetImageStorageClass(image,DirectClass,exception) == MagickFalse)
+ status=SetImageStorageClass(image,DirectClass,exception);
+ if (status == MagickFalse)
break;
image_view=AcquireAuthenticCacheView(image,exception);
#if defined(MAGICKCORE_OPENMP_SUPPORT)
ConvertXYZToLuv(X,Y,Z,L,u,v);
}
+static void ConvertRGBToxyY(const double red,const double green,
+ const double blue,double *low_x,double *low_y,double *cap_Y)
+{
+ double
+ X,
+ Y,
+ Z;
+
+ ConvertRGBToXYZ(red,green,blue,&X,&Y,&Z);
+ *low_x=X/(X+Y+Z);
+ *low_y=Y/(X+Y+Z);
+ *cap_Y=Y;
+}
+
static void ConvertRGBToYDbDr(const double red,const double green,
const double blue,double *Y,double *Db,double *Dr)
{
case LCHuvColorspace:
case LMSColorspace:
case LuvColorspace:
+ case xyYColorspace:
case XYZColorspace:
case YCbCrColorspace:
case YDbDrColorspace:
ConvertRGBToLuv(red,green,blue,&X,&Y,&Z);
break;
}
+ case xyYColorspace:
+ {
+ ConvertRGBToxyY(red,green,blue,&X,&Y,&Z);
+ break;
+ }
case XYZColorspace:
{
ConvertRGBToXYZ(red,green,blue,&X,&Y,&Z);
}
else
if ((IsRGBColorspace(colorspace) != MagickFalse) ||
- (colorspace == XYZColorspace))
+ (colorspace == XYZColorspace) || (colorspace == xyYColorspace))
image->gamma=1.000;
else
{
ConvertXYZToRGB(X,Y,Z,red,green,blue);
}
+static inline void ConvertxyYToRGB(const double low_x,const double low_y,
+ const double cap_Y,double *red,double *green,double *blue)
+{
+ double
+ X,
+ Y,
+ Z;
+
+ X=cap_Y/low_y*low_x;
+ Y=cap_Y;
+ Z=cap_Y/low_y*(1.0-low_x-low_y);
+ ConvertXYZToRGB(X,Y,Z,red,green,blue);
+}
+
static void ConvertYPbPrToRGB(const double Y,const double Pb,const double Pr,
double *red,double *green,double *blue)
{
case LCHuvColorspace:
case LMSColorspace:
case LuvColorspace:
+ case xyYColorspace:
case XYZColorspace:
case YCbCrColorspace:
case YDbDrColorspace:
ConvertLuvToRGB(X,Y,Z,&red,&green,&blue);
break;
}
+ case xyYColorspace:
+ {
+ ConvertxyYToRGB(X,Y,Z,&red,&green,&blue);
+ break;
+ }
case XYZColorspace:
{
ConvertXYZToRGB(X,Y,Z,&red,&green,&blue);
{
{ "Undefined", UndefinedAlphaChannel, UndefinedOptionFlag, MagickTrue },
{ "Activate", ActivateAlphaChannel, UndefinedOptionFlag, MagickFalse },
+ { "Associate", AssociateAlphaChannel, UndefinedOptionFlag, MagickFalse },
{ "Background", BackgroundAlphaChannel, UndefinedOptionFlag, MagickFalse },
{ "Copy", CopyAlphaChannel, UndefinedOptionFlag, MagickFalse },
{ "Deactivate", DeactivateAlphaChannel, UndefinedOptionFlag, MagickFalse },
+ { "Disassociate", DisassociateAlphaChannel, UndefinedOptionFlag, MagickFalse },
{ "Extract", ExtractAlphaChannel, UndefinedOptionFlag, MagickFalse },
{ "Off", DeactivateAlphaChannel, UndefinedOptionFlag, MagickFalse },
{ "On", ActivateAlphaChannel, UndefinedOptionFlag, MagickFalse },
{ "scRGB", scRGBColorspace, UndefinedOptionFlag, MagickFalse },
{ "sRGB", sRGBColorspace, UndefinedOptionFlag, MagickFalse },
{ "Transparent", TransparentColorspace, UndefinedOptionFlag, MagickFalse },
+ { "xyY", xyYColorspace, UndefinedOptionFlag, MagickFalse },
{ "XYZ", XYZColorspace, UndefinedOptionFlag, MagickFalse },
{ "YCbCr", YCbCrColorspace, UndefinedOptionFlag, MagickFalse },
{ "YDbDr", YDbDrColorspace, UndefinedOptionFlag, MagickFalse },