% June 2007 %
% %
% %
-% Copyright 1999-2011 ImageMagick Studio LLC, a non-profit organization %
+% Copyright 1999-2012 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. You may %
#include "MagickCore/image.h"
#include "MagickCore/list.h"
#include "MagickCore/matrix.h"
+#include "MagickCore/matrix-private.h"
#include "MagickCore/memory_.h"
#include "MagickCore/monitor-private.h"
#include "MagickCore/option.h"
#include "MagickCore/pixel.h"
#include "MagickCore/pixel-accessor.h"
+#include "MagickCore/pixel-private.h"
#include "MagickCore/resample.h"
#include "MagickCore/resample-private.h"
#include "MagickCore/registry.h"
+#include "MagickCore/resource_.h"
#include "MagickCore/semaphore.h"
+#include "MagickCore/shear.h"
#include "MagickCore/string_.h"
#include "MagickCore/string-private.h"
#include "MagickCore/thread-private.h"
/* From "Digital Image Warping" by George Wolberg, page 50 */
double determinant;
- determinant=1.0/(coeff[0]*coeff[4]-coeff[1]*coeff[3]);
+ determinant=MagickEpsilonReciprocal(coeff[0]*coeff[4]-coeff[1]*coeff[3]);
inverse[0]=determinant*coeff[4];
inverse[1]=determinant*(-coeff[1]);
inverse[2]=determinant*(coeff[1]*coeff[5]-coeff[2]*coeff[4]);
/* From "Digital Image Warping" by George Wolberg, page 53 */
double determinant;
- determinant=1.0/(coeff[0]*coeff[4]-coeff[3]*coeff[1]);
+ determinant=MagickEpsilonReciprocal(coeff[0]*coeff[4]-coeff[3]*coeff[1]);
inverse[0]=determinant*(coeff[4]-coeff[7]*coeff[5]);
inverse[1]=determinant*(coeff[7]*coeff[2]-coeff[1]);
inverse[2]=determinant*(coeff[1]*coeff[5]-coeff[4]*coeff[2]);
% %
% %
% %
+% A f f i n e T r a n s f o r m I m a g e %
+% %
+% %
+% %
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%
+% AffineTransformImage() transforms an image as dictated by the affine matrix.
+% It allocates the memory necessary for the new Image structure and returns
+% a pointer to the new image.
+%
+% The format of the AffineTransformImage method is:
+%
+% Image *AffineTransformImage(const Image *image,
+% AffineMatrix *affine_matrix,ExceptionInfo *exception)
+%
+% A description of each parameter follows:
+%
+% o image: the image.
+%
+% o affine_matrix: the affine matrix.
+%
+% o exception: return any errors or warnings in this structure.
+%
+*/
+MagickExport Image *AffineTransformImage(const Image *image,
+ const AffineMatrix *affine_matrix,ExceptionInfo *exception)
+{
+ double
+ distort[6];
+
+ Image
+ *deskew_image;
+
+ /*
+ Affine transform image.
+ */
+ assert(image->signature == MagickSignature);
+ if (image->debug != MagickFalse)
+ (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
+ assert(affine_matrix != (AffineMatrix *) NULL);
+ assert(exception != (ExceptionInfo *) NULL);
+ assert(exception->signature == MagickSignature);
+ distort[0]=affine_matrix->sx;
+ distort[1]=affine_matrix->rx;
+ distort[2]=affine_matrix->ry;
+ distort[3]=affine_matrix->sy;
+ distort[4]=affine_matrix->tx;
+ distort[5]=affine_matrix->ty;
+ deskew_image=DistortImage(image,AffineProjectionDistortion,6,distort,
+ MagickTrue,exception);
+ return(deskew_image);
+}
+\f
+/*
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+% %
+% %
+% %
+ G e n e r a t e C o e f f i c i e n t s %
% %
% %
{
#define DistortResizeImageTag "Distort/Image"
+ double
+ distort_args[12];
+
Image
*resize_image,
*tmp_image;
RectangleInfo
crop_area;
- double
- distort_args[12];
-
VirtualPixelMethod
vp_save;
return((Image *) NULL);
/* Do not short-circuit this resize if final image size is unchanged */
- (void) SetImageVirtualPixelMethod(image,TransparentVirtualPixelMethod);
-
(void) ResetMagickMemory(distort_args,0,12*sizeof(double));
distort_args[4]=(double) image->columns;
distort_args[6]=(double) columns;
tmp_image=CloneImage(image,0,0,MagickTrue,exception);
if ( tmp_image == (Image *) NULL )
return((Image *) NULL);
- (void) SetImageVirtualPixelMethod(tmp_image,TransparentVirtualPixelMethod);
+ (void) SetImageVirtualPixelMethod(tmp_image,TransparentVirtualPixelMethod,
+ exception);
if (image->matte == MagickFalse)
{
/*
Image has not transparency channel, so we free to use it
*/
- (void) SetImageAlphaChannel(tmp_image,SetAlphaChannel);
+ (void) SetImageAlphaChannel(tmp_image,SetAlphaChannel,exception);
resize_image=DistortImage(tmp_image,AffineDistortion,12,distort_args,
- MagickTrue,exception),
+ MagickTrue,exception),
tmp_image=DestroyImage(tmp_image);
if ( resize_image == (Image *) NULL )
return((Image *) NULL);
- (void) SetImageAlphaChannel(resize_image,DeactivateAlphaChannel);
- InheritException(exception,&image->exception);
+ (void) SetImageAlphaChannel(resize_image,DeactivateAlphaChannel,exception);
}
else
{
Image has transparency so handle colors and alpha separatly.
Basically we need to separate Virtual-Pixel alpha in the resized
image, so only the actual original images alpha channel is used.
+
+ distort alpha channel separately
*/
Image
*resize_alpha;
- /* distort alpha channel separately */
- (void) SeparateImageChannel(tmp_image,TrueAlphaChannel);
- (void) SetImageAlphaChannel(tmp_image,OpaqueAlphaChannel);
+ (void) SetImageAlphaChannel(tmp_image,ExtractAlphaChannel,exception);
+ (void) SetImageAlphaChannel(tmp_image,OpaqueAlphaChannel,exception);
resize_alpha=DistortImage(tmp_image,AffineDistortion,12,distort_args,
- MagickTrue,exception),
+ MagickTrue,exception),
tmp_image=DestroyImage(tmp_image);
- if ( resize_alpha == (Image *) NULL )
+ if (resize_alpha == (Image *) NULL)
return((Image *) NULL);
/* distort the actual image containing alpha + VP alpha */
if ( tmp_image == (Image *) NULL )
return((Image *) NULL);
(void) SetImageVirtualPixelMethod(tmp_image,
- TransparentVirtualPixelMethod);
+ TransparentVirtualPixelMethod,exception);
resize_image=DistortImage(tmp_image,AffineDistortion,12,distort_args,
- MagickTrue,exception),
+ MagickTrue,exception),
tmp_image=DestroyImage(tmp_image);
if ( resize_image == (Image *) NULL)
{
resize_alpha=DestroyImage(resize_alpha);
return((Image *) NULL);
}
-
/* replace resize images alpha with the separally distorted alpha */
- (void) SetImageAlphaChannel(resize_image,DeactivateAlphaChannel);
- (void) SetImageAlphaChannel(resize_alpha,DeactivateAlphaChannel);
- (void) CompositeImage(resize_image,CopyOpacityCompositeOp,resize_alpha,
- 0,0);
- InheritException(exception,&resize_image->exception);
+ (void) SetImageAlphaChannel(resize_image,DeactivateAlphaChannel,
+ exception);
+ (void) SetImageAlphaChannel(resize_alpha,DeactivateAlphaChannel,
+ exception);
+ (void) CompositeImage(resize_image,resize_alpha,CopyAlphaCompositeOp,
+ MagickTrue,0,0,exception);
resize_alpha=DestroyImage(resize_alpha);
}
- (void) SetImageVirtualPixelMethod(resize_image,vp_save);
+ (void) SetImageVirtualPixelMethod(resize_image,vp_save,exception);
/*
Clean up the results of the Distortion
% instead
%
*/
-
MagickExport Image *DistortImage(const Image *image,DistortImageMethod method,
const size_t number_arguments,const double *arguments,
MagickBooleanType bestfit,ExceptionInfo *exception)
s.x = (double) image->page.x;
s.y = (double) image->page.y;
scale=inverse[6]*s.x+inverse[7]*s.y+1.0;
- scale=1.0/( (fabs(scale) <= MagickEpsilon) ? 1.0 : scale );
+ scale=MagickEpsilonReciprocal(scale);
d.x = scale*(inverse[0]*s.x+inverse[1]*s.y+inverse[2]);
d.y = scale*(inverse[3]*s.x+inverse[4]*s.y+inverse[5]);
InitalBounds(d);
s.x = (double) image->page.x+image->columns;
s.y = (double) image->page.y;
scale=inverse[6]*s.x+inverse[7]*s.y+1.0;
- scale=1.0/( (fabs(scale) <= MagickEpsilon) ? 1.0 : scale );
+ scale=MagickEpsilonReciprocal(scale);
d.x = scale*(inverse[0]*s.x+inverse[1]*s.y+inverse[2]);
d.y = scale*(inverse[3]*s.x+inverse[4]*s.y+inverse[5]);
ExpandBounds(d);
s.x = (double) image->page.x;
s.y = (double) image->page.y+image->rows;
scale=inverse[6]*s.x+inverse[7]*s.y+1.0;
- scale=1.0/( (fabs(scale) <= MagickEpsilon) ? 1.0 : scale );
+ scale=MagickEpsilonReciprocal(scale);
d.x = scale*(inverse[0]*s.x+inverse[1]*s.y+inverse[2]);
d.y = scale*(inverse[3]*s.x+inverse[4]*s.y+inverse[5]);
ExpandBounds(d);
s.x = (double) image->page.x+image->columns;
s.y = (double) image->page.y+image->rows;
scale=inverse[6]*s.x+inverse[7]*s.y+1.0;
- scale=1.0/( (fabs(scale) <= MagickEpsilon) ? 1.0 : scale );
+ scale=MagickEpsilonReciprocal(scale);
d.x = scale*(inverse[0]*s.x+inverse[1]*s.y+inverse[2]);
d.y = scale*(inverse[3]*s.x+inverse[4]*s.y+inverse[5]);
ExpandBounds(d);
{ const char *artifact=GetImageArtifact(image,"distort:viewport");
viewport_given = MagickFalse;
if ( artifact != (const char *) NULL ) {
- (void) ParseAbsoluteGeometry(artifact,&geometry);
- viewport_given = MagickTrue;
+ MagickStatusType flags=ParseAbsoluteGeometry(artifact,&geometry);
+ if (flags==NoValue)
+ (void) ThrowMagickException(exception,GetMagickModule(),
+ OptionWarning,"InvalidSetting","'%s' '%s'",
+ "distort:viewport",artifact);
+ else
+ viewport_given = MagickTrue;
}
}
/* Verbose output */
- if ( GetImageArtifact(image,"verbose") != (const char *) NULL ) {
+ if ( IfStringTrue(GetImageArtifact(image,"verbose")) ) {
register ssize_t
i;
char image_gen[MaxTextExtent];
artifact=GetImageArtifact(image,"distort:scale");
output_scaling = 1.0;
if (artifact != (const char *) NULL) {
- output_scaling = fabs(InterpretLocaleValue(artifact,(char **) NULL));
- geometry.width *= output_scaling;
- geometry.height *= output_scaling;
- geometry.x *= output_scaling;
- geometry.y *= output_scaling;
+ output_scaling = fabs(StringToDouble(artifact,(char **) NULL));
+ geometry.width=(size_t) (output_scaling*geometry.width+0.5);
+ geometry.height=(size_t) (output_scaling*geometry.height+0.5);
+ geometry.x=(ssize_t) (output_scaling*geometry.x+0.5);
+ geometry.y=(ssize_t) (output_scaling*geometry.y+0.5);
if ( output_scaling < 0.1 ) {
coeff = (double *) RelinquishMagickMemory(coeff);
(void) ThrowMagickException(exception,GetMagickModule(),OptionError,
if (distort_image == (Image *) NULL)
return((Image *) NULL);
/* if image is ColorMapped - change it to DirectClass */
- if (SetImageStorageClass(distort_image,DirectClass) == MagickFalse)
+ if (SetImageStorageClass(distort_image,DirectClass,exception) == MagickFalse)
{
- InheritException(exception,&distort_image->exception);
distort_image=DestroyImage(distort_image);
return((Image *) NULL);
}
+ if ((IsPixelInfoGray(&distort_image->background_color) == MagickFalse) &&
+ (IsGrayColorspace(distort_image->colorspace) != MagickFalse))
+ (void) TransformImageColorspace(distort_image,RGBColorspace,exception);
+ if (distort_image->background_color.matte != MagickFalse)
+ distort_image->matte=MagickTrue;
distort_image->page.x=geometry.x;
distort_image->page.y=geometry.y;
- if (distort_image->background_color.alpha != OpaqueAlpha)
- distort_image->matte=MagickTrue;
{ /* ----- MAIN CODE -----
Sample the source image to each pixel in the distort image.
GetPixelInfo(distort_image,&zero);
resample_filter=AcquireResampleFilterThreadSet(image,
UndefinedVirtualPixelMethod,MagickFalse,exception);
- distort_view=AcquireCacheView(distort_image);
+ distort_view=AcquireAuthenticCacheView(distort_image,exception);
#if defined(MAGICKCORE_OPENMP_SUPPORT)
- #pragma omp parallel for schedule(dynamic,4) shared(progress,status)
+ #pragma omp parallel for schedule(static,4) shared(progress,status) \
+ dynamic_number_threads(image,image->columns,image->rows,1)
#endif
for (j=0; j < (ssize_t) distort_image->rows; j++)
{
q=QueueCacheViewAuthenticPixels(distort_view,0,j,distort_image->columns,1,
exception);
- if (q == (const Quantum *) NULL)
+ if (q == (Quantum *) NULL)
{
status=MagickFalse;
continue;
*/
validity = 1.0;
- GetPixelInfo(distort_image,&invalid);
- SetPixelInfoPacket(distort_image,&distort_image->matte_color,&invalid);
+ invalid=distort_image->matte_color;
if (distort_image->colorspace == CMYKColorspace)
ConvertRGBToCMYK(&invalid); /* what about other color spaces? */
-
for (i=0; i < (ssize_t) distort_image->columns; i++)
{
/* map pixel coordinate to distortion space coordinate */
if ( validity <= 0.0 ) {
/* result of distortion is an invalid pixel - don't resample */
- SetPixelPixelInfo(distort_image,&invalid,q);
+ SetPixelInfoPixel(distort_image,&invalid,q);
}
else {
/* resample the source image to find its correct color */
- (void) ResamplePixelColor(resample_filter[id],s.x,s.y,&pixel);
+ (void) ResamplePixelColor(resample_filter[id],s.x,s.y,&pixel,
+ exception);
/* if validity between 0.0 and 1.0 mix result with invalid pixel */
if ( validity < 1.0 ) {
/* Do a blend of sample color and invalid pixel */
CompositePixelInfoBlend(&pixel,validity,&invalid,(1.0-validity),
&pixel);
}
- SetPixelPixelInfo(distort_image,&pixel,q);
+ SetPixelInfoPixel(distort_image,&pixel,q);
}
q+=GetPixelChannels(distort_image);
}
proceed;
#if defined(MAGICKCORE_OPENMP_SUPPORT)
- #pragma omp critical (MagickCore_DistortImage)
+ #pragma omp critical (MagickCore_DistortImage)
#endif
proceed=SetImageProgress(image,DistortImageTag,progress++,
image->rows);
% %
% %
% %
+% R o t a t e I m a g e %
+% %
+% %
+% %
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%
+% RotateImage() creates a new image that is a rotated copy of an existing
+% one. Positive angles rotate counter-clockwise (right-hand rule), while
+% negative angles rotate clockwise. Rotated images are usually larger than
+% the originals and have 'empty' triangular corners. X axis. Empty
+% triangles left over from shearing the image are filled with the background
+% color defined by member 'background_color' of the image. RotateImage
+% allocates the memory necessary for the new Image structure and returns a
+% pointer to the new image.
+%
+% The format of the RotateImage method is:
+%
+% Image *RotateImage(const Image *image,const double degrees,
+% ExceptionInfo *exception)
+%
+% A description of each parameter follows.
+%
+% o image: the image.
+%
+% o degrees: Specifies the number of degrees to rotate the image.
+%
+% o exception: return any errors or warnings in this structure.
+%
+*/
+MagickExport Image *RotateImage(const Image *image,const double degrees,
+ ExceptionInfo *exception)
+{
+ Image
+ *distort_image,
+ *rotate_image;
+
+ double
+ angle;
+
+ PointInfo
+ shear;
+
+ size_t
+ rotations;
+
+ /*
+ Adjust rotation angle.
+ */
+ assert(image != (Image *) NULL);
+ assert(image->signature == MagickSignature);
+ if (image->debug != MagickFalse)
+ (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
+ assert(exception != (ExceptionInfo *) NULL);
+ assert(exception->signature == MagickSignature);
+ angle=degrees;
+ while (angle < -45.0)
+ angle+=360.0;
+ for (rotations=0; angle > 45.0; rotations++)
+ angle-=90.0;
+ rotations%=4;
+ shear.x=(-tan((double) DegreesToRadians(angle)/2.0));
+ shear.y=sin((double) DegreesToRadians(angle));
+ if ((fabs(shear.x) < MagickEpsilon) && (fabs(shear.y) < MagickEpsilon))
+ return(IntegralRotateImage(image,rotations,exception));
+ distort_image=CloneImage(image,0,0,MagickTrue,exception);
+ if (distort_image == (Image *) NULL)
+ return((Image *) NULL);
+ (void) SetImageVirtualPixelMethod(distort_image,BackgroundVirtualPixelMethod,
+ exception);
+ rotate_image=DistortImage(distort_image,ScaleRotateTranslateDistortion,1,
+ °rees,MagickTrue,exception);
+ distort_image=DestroyImage(distort_image);
+ return(rotate_image);
+}
+\f
+/*
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+% %
+% %
+% %
% S p a r s e C o l o r I m a g e %
% %
% %
%
% The format of the SparseColorImage() method is:
%
-% Image *SparseColorImage(const Image *image,const ChannelType channel,
+% Image *SparseColorImage(const Image *image,
% const SparseColorMethod method,const size_t number_arguments,
% const double *arguments,ExceptionInfo *exception)
%
%
% o image: the image to be filled in.
%
-% o channel: Specify which color values (in RGBKA sequence) are being set.
-% This also determines the number of color_values in above.
-%
% o method: the method to fill in the gradient between the control points.
%
% The methods used for SparseColor() are often simular to methods
%
*/
MagickExport Image *SparseColorImage(const Image *image,
- const ChannelType channel,const SparseColorMethod method,
- const size_t number_arguments,const double *arguments,
- ExceptionInfo *exception)
+ const SparseColorMethod method,const size_t number_arguments,
+ const double *arguments,ExceptionInfo *exception)
{
#define SparseColorTag "Distort/SparseColor"
/* Determine number of color values needed per control point */
number_colors=0;
- if ( channel & RedChannel ) number_colors++;
- if ( channel & GreenChannel ) number_colors++;
- if ( channel & BlueChannel ) number_colors++;
- if ( channel & AlphaChannel ) number_colors++;
- if ( channel & BlackChannel ) number_colors++;
+ if ((GetPixelRedTraits(image) & UpdatePixelTrait) != 0)
+ number_colors++;
+ if ((GetPixelGreenTraits(image) & UpdatePixelTrait) != 0)
+ number_colors++;
+ if ((GetPixelBlueTraits(image) & UpdatePixelTrait) != 0)
+ number_colors++;
+ if (((GetPixelBlackTraits(image) & UpdatePixelTrait) != 0) &&
+ (image->colorspace == CMYKColorspace))
+ number_colors++;
+ if (((GetPixelAlphaTraits(image) & UpdatePixelTrait) != 0) &&
+ (image->matte != MagickFalse))
+ number_colors++;
/*
Convert input arguments into mapping coefficients, this this case
}
/* Verbose output */
- if ( GetImageArtifact(image,"verbose") != (const char *) NULL ) {
+ if ( IfStringTrue(GetImageArtifact(image,"verbose")) ) {
switch (sparse_method) {
case BarycentricColorInterpolate:
{
register ssize_t x=0;
(void) FormatLocaleFile(stderr, "Barycentric Sparse Color:\n");
- if ( channel & RedChannel )
+ if ((GetPixelRedTraits(image) & UpdatePixelTrait) != 0)
(void) FormatLocaleFile(stderr, " -channel R -fx '%+lf*i %+lf*j %+lf' \\\n",
coeff[x], coeff[x+1], coeff[x+2]),x+=3;
- if ( channel & GreenChannel )
+ if ((GetPixelGreenTraits(image) & UpdatePixelTrait) != 0)
(void) FormatLocaleFile(stderr, " -channel G -fx '%+lf*i %+lf*j %+lf' \\\n",
coeff[x], coeff[x+1], coeff[x+2]),x+=3;
- if ( channel & BlueChannel )
+ if ((GetPixelBlueTraits(image) & UpdatePixelTrait) != 0)
(void) FormatLocaleFile(stderr, " -channel B -fx '%+lf*i %+lf*j %+lf' \\\n",
coeff[x], coeff[x+1], coeff[x+2]),x+=3;
- if ( channel & BlackChannel )
+ if (((GetPixelBlackTraits(image) & UpdatePixelTrait) != 0) &&
+ (image->colorspace == CMYKColorspace))
(void) FormatLocaleFile(stderr, " -channel K -fx '%+lf*i %+lf*j %+lf' \\\n",
coeff[x], coeff[x+1], coeff[x+2]),x+=3;
- if ( channel & AlphaChannel )
+ if (((GetPixelAlphaTraits(image) & UpdatePixelTrait) != 0) &&
+ (image->matte != MagickFalse))
(void) FormatLocaleFile(stderr, " -channel A -fx '%+lf*i %+lf*j %+lf' \\\n",
coeff[x], coeff[x+1], coeff[x+2]),x+=3;
break;
{
register ssize_t x=0;
(void) FormatLocaleFile(stderr, "Bilinear Sparse Color\n");
- if ( channel & RedChannel )
+ if ((GetPixelRedTraits(image) & UpdatePixelTrait) != 0)
(void) FormatLocaleFile(stderr, " -channel R -fx '%+lf*i %+lf*j %+lf*i*j %+lf;\n",
coeff[ x ], coeff[x+1],
coeff[x+2], coeff[x+3]),x+=4;
- if ( channel & GreenChannel )
+ if ((GetPixelGreenTraits(image) & UpdatePixelTrait) != 0)
(void) FormatLocaleFile(stderr, " -channel G -fx '%+lf*i %+lf*j %+lf*i*j %+lf;\n",
coeff[ x ], coeff[x+1],
coeff[x+2], coeff[x+3]),x+=4;
- if ( channel & BlueChannel )
+ if ((GetPixelBlueTraits(image) & UpdatePixelTrait) != 0)
(void) FormatLocaleFile(stderr, " -channel B -fx '%+lf*i %+lf*j %+lf*i*j %+lf;\n",
coeff[ x ], coeff[x+1],
coeff[x+2], coeff[x+3]),x+=4;
- if ( channel & BlackChannel )
+ if (((GetPixelBlackTraits(image) & UpdatePixelTrait) != 0) &&
+ (image->colorspace == CMYKColorspace))
(void) FormatLocaleFile(stderr, " -channel K -fx '%+lf*i %+lf*j %+lf*i*j %+lf;\n",
coeff[ x ], coeff[x+1],
coeff[x+2], coeff[x+3]),x+=4;
- if ( channel & AlphaChannel )
+ if (((GetPixelAlphaTraits(image) & UpdatePixelTrait) != 0) &&
+ (image->matte != MagickFalse))
(void) FormatLocaleFile(stderr, " -channel A -fx '%+lf*i %+lf*j %+lf*i*j %+lf;\n",
coeff[ x ], coeff[x+1],
coeff[x+2], coeff[x+3]),x+=4;
sparse_image=CloneImage(image,0,0,MagickTrue,exception);
if (sparse_image == (Image *) NULL)
return((Image *) NULL);
- if (SetImageStorageClass(sparse_image,DirectClass) == MagickFalse)
+ if (SetImageStorageClass(sparse_image,DirectClass,exception) == MagickFalse)
{ /* if image is ColorMapped - change it to DirectClass */
- InheritException(exception,&image->exception);
sparse_image=DestroyImage(sparse_image);
return((Image *) NULL);
}
status=MagickTrue;
progress=0;
- sparse_view=AcquireCacheView(sparse_image);
+ sparse_view=AcquireAuthenticCacheView(sparse_image,exception);
#if defined(MAGICKCORE_OPENMP_SUPPORT)
- #pragma omp parallel for schedule(dynamic,4) shared(progress,status)
+ #pragma omp parallel for schedule(static,4) shared(progress,status) \
+ dynamic_number_threads(image,image->columns,image->rows,1)
#endif
for (j=0; j < (ssize_t) sparse_image->rows; j++)
{
q=GetCacheViewAuthenticPixels(sparse_view,0,j,sparse_image->columns,
1,exception);
- if (q == (const Quantum *) NULL)
+ if (q == (Quantum *) NULL)
{
status=MagickFalse;
continue;
GetPixelInfo(sparse_image,&pixel);
for (i=0; i < (ssize_t) image->columns; i++)
{
- SetPixelInfo(image,q,&pixel);
+ GetPixelInfoPixel(image,q,&pixel);
switch (sparse_method)
{
case BarycentricColorInterpolate:
{
register ssize_t x=0;
- if ( channel & RedChannel )
+ if ((GetPixelRedTraits(image) & UpdatePixelTrait) != 0)
pixel.red = coeff[x]*i +coeff[x+1]*j
+coeff[x+2], x+=3;
- if ( channel & GreenChannel )
+ if ((GetPixelGreenTraits(image) & UpdatePixelTrait) != 0)
pixel.green = coeff[x]*i +coeff[x+1]*j
+coeff[x+2], x+=3;
- if ( channel & BlueChannel )
+ if ((GetPixelBlueTraits(image) & UpdatePixelTrait) != 0)
pixel.blue = coeff[x]*i +coeff[x+1]*j
+coeff[x+2], x+=3;
- if ( channel & AlphaChannel )
- pixel.alpha = coeff[x]*i +coeff[x+1]*j
- +coeff[x+2], x+=3;
- if ( channel & BlackChannel )
+ if (((GetPixelBlackTraits(image) & UpdatePixelTrait) != 0) &&
+ (image->colorspace == CMYKColorspace))
pixel.black = coeff[x]*i +coeff[x+1]*j
+coeff[x+2], x+=3;
+ if (((GetPixelAlphaTraits(image) & UpdatePixelTrait) != 0) &&
+ (image->matte != MagickFalse))
+ pixel.alpha = coeff[x]*i +coeff[x+1]*j
+ +coeff[x+2], x+=3;
break;
}
case BilinearColorInterpolate:
{
register ssize_t x=0;
- if ( channel & RedChannel )
+ if ((GetPixelRedTraits(image) & UpdatePixelTrait) != 0)
pixel.red = coeff[x]*i + coeff[x+1]*j +
coeff[x+2]*i*j + coeff[x+3], x+=4;
- if ( channel & GreenChannel )
+ if ((GetPixelGreenTraits(image) & UpdatePixelTrait) != 0)
pixel.green = coeff[x]*i + coeff[x+1]*j +
coeff[x+2]*i*j + coeff[x+3], x+=4;
- if ( channel & BlueChannel )
+ if ((GetPixelBlueTraits(image) & UpdatePixelTrait) != 0)
pixel.blue = coeff[x]*i + coeff[x+1]*j +
coeff[x+2]*i*j + coeff[x+3], x+=4;
- if ( channel & AlphaChannel )
- pixel.alpha = coeff[x]*i + coeff[x+1]*j +
- coeff[x+2]*i*j + coeff[x+3], x+=4;
- if ( channel & BlackChannel )
+ if (((GetPixelBlackTraits(image) & UpdatePixelTrait) != 0) &&
+ (image->colorspace == CMYKColorspace))
pixel.black = coeff[x]*i + coeff[x+1]*j +
coeff[x+2]*i*j + coeff[x+3], x+=4;
+ if (((GetPixelAlphaTraits(image) & UpdatePixelTrait) != 0) &&
+ (image->matte != MagickFalse))
+ pixel.alpha = coeff[x]*i + coeff[x+1]*j +
+ coeff[x+2]*i*j + coeff[x+3], x+=4;
break;
}
case InverseColorInterpolate:
double
denominator;
- if ( channel & RedChannel ) pixel.red = 0.0;
- if ( channel & GreenChannel ) pixel.green = 0.0;
- if ( channel & BlueChannel ) pixel.blue = 0.0;
- if ( channel & BlackChannel ) pixel.black = 0.0;
- if ( channel & AlphaChannel ) pixel.alpha = 0.0;
+ if ((GetPixelRedTraits(image) & UpdatePixelTrait) != 0)
+ pixel.red=0.0;
+ if ((GetPixelGreenTraits(image) & UpdatePixelTrait) != 0)
+ pixel.green=0.0;
+ if ((GetPixelBlueTraits(image) & UpdatePixelTrait) != 0)
+ pixel.blue=0.0;
+ if (((GetPixelBlackTraits(image) & UpdatePixelTrait) != 0) &&
+ (image->colorspace == CMYKColorspace))
+ pixel.black=0.0;
+ if (((GetPixelAlphaTraits(image) & UpdatePixelTrait) != 0) &&
+ (image->matte != MagickFalse))
+ pixel.alpha=0.0;
denominator = 0.0;
for(k=0; k<number_arguments; k+=2+number_colors) {
register ssize_t x=(ssize_t) k+2;
if ( method == InverseColorInterpolate )
weight = sqrt(weight); /* inverse, not inverse squared */
weight = ( weight < 1.0 ) ? 1.0 : 1.0/weight;
- if ( channel & RedChannel )
+ if ((GetPixelRedTraits(image) & UpdatePixelTrait) != 0)
pixel.red += arguments[x++]*weight;
- if ( channel & GreenChannel )
+ if ((GetPixelGreenTraits(image) & UpdatePixelTrait) != 0)
pixel.green += arguments[x++]*weight;
- if ( channel & BlueChannel )
+ if ((GetPixelBlueTraits(image) & UpdatePixelTrait) != 0)
pixel.blue += arguments[x++]*weight;
- if ( channel & AlphaChannel )
- pixel.alpha += arguments[x++]*weight;
- if ( channel & BlackChannel )
+ if (((GetPixelBlackTraits(image) & UpdatePixelTrait) != 0) &&
+ (image->colorspace == CMYKColorspace))
pixel.black += arguments[x++]*weight;
+ if (((GetPixelAlphaTraits(image) & UpdatePixelTrait) != 0) &&
+ (image->matte != MagickFalse))
+ pixel.alpha += arguments[x++]*weight;
denominator += weight;
}
- if ( channel & RedChannel ) pixel.red /= denominator;
- if ( channel & GreenChannel ) pixel.green /= denominator;
- if ( channel & BlueChannel ) pixel.blue /= denominator;
- if ( channel & AlphaChannel ) pixel.alpha /= denominator;
- if ( channel & BlackChannel ) pixel.black /= denominator;
+ if ((GetPixelRedTraits(image) & UpdatePixelTrait) != 0)
+ pixel.red/=denominator;
+ if ((GetPixelGreenTraits(image) & UpdatePixelTrait) != 0)
+ pixel.green/=denominator;
+ if ((GetPixelBlueTraits(image) & UpdatePixelTrait) != 0)
+ pixel.blue/=denominator;
+ if (((GetPixelBlackTraits(image) & UpdatePixelTrait) != 0) &&
+ (image->colorspace == CMYKColorspace))
+ pixel.black/=denominator;
+ if (((GetPixelAlphaTraits(image) & UpdatePixelTrait) != 0) &&
+ (image->matte != MagickFalse))
+ pixel.alpha/=denominator;
break;
}
case VoronoiColorInterpolate:
+ ((double)j-arguments[k+1])*((double)j-arguments[k+1]);
if ( distance < minimum ) {
register ssize_t x=(ssize_t) k+2;
- if ( channel & RedChannel ) pixel.red = arguments[x++];
- if ( channel & GreenChannel ) pixel.green = arguments[x++];
- if ( channel & BlueChannel ) pixel.blue = arguments[x++];
- if ( channel & AlphaChannel ) pixel.alpha = arguments[x++];
- if ( channel & BlackChannel ) pixel.black = arguments[x++];
+ if ((GetPixelRedTraits(image) & UpdatePixelTrait) != 0)
+ pixel.red=arguments[x++];
+ if ((GetPixelGreenTraits(image) & UpdatePixelTrait) != 0)
+ pixel.green=arguments[x++];
+ if ((GetPixelBlueTraits(image) & UpdatePixelTrait) != 0)
+ pixel.blue=arguments[x++];
+ if (((GetPixelBlackTraits(image) & UpdatePixelTrait) != 0) &&
+ (image->colorspace == CMYKColorspace))
+ pixel.black=arguments[x++];
+ if (((GetPixelAlphaTraits(image) & UpdatePixelTrait) != 0) &&
+ (image->matte != MagickFalse))
+ pixel.alpha=arguments[x++];
minimum = distance;
}
}
}
}
/* set the color directly back into the source image */
- if ( channel & RedChannel ) pixel.red *= QuantumRange;
- if ( channel & GreenChannel ) pixel.green *= QuantumRange;
- if ( channel & BlueChannel ) pixel.blue *= QuantumRange;
- if ( channel & BlackChannel ) pixel.black *= QuantumRange;
- if ( channel & AlphaChannel ) pixel.alpha *= QuantumRange;
- SetPixelPixelInfo(sparse_image,&pixel,q);
+ if ((GetPixelRedTraits(image) & UpdatePixelTrait) != 0)
+ pixel.red*=QuantumRange;
+ if ((GetPixelGreenTraits(image) & UpdatePixelTrait) != 0)
+ pixel.green*=QuantumRange;
+ if ((GetPixelBlueTraits(image) & UpdatePixelTrait) != 0)
+ pixel.blue*=QuantumRange;
+ if (((GetPixelBlackTraits(image) & UpdatePixelTrait) != 0) &&
+ (image->colorspace == CMYKColorspace))
+ pixel.black*=QuantumRange;
+ if (((GetPixelAlphaTraits(image) & UpdatePixelTrait) != 0) &&
+ (image->matte != MagickFalse))
+ pixel.alpha*=QuantumRange;
+ SetPixelInfoPixel(sparse_image,&pixel,q);
q+=GetPixelChannels(sparse_image);
}
sync=SyncCacheViewAuthenticPixels(sparse_view,exception);
proceed;
#if defined(MAGICKCORE_OPENMP_SUPPORT)
- #pragma omp critical (MagickCore_SparseColorImage)
+ #pragma omp critical (MagickCore_SparseColorImage)
#endif
proceed=SetImageProgress(image,SparseColorTag,progress++,image->rows);
if (proceed == MagickFalse)