diff --git a/MagickCore/image.c b/MagickCore/image.c
index 7f96174..da9bda0 100644
--- a/MagickCore/image.c
+++ b/MagickCore/image.c
@@ -2410,6 +2410,75 @@
% o exception: return any errors or warnings in this structure.
%
*/
+
+static inline void FlattenPixelInfo(const Image *image,const PixelInfo *p,
+ const MagickRealType alpha,const Quantum *q,const MagickRealType beta,
+ Quantum *composite)
+{
+ MagickRealType
+ Da,
+ gamma,
+ Sa;
+
+ register ssize_t
+ i;
+
+ /*
+ Compose pixel p over pixel q with the given alpha.
+ */
+ Sa=QuantumScale*alpha;
+ Da=QuantumScale*beta,
+ gamma=Sa*(-Da)+Sa+Da;
+ gamma=1.0/(gamma <= MagickEpsilon ? 1.0 : gamma);
+ for (i=0; i < (ssize_t) GetPixelChannels(image); i++)
+ {
+ PixelChannel
+ channel;
+
+ PixelTrait
+ traits;
+
+ channel=GetPixelChannelMapChannel(image,i);
+ traits=GetPixelChannelMapTraits(image,channel);
+ if (traits == UndefinedPixelTrait)
+ continue;
+ switch (channel)
+ {
+ case RedPixelChannel:
+ {
+ composite[i]=ClampToQuantum(gamma*MagickOver_((MagickRealType) q[i],
+ beta,(MagickRealType) p->red,alpha));
+ break;
+ }
+ case GreenPixelChannel:
+ {
+ composite[i]=ClampToQuantum(gamma*MagickOver_((MagickRealType) q[i],
+ beta,(MagickRealType) p->green,alpha));
+ break;
+ }
+ case BluePixelChannel:
+ {
+ composite[i]=ClampToQuantum(gamma*MagickOver_((MagickRealType) q[i],
+ beta,(MagickRealType) p->blue,alpha));
+ break;
+ }
+ case BlackPixelChannel:
+ {
+ composite[i]=ClampToQuantum(gamma*MagickOver_((MagickRealType) q[i],
+ beta,(MagickRealType) p->black,alpha));
+ break;
+ }
+ case AlphaPixelChannel:
+ {
+ composite[i]=ClampToQuantum(QuantumRange*(Sa*(-Da)+Sa+Da));
+ break;
+ }
+ default:
+ break;
+ }
+ }
+}
+
MagickExport MagickBooleanType SetImageAlphaChannel(Image *image,
const AlphaChannelType alpha_type,ExceptionInfo *exception)
{
@@ -2433,19 +2502,16 @@
CacheView
*image_view;
- PixelInfo
- background;
-
ssize_t
y;
/*
Set transparent pixels to background color.
*/
- image->matte=MagickTrue;
+ if (image->matte == MagickFalse)
+ break;
if (SetImageStorageClass(image,DirectClass,exception) == MagickFalse)
break;
- background=image->background_color;
image_view=AcquireCacheView(image);
#if defined(MAGICKCORE_OPENMP_SUPPORT)
#pragma omp parallel for schedule(static,4) shared(status)
@@ -2470,7 +2536,7 @@
for (x=0; x < (ssize_t) image->columns; x++)
{
if (GetPixelAlpha(image,q) == TransparentAlpha)
- SetPixelInfoPixel(image,&background,q);
+ SetPixelInfoPixel(image,&image->background_color,q);
q+=GetPixelChannels(image);
}
if (SyncCacheViewAuthenticPixels(image_view,exception) == MagickFalse)
@@ -2479,13 +2545,8 @@
image_view=DestroyCacheView(image_view);
return(status);
}
- case DeactivateAlphaChannel:
- {
- image->matte=MagickFalse;
- break;
- }
- case ShapeAlphaChannel:
case CopyAlphaChannel:
+ case ShapeAlphaChannel:
{
/*
Copy pixel intensity to the alpha channel.
@@ -2496,6 +2557,11 @@
&image->background_color,MagickTrue,exception);
break;
}
+ case DeactivateAlphaChannel:
+ {
+ image->matte=MagickFalse;
+ break;
+ }
case ExtractAlphaChannel:
{
status=CompositeImage(image,AlphaCompositeOp,image,0,0,exception);
@@ -2507,10 +2573,54 @@
status=SetImageAlpha(image,OpaqueAlpha,exception);
break;
}
- case TransparentAlphaChannel:
+ case FlattenAlphaChannel:
{
- status=SetImageAlpha(image,TransparentAlpha,exception);
- break;
+ CacheView
+ *image_view;
+
+ ssize_t
+ y;
+
+ /*
+ Flatten image pixels over the background pixels.
+ */
+ if (image->matte == MagickFalse)
+ break;
+ if (SetImageStorageClass(image,DirectClass,exception) == MagickFalse)
+ break;
+ image_view=AcquireCacheView(image);
+#if defined(MAGICKCORE_OPENMP_SUPPORT)
+ #pragma omp parallel for schedule(static,4) shared(status)
+#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++)
+ {
+ FlattenPixelInfo(image,&image->background_color,
+ image->background_color.alpha,q,(MagickRealType)
+ GetPixelAlpha(image,q),q);
+ q+=GetPixelChannels(image);
+ }
+ if (SyncCacheViewAuthenticPixels(image_view,exception) == MagickFalse)
+ status=MagickFalse;
+ }
+ image_view=DestroyCacheView(image_view);
+ return(status);
}
case SetAlphaChannel:
{
@@ -2518,6 +2628,11 @@
status=SetImageAlpha(image,OpaqueAlpha,exception);
break;
}
+ case TransparentAlphaChannel:
+ {
+ status=SetImageAlpha(image,TransparentAlpha,exception);
+ break;
+ }
case UndefinedAlphaChannel:
break;
}
diff --git a/MagickCore/image.h b/MagickCore/image.h
index b6f0c39..d4403b8 100644
--- a/MagickCore/image.h
+++ b/MagickCore/image.h
@@ -38,7 +38,8 @@
OpaqueAlphaChannel,
SetAlphaChannel,
ShapeAlphaChannel,
- TransparentAlphaChannel
+ TransparentAlphaChannel,
+ FlattenAlphaChannel
} AlphaChannelType;
typedef enum
diff --git a/MagickCore/option.c b/MagickCore/option.c
index 17bdf68..4024c49 100644
--- a/MagickCore/option.c
+++ b/MagickCore/option.c
@@ -98,6 +98,7 @@
{ "Copy", CopyAlphaChannel, UndefinedOptionFlag, MagickFalse },
{ "Deactivate", DeactivateAlphaChannel, UndefinedOptionFlag, MagickFalse },
{ "Extract", ExtractAlphaChannel, UndefinedOptionFlag, MagickFalse },
+ { "Flatten", FlattenAlphaChannel, UndefinedOptionFlag, MagickFalse },
{ "Off", DeactivateAlphaChannel, UndefinedOptionFlag, MagickFalse },
{ "On", ActivateAlphaChannel, UndefinedOptionFlag, MagickFalse },
{ "Opaque", OpaqueAlphaChannel, UndefinedOptionFlag, MagickFalse },