diff --git a/PerlMagick/Magick.xs b/PerlMagick/Magick.xs
index c7ab9c1..ef3d2e9 100644
--- a/PerlMagick/Magick.xs
+++ b/PerlMagick/Magick.xs
@@ -528,6 +528,7 @@
{ "Morphology", { {"kernel", StringReference},
{"channel", MagickChannelOptions}, {"method", MagickMorphologyOptions},
{"iterations", IntegerReference} } },
+ { "ColorMatrix", { {"matrix", StringReference} } },
};
static SplayTreeInfo
@@ -7182,6 +7183,8 @@
BrightnessContrastImage = 264
Morphology = 265
MorphologyImage = 266
+ ColorMatrix = 267
+ ColorMatrixImage = 268
MogrifyRegion = 666
PPCODE:
{
@@ -10482,6 +10485,20 @@
kernel=DestroyKernelInfo(kernel);
break;
}
+ case 134: /* ColorMatrix */
+ {
+ KernelInfo
+ *color_matrix;
+
+ if (attribute_flag[0] == 0)
+ break;
+ color_matrix=AcquireKernelInfo(argument_list[0].string_reference);
+ if (color_matrix == (KernelInfo *) NULL)
+ break;
+ image=ColorMatrixImage(image,color_matrix,exception);
+ kernel=DestroyKernelInfo(kernel);
+ break;
+ }
}
if (next != (Image *) NULL)
(void) CatchImageException(next);
diff --git a/coders/psd.c b/coders/psd.c
index 2b1c196..66f75a8 100644
--- a/coders/psd.c
+++ b/coders/psd.c
@@ -68,6 +68,7 @@
Define declaractions.
*/
#define MaxPSDChannels 56
+#define PSDQuantum(x) (((long) (x)+1) & -2)
/*
Enumerated declaractions.
@@ -1987,15 +1988,35 @@
*/
res_extra = 28; /* 0x03EB */
profile=GetImageProfile(image,"8bim");
- if (profile == (StringInfo *) NULL)
- (void) WriteBlobMSBLong(image,(unsigned int) res_extra);
- else
+ if (profile != (StringInfo *) NULL)
{
(void) WriteBlobMSBLong(image,(unsigned int) (res_extra+
GetStringInfoLength(profile)));
(void) WriteBlob(image,GetStringInfoLength(profile),GetStringInfoDatum(
profile));
}
+ else
+ {
+ profile=GetImageProfile(image,"icc");
+ if (profile == (StringInfo *) NULL)
+ (void) WriteBlobMSBLong(image,(unsigned int) res_extra);
+ else
+ {
+ size_t
+ length;
+
+ length=PSDQuantum(GetStringInfoLength(profile));
+ (void) WriteBlobMSBLong(image,(unsigned int) (res_extra+length+12));
+ (void) WriteBlob(image,4,(const unsigned char *) "8BIM");
+ (void) WriteBlobMSBShort(image,0x040F);
+ (void) WriteBlobMSBShort(image,0);
+ (void) WriteBlobMSBLong(image,GetStringInfoLength(profile));
+ (void) WriteBlob(image,GetStringInfoLength(profile),
+ GetStringInfoDatum(profile));
+ if (length != GetStringInfoLength(profile))
+ (void) WriteBlobByte(image,0);
+ }
+ }
WriteResolutionResourceBlock(image);
compute_layer_info:
diff --git a/magick/deprecate.c b/magick/deprecate.c
index 04d45fb..52df130 100644
--- a/magick/deprecate.c
+++ b/magick/deprecate.c
@@ -62,6 +62,7 @@
#include "magick/enhance.h"
#include "magick/exception.h"
#include "magick/exception-private.h"
+#include "magick/fx.h"
#include "magick/geometry.h"
#include "magick/identify.h"
#include "magick/image.h"
@@ -72,6 +73,7 @@
#include "magick/magick.h"
#include "magick/monitor.h"
#include "magick/monitor-private.h"
+#include "magick/morphology.h"
#include "magick/paint.h"
#include "magick/pixel.h"
#include "magick/pixel-private.h"
@@ -5197,6 +5199,64 @@
% %
% %
% %
+% R e c o l o r I m a g e %
+% %
+% %
+% %
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%
+% RecolorImage() apply color transformation to an image. The method permits
+% saturation changes, hue rotation, luminance to alpha, and various other
+% effects. Although variable-sized transformation matrices can be used,
+% typically one uses a 5x5 matrix for an RGBA image and a 6x6 for CMYKA
+% (or RGBA with offsets). The matrix is similar to those used by Adobe Flash
+% except offsets are in column 6 rather than 5 (in support of CMYKA images)
+% and offsets are normalized (divide Flash offset by 255).
+%
+% The format of the RecolorImage method is:
+%
+% Image *RecolorImage(const Image *image,const unsigned long order,
+% const double *color_matrix,ExceptionInfo *exception)
+%
+% A description of each parameter follows:
+%
+% o image: the image.
+%
+% o order: the number of columns and rows in the recolor matrix.
+%
+% o color_matrix: An array of double representing the recolor matrix.
+%
+% o exception: return any errors or warnings in this structure.
+%
+*/
+MagickExport Image *RecolorImage(const Image *image,const unsigned long order,
+ const double *color_matrix,ExceptionInfo *exception)
+{
+ double
+ *values;
+
+ KernelInfo
+ *kernel_info;
+
+ Image
+ *recolor_image;
+
+ kernel_info=AcquireKernelInfo("1");
+ kernel_info->width=order;
+ kernel_info->height=order;
+ values=kernel_info->values;
+ kernel_info->values=(double *) color_matrix;
+ recolor_image=ColorMatrixImage(image,kernel_info,exception);
+ kernel_info->values=values;
+ kernel_info=DestroyKernelInfo(kernel_info);
+ return(recolor_image);
+}
+
+/*
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+% %
+% %
+% %
% R e s e t I m a g e A t t r i b u t e I t e r a t o r %
% %
% %
diff --git a/magick/deprecate.h b/magick/deprecate.h
index 89c44aa..134a316 100644
--- a/magick/deprecate.h
+++ b/magick/deprecate.h
@@ -128,6 +128,8 @@
*FlattenImages(Image *,ExceptionInfo *) magick_attribute((deprecated)),
*MosaicImages(Image *,ExceptionInfo *) magick_attribute((deprecated)),
*PopImageList(Image **) magick_attribute((deprecated)),
+ *RecolorImage(const Image *,const unsigned long,const double *,
+ ExceptionInfo *) magick_attribute((deprecated)),
*ShiftImageList(Image **) magick_attribute((deprecated)),
*SpliceImageList(Image *,const long,const unsigned long,const Image *,
ExceptionInfo *) magick_attribute((deprecated));
diff --git a/magick/fx.c b/magick/fx.c
index 5f28131..4ac16c7 100644
--- a/magick/fx.c
+++ b/magick/fx.c
@@ -807,6 +807,232 @@
% %
% %
% %
+% C o l o r M a t r i x I m a g e %
+% %
+% %
+% %
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%
+% ColorMatrixImage() applies color transformation to an image. This method
+% permits saturation changes, hue rotation, luminance to alpha, and various
+% other effects. Although variable-sized transformation matrices can be used,
+% typically one uses a 5x5 matrix for an RGBA image and a 6x6 for CMYKA
+% (or RGBA with offsets). The matrix is similar to those used by Adobe Flash
+% except offsets are in column 6 rather than 5 (in support of CMYKA images)
+% and offsets are normalized (divide Flash offset by 255).
+%
+% The format of the ColorMatrixImage method is:
+%
+% Image *ColorMatrixImage(const Image *image,
+% const KernelInfo *color_matrix,ExceptionInfo *exception)
+%
+% A description of each parameter follows:
+%
+% o image: the image.
+%
+% o color_matrix: the color matrix.
+%
+% o exception: return any errors or warnings in this structure.
+%
+*/
+MagickExport Image *ColorMatrixImage(const Image *image,
+ const KernelInfo *color_matrix,ExceptionInfo *exception)
+{
+#define ColorMatrixImageTag "ColorMatrix/Image"
+
+ CacheView
+ *color_view,
+ *image_view;
+
+ double
+ ColorMatrix[6][6] =
+ {
+ { 1.0, 0.0, 0.0, 0.0, 0.0, 0.0 },
+ { 0.0, 1.0, 0.0, 0.0, 0.0, 0.0 },
+ { 0.0, 0.0, 1.0, 0.0, 0.0, 0.0 },
+ { 0.0, 0.0, 0.0, 1.0, 0.0, 0.0 },
+ { 0.0, 0.0, 0.0, 0.0, 1.0, 0.0 },
+ { 0.0, 0.0, 0.0, 0.0, 0.0, 1.0 }
+ };
+
+ Image
+ *color_image;
+
+ long
+ progress,
+ u,
+ v,
+ y;
+
+ MagickBooleanType
+ status;
+
+ register long
+ i;
+
+ /*
+ Create color matrix.
+ */
+ 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);
+ i=0;
+ for (v=0; v < (long) color_matrix->height; v++)
+ for (u=0; u < (long) color_matrix->width; u++)
+ {
+ if ((v < 6) && (u < 6))
+ ColorMatrix[v][u]=color_matrix->values[i];
+ i++;
+ }
+ /*
+ Initialize color image.
+ */
+ color_image=CloneImage(image,0,0,MagickTrue,exception);
+ if (color_image == (Image *) NULL)
+ return((Image *) NULL);
+ if (SetImageStorageClass(color_image,DirectClass) == MagickFalse)
+ {
+ InheritException(exception,&color_image->exception);
+ color_image=DestroyImage(color_image);
+ return((Image *) NULL);
+ }
+ if (image->debug != MagickFalse)
+ {
+ char
+ format[MaxTextExtent],
+ *message;
+
+ (void) LogMagickEvent(TransformEvent,GetMagickModule(),
+ " ColorMatrix image with color matrix:");
+ message=AcquireString("");
+ for (v=0; v < 6; v++)
+ {
+ *message='\0';
+ (void) FormatMagickString(format,MaxTextExtent,"%ld: ",v);
+ (void) ConcatenateString(&message,format);
+ for (u=0; u < 6; u++)
+ {
+ (void) FormatMagickString(format,MaxTextExtent,"%+f ",
+ ColorMatrix[v][u]);
+ (void) ConcatenateString(&message,format);
+ }
+ (void) LogMagickEvent(TransformEvent,GetMagickModule(),"%s",message);
+ }
+ message=DestroyString(message);
+ }
+ /*
+ ColorMatrix image.
+ */
+ status=MagickTrue;
+ progress=0;
+ image_view=AcquireCacheView(image);
+ color_view=AcquireCacheView(color_image);
+#if defined(MAGICKCORE_OPENMP_SUPPORT)
+ #pragma omp parallel for schedule(dynamic,4) shared(progress,status)
+#endif
+ for (y=0; y < (long) image->rows; y++)
+ {
+ MagickRealType
+ pixel;
+
+ register const IndexPacket
+ *restrict indexes;
+
+ register const PixelPacket
+ *restrict p;
+
+ register long
+ x;
+
+ register IndexPacket
+ *restrict color_indexes;
+
+ register PixelPacket
+ *restrict q;
+
+ if (status == MagickFalse)
+ continue;
+ p=GetCacheViewVirtualPixels(image_view,0,y,image->columns,1,exception);
+ q=GetCacheViewAuthenticPixels(color_view,0,y,color_image->columns,1,
+ exception);
+ if ((p == (const PixelPacket *) NULL) || (q == (PixelPacket *) NULL))
+ {
+ status=MagickFalse;
+ continue;
+ }
+ indexes=GetCacheViewVirtualIndexQueue(image_view);
+ color_indexes=GetCacheViewAuthenticIndexQueue(color_view);
+ for (x=0; x < (long) image->columns; x++)
+ {
+ register long
+ v;
+
+ unsigned long
+ height;
+
+ height=color_matrix->height > 6 ? 6UL : color_matrix->height;
+ for (v=0; v < (long) height; v++)
+ {
+ pixel=ColorMatrix[v][0]*p->red+ColorMatrix[v][1]*p->green+
+ ColorMatrix[v][2]*p->blue;
+ if (image->matte != MagickFalse)
+ pixel+=ColorMatrix[v][3]*(QuantumRange-p->opacity);
+ if (image->colorspace == CMYKColorspace)
+ pixel+=ColorMatrix[v][4]*indexes[x];
+ pixel+=QuantumRange*ColorMatrix[v][5];
+ switch (v)
+ {
+ case 0: q->red=ClampToQuantum(pixel); break;
+ case 1: q->green=ClampToQuantum(pixel); break;
+ case 2: q->blue=ClampToQuantum(pixel); break;
+ case 3:
+ {
+ if (image->matte != MagickFalse)
+ q->opacity=ClampToQuantum(QuantumRange-pixel);
+ break;
+ }
+ case 4:
+ {
+ if (image->colorspace == CMYKColorspace)
+ color_indexes[x]=ClampToQuantum(pixel);
+ break;
+ }
+ }
+ }
+ p++;
+ q++;
+ }
+ if (SyncCacheViewAuthenticPixels(color_view,exception) == MagickFalse)
+ status=MagickFalse;
+ if (image->progress_monitor != (MagickProgressMonitor) NULL)
+ {
+ MagickBooleanType
+ proceed;
+
+#if defined(MAGICKCORE_OPENMP_SUPPORT)
+ #pragma omp critical (MagickCore_ColorMatrixImage)
+#endif
+ proceed=SetImageProgress(image,ColorMatrixImageTag,progress++,
+ image->rows);
+ if (proceed == MagickFalse)
+ status=MagickFalse;
+ }
+ }
+ color_view=DestroyCacheView(color_view);
+ image_view=DestroyCacheView(image_view);
+ if (status == MagickFalse)
+ color_image=DestroyImage(color_image);
+ return(color_image);
+}
+
+/*
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+% %
+% %
+% %
+ D e s t r o y F x I n f o %
% %
% %
@@ -3645,229 +3871,6 @@
% %
% %
% %
-% R e c o l o r I m a g e %
-% %
-% %
-% %
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-%
-% RecolorImage() apply color transformation to an image. The method permits
-% saturation changes, hue rotation, luminance to alpha, and various other
-% effects. Although variable-sized transformation matrices can be used,
-% typically one uses a 5x5 matrix for an RGBA image and a 6x6 for CMYKA
-% (or RGBA with offsets). The matrix is similar to those used by Adobe Flash
-% except offsets are in column 6 rather than 5 (in support of CMYKA images)
-% and offsets are normalized (divide Flash offset by 255).
-%
-% The format of the RecolorImage method is:
-%
-% Image *RecolorImage(const Image *image,const unsigned long order,
-% const double *color_matrix,ExceptionInfo *exception)
-%
-% A description of each parameter follows:
-%
-% o image: the image.
-%
-% o order: the number of columns and rows in the recolor matrix.
-%
-% o color_matrix: An array of double representing the recolor matrix.
-%
-% o exception: return any errors or warnings in this structure.
-%
-*/
-MagickExport Image *RecolorImage(const Image *image,const unsigned long order,
- const double *color_matrix,ExceptionInfo *exception)
-{
-#define RecolorImageTag "Recolor/Image"
-
- CacheView
- *image_view,
- *recolor_view;
-
- double
- recolor_matrix[6][6] =
- {
- { 1.0, 0.0, 0.0, 0.0, 0.0, 0.0 },
- { 0.0, 1.0, 0.0, 0.0, 0.0, 0.0 },
- { 0.0, 0.0, 1.0, 0.0, 0.0, 0.0 },
- { 0.0, 0.0, 0.0, 1.0, 0.0, 0.0 },
- { 0.0, 0.0, 0.0, 0.0, 1.0, 0.0 },
- { 0.0, 0.0, 0.0, 0.0, 0.0, 1.0 }
- };
-
- Image
- *recolor_image;
-
- long
- progress,
- u,
- v,
- y;
-
- MagickBooleanType
- status;
-
- register long
- i;
-
- /*
- Create recolor matrix.
- */
- 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);
- i=0;
- for (v=0; v < (long) order; v++)
- for (u=0; u < (long) order; u++)
- {
- if ((v < 6) && (u < 6))
- recolor_matrix[v][u]=color_matrix[i];
- i++;
- }
- /*
- Initialize recolor image.
- */
- recolor_image=CloneImage(image,0,0,MagickTrue,exception);
- if (recolor_image == (Image *) NULL)
- return((Image *) NULL);
- if (SetImageStorageClass(recolor_image,DirectClass) == MagickFalse)
- {
- InheritException(exception,&recolor_image->exception);
- recolor_image=DestroyImage(recolor_image);
- return((Image *) NULL);
- }
- if (image->debug != MagickFalse)
- {
- char
- format[MaxTextExtent],
- *message;
-
- (void) LogMagickEvent(TransformEvent,GetMagickModule(),
- " Recolor image with color matrix:");
- message=AcquireString("");
- for (v=0; v < 6; v++)
- {
- *message='\0';
- (void) FormatMagickString(format,MaxTextExtent,"%ld: ",v);
- (void) ConcatenateString(&message,format);
- for (u=0; u < 6; u++)
- {
- (void) FormatMagickString(format,MaxTextExtent,"%+f ",
- recolor_matrix[v][u]);
- (void) ConcatenateString(&message,format);
- }
- (void) LogMagickEvent(TransformEvent,GetMagickModule(),"%s",message);
- }
- message=DestroyString(message);
- }
- /*
- Recolor image.
- */
- status=MagickTrue;
- progress=0;
- image_view=AcquireCacheView(image);
- recolor_view=AcquireCacheView(recolor_image);
-#if defined(MAGICKCORE_OPENMP_SUPPORT)
- #pragma omp parallel for schedule(dynamic,4) shared(progress,status)
-#endif
- for (y=0; y < (long) image->rows; y++)
- {
- MagickRealType
- pixel;
-
- register const IndexPacket
- *restrict indexes;
-
- register const PixelPacket
- *restrict p;
-
- register long
- x;
-
- register IndexPacket
- *restrict recolor_indexes;
-
- register PixelPacket
- *restrict q;
-
- if (status == MagickFalse)
- continue;
- p=GetCacheViewVirtualPixels(image_view,0,y,image->columns,1,exception);
- q=GetCacheViewAuthenticPixels(recolor_view,0,y,recolor_image->columns,1,
- exception);
- if ((p == (const PixelPacket *) NULL) || (q == (PixelPacket *) NULL))
- {
- status=MagickFalse;
- continue;
- }
- indexes=GetCacheViewVirtualIndexQueue(image_view);
- recolor_indexes=GetCacheViewAuthenticIndexQueue(recolor_view);
- for (x=0; x < (long) image->columns; x++)
- {
- register long
- v;
-
- for (v=0; v < (long) (order > 6 ? 6 : order); v++)
- {
- pixel=recolor_matrix[v][0]*p->red+recolor_matrix[v][1]*p->green+
- recolor_matrix[v][2]*p->blue;
- if (image->matte != MagickFalse)
- pixel+=recolor_matrix[v][3]*(QuantumRange-p->opacity);
- if (image->colorspace == CMYKColorspace)
- pixel+=recolor_matrix[v][4]*indexes[x];
- pixel+=QuantumRange*recolor_matrix[v][5];
- switch (v)
- {
- case 0: q->red=ClampToQuantum(pixel); break;
- case 1: q->green=ClampToQuantum(pixel); break;
- case 2: q->blue=ClampToQuantum(pixel); break;
- case 3:
- {
- if (image->matte != MagickFalse)
- q->opacity=ClampToQuantum(QuantumRange-pixel);
- break;
- }
- case 4:
- {
- if (image->colorspace == CMYKColorspace)
- recolor_indexes[x]=ClampToQuantum(pixel);
- break;
- }
- }
- }
- p++;
- q++;
- }
- if (SyncCacheViewAuthenticPixels(recolor_view,exception) == MagickFalse)
- status=MagickFalse;
- if (image->progress_monitor != (MagickProgressMonitor) NULL)
- {
- MagickBooleanType
- proceed;
-
-#if defined(MAGICKCORE_OPENMP_SUPPORT)
- #pragma omp critical (MagickCore_RecolorImage)
-#endif
- proceed=SetImageProgress(image,RecolorImageTag,progress++,image->rows);
- if (proceed == MagickFalse)
- status=MagickFalse;
- }
- }
- recolor_view=DestroyCacheView(recolor_view);
- image_view=DestroyCacheView(image_view);
- if (status == MagickFalse)
- recolor_image=DestroyImage(recolor_image);
- return(recolor_image);
-}
-
-/*
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-% %
-% %
-% %
% S e p i a T o n e I m a g e %
% %
% %
diff --git a/magick/fx.h b/magick/fx.h
index 1087ba0..68eccbb 100644
--- a/magick/fx.h
+++ b/magick/fx.h
@@ -43,13 +43,12 @@
*BlueShiftImage(const Image *,const double,ExceptionInfo *),
*CharcoalImage(const Image *,const double,const double,ExceptionInfo *),
*ColorizeImage(const Image *,const char *,const PixelPacket,ExceptionInfo *),
+ *ColorMatrixImage(const Image *,const KernelInfo *kernel,ExceptionInfo *),
*FxImage(const Image *,const char *,ExceptionInfo *),
*FxImageChannel(const Image *,const ChannelType,const char *,ExceptionInfo *),
*ImplodeImage(const Image *,const double,ExceptionInfo *),
*MorphImages(const Image *,const unsigned long,ExceptionInfo *),
*PolaroidImage(const Image *,const DrawInfo *,const double,ExceptionInfo *),
- *RecolorImage(const Image *,const unsigned long,const double *,
- ExceptionInfo *),
*SepiaToneImage(const Image *,const double,ExceptionInfo *),
*ShadowImage(const Image *,const double,const double,const long,const long,
ExceptionInfo *),
diff --git a/magick/morphology.c b/magick/morphology.c
index b52f298..02118f7 100644
--- a/magick/morphology.c
+++ b/magick/morphology.c
@@ -931,7 +931,7 @@
% be modified without effecting the original. The cloned kernel should be
% destroyed using DestoryKernelInfo() when no longer needed.
%
-% The format of the DestroyKernelInfo method is:
+% The format of the CloneKernelInfo method is:
%
% KernelInfo *CloneKernelInfo(const KernelInfo *kernel)
%
diff --git a/magick/option.c b/magick/option.c
index 26b4a75..2d8a6ca 100644
--- a/magick/option.c
+++ b/magick/option.c
@@ -238,6 +238,8 @@
{ "-colorize", 1L, MagickFalse },
{ "+colormap", 0L, MagickFalse },
{ "-colormap", 1L, MagickFalse },
+ { "+color-matrix", 0L, MagickFalse },
+ { "-color-matrix", 1L, MagickFalse },
{ "+colors", 0L, MagickFalse },
{ "-colors", 1L, MagickFalse },
{ "+colorspace", 0L, MagickFalse },
diff --git a/utilities/convert.1.in b/utilities/convert.1.in
index 8a72a80..139e481 100644
--- a/utilities/convert.1.in
+++ b/utilities/convert.1.in
@@ -115,6 +115,7 @@
\-clip-mask filename associate a clip mask with the image
\-clip-path id clip along a named path from the 8BIM profile
\-colorize value colorize the image with the fill color
+ \-color-matrix matrix apply color correction to the image
\-contrast enhance or reduce the image contrast
\-contrast-stretch geometry
improve contrast by `stretching' the intensity range
@@ -173,7 +174,6 @@
\-raise value lighten/darken image edges to create a 3-D effect
\-random-threshold low,high
random threshold the image
- \-recolor matrix apply color correction to the image
\-region geometry apply options to a portion of the image
\-render render vector graphics
\-repage geometry size and location of an image canvas
diff --git a/utilities/mogrify.1.in b/utilities/mogrify.1.in
index a7ea455..300c7aa 100644
--- a/utilities/mogrify.1.in
+++ b/utilities/mogrify.1.in
@@ -119,6 +119,7 @@
\-clip-mask filename associate a clip mask with the image
\-clip-path id clip along a named path from the 8BIM profile
\-colorize value colorize the image with the fill color
+ \-color-matrix matrix apply color correction to the image
\-contrast enhance or reduce the image contrast
\-contrast-stretch geometry
improve contrast by `stretching' the intensity range
@@ -175,7 +176,6 @@
\-raise value lighten/darken image edges to create a 3-D effect
\-random-threshold low,high
random threshold the image
- \-recolor matrix apply color correction to the image
\-region geometry apply options to a portion of the image
\-render render vector graphics
\-repage geometry size and location of an image canvas
diff --git a/wand/convert.c b/wand/convert.c
index dc324c0..f24d6c2 100644
--- a/wand/convert.c
+++ b/wand/convert.c
@@ -171,6 +171,7 @@
"-clip-mask filename associate a clip mask with the image",
"-clip-path id clip along a named path from the 8BIM profile",
"-colorize value colorize the image with the fill color",
+ "-color-matrix matrix apply color correction to the image",
"-contrast enhance or reduce the image contrast",
"-contrast-stretch geometry",
" improve contrast by `stretching' the intensity range",
@@ -240,7 +241,6 @@
"-raise value lighten/darken image edges to create a 3-D effect",
"-random-threshold low,high",
" random threshold the image",
- "-recolor matrix apply color correction to the image",
"-region geometry apply options to a portion of the image",
"-render render vector graphics",
"-repage geometry size and location of an image canvas",
@@ -945,6 +945,17 @@
ThrowConvertInvalidArgumentException(option,argv[i]);
break;
}
+ if (LocaleCompare("color-matrix",option+1) == 0)
+ {
+ if (*option == '+')
+ break;
+ i++;
+ if (i == (long) (argc-1))
+ ThrowConvertException(OptionError,"MissingArgument",option);
+ if (IsGeometry(argv[i]) == MagickFalse)
+ ThrowConvertInvalidArgumentException(option,argv[i]);
+ break;
+ }
if (LocaleCompare("colors",option+1) == 0)
{
if (*option == '+')
@@ -1051,7 +1062,7 @@
* These may not work for kernels with 'nan' values, like 'diamond'
*/
GetMagickToken(argv[i],NULL,token);
- if ( isalpha((int)token[0]) )
+ if (isalpha((int) (unsigned char) *token) != 0)
{
long
op;
@@ -1061,9 +1072,9 @@
ThrowConvertException(OptionError,"UnrecognizedKernelType",
token);
}
- /* geometry is currently invalid if a 'nan' value is included */
- else if (IsGeometry(argv[i]) == MagickFalse)
- ThrowConvertInvalidArgumentException(option,argv[i]);
+ else
+ if (IsGeometry(argv[i]) == MagickFalse)
+ ThrowConvertInvalidArgumentException(option,argv[i]);
#endif
break;
}
@@ -1960,12 +1971,12 @@
}
if (LocaleCompare("morphology",option+1) == 0)
{
- long
- op;
-
char
token[MaxTextExtent];
+ long
+ op;
+
i++;
if (i == (long) argc)
ThrowConvertException(OptionError,"MissingArgument",option);
@@ -1973,17 +1984,17 @@
op=ParseMagickOption(MagickMorphologyOptions,MagickFalse,token);
if (op < 0)
ThrowConvertException(OptionError,"UnrecognizedMorphologyMethod",
- token);
+ token);
i++;
if (i == (long) (argc-1))
ThrowConvertException(OptionError,"MissingArgument",option);
GetMagickToken(argv[i],NULL,token);
- if ( isalpha((int)token[0]) )
+ if (isalpha((int) ((unsigned char) *token)) != 0)
{
op=ParseMagickOption(MagickKernelOptions,MagickFalse,token);
if (op < 0)
ThrowConvertException(OptionError,"UnrecognizedKernelType",
- token);
+ token);
}
#if 0
/* DO NOT ENABLE, geometry can not handle user defined kernels
diff --git a/wand/deprecate.c b/wand/deprecate.c
index 4bd5f29..9c28881 100644
--- a/wand/deprecate.c
+++ b/wand/deprecate.c
@@ -1231,6 +1231,61 @@
% %
% %
% %
+% M a g i c k R e c o l o r I m a g e %
+% %
+% %
+% %
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%
+% MagickRecolorImage() apply color transformation to an image. The method
+% permits saturation changes, hue rotation, luminance to alpha, and various
+% other effects. Although variable-sized transformation matrices can be used,
+% typically one uses a 5x5 matrix for an RGBA image and a 6x6 for CMYKA
+% (or RGBA with offsets). The matrix is similar to those used by Adobe Flash
+% except offsets are in column 6 rather than 5 (in support of CMYKA images)
+% and offsets are normalized (divide Flash offset by 255).
+%
+% The format of the MagickRecolorImage method is:
+%
+% MagickBooleanType MagickRecolorImage(MagickWand *wand,
+% const unsigned long order,const double *color_matrix)
+%
+% A description of each parameter follows:
+%
+% o wand: the magick wand.
+%
+% o order: the number of columns and rows in the color matrix.
+%
+% o color_matrix: An array of doubles representing the color matrix.
+%
+*/
+WandExport MagickBooleanType MagickRecolorImage(MagickWand *wand,
+ const unsigned long order,const double *color_matrix)
+{
+ Image
+ *transform_image;
+
+ assert(wand != (MagickWand *) NULL);
+ assert(wand->signature == WandSignature);
+ if (wand->debug != MagickFalse)
+ (void) LogMagickEvent(WandEvent,GetMagickModule(),"%s",wand->name);
+ if (color_matrix == (const double *) NULL)
+ return(MagickFalse);
+ if (wand->images == (Image *) NULL)
+ ThrowWandException(WandError,"ContainsNoImages",wand->name);
+ transform_image=RecolorImage(wand->images,order,color_matrix,
+ wand->exception);
+ if (transform_image == (Image *) NULL)
+ return(MagickFalse);
+ ReplaceImageInList(&wand->images,transform_image);
+ return(MagickTrue);
+}
+
+/*
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+% %
+% %
+% %
% M a g i c k S e t I m a g e A t t r i b u t e %
% %
% %
diff --git a/wand/deprecate.h b/wand/deprecate.h
index 7568f28..8ad710b 100644
--- a/wand/deprecate.h
+++ b/wand/deprecate.h
@@ -78,6 +78,8 @@
magick_attribute((deprecated)),
MagickPaintTransparentImage(MagickWand *,const PixelWand *,const double,
const double) magick_attribute((deprecated)),
+ MagickRecolorImage(MagickWand *,const unsigned long,const double *)
+ magick_attribute((deprecated)),
MagickSetImageAttribute(MagickWand *,const char *,const char *)
magick_attribute((deprecated)),
MagickSetImageIndex(MagickWand *,const long) magick_attribute((deprecated)),
diff --git a/wand/magick-image.c b/wand/magick-image.c
index 5afb72d..3851da0 100644
--- a/wand/magick-image.c
+++ b/wand/magick-image.c
@@ -1613,6 +1613,58 @@
% %
% %
% %
+% M a g i c k C o l o r M a t r i x I m a g e %
+% %
+% %
+% %
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%
+% MagickColorMatrixImage() apply color transformation to an image. The method
+% permits saturation changes, hue rotation, luminance to alpha, and various
+% other effects. Although variable-sized transformation matrices can be used,
+% typically one uses a 5x5 matrix for an RGBA image and a 6x6 for CMYKA
+% (or RGBA with offsets). The matrix is similar to those used by Adobe Flash
+% except offsets are in column 6 rather than 5 (in support of CMYKA images)
+% and offsets are normalized (divide Flash offset by 255).
+%
+% The format of the MagickColorMatrixImage method is:
+%
+% MagickBooleanType MagickColorMatrixImage(MagickWand *wand,
+% const KernelInfo *color_matrix)
+%
+% A description of each parameter follows:
+%
+% o wand: the magick wand.
+%
+% o color_matrix: the color matrix.
+%
+*/
+WandExport MagickBooleanType MagickColorMatrixImage(MagickWand *wand,
+ const KernelInfo *color_matrix)
+{
+ Image
+ *color_image;
+
+ assert(wand != (MagickWand *) NULL);
+ assert(wand->signature == WandSignature);
+ if (wand->debug != MagickFalse)
+ (void) LogMagickEvent(WandEvent,GetMagickModule(),"%s",wand->name);
+ if (color_matrix == (const KernelInfo *) NULL)
+ return(MagickFalse);
+ if (wand->images == (Image *) NULL)
+ ThrowWandException(WandError,"ContainsNoImages",wand->name);
+ color_image=ColorMatrixImage(wand->images,color_matrix,wand->exception);
+ if (color_image == (Image *) NULL)
+ return(MagickFalse);
+ ReplaceImageInList(&wand->images,color_image);
+ return(MagickTrue);
+}
+
+/*
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+% %
+% %
+% %
% M a g i c k C o m b i n e I m a g e s %
% %
% %
@@ -8551,61 +8603,6 @@
% %
% %
% %
-% M a g i c k R e c o l o r I m a g e %
-% %
-% %
-% %
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-%
-% MagickRecolorImage() apply color transformation to an image. The method
-% permits saturation changes, hue rotation, luminance to alpha, and various
-% other effects. Although variable-sized transformation matrices can be used,
-% typically one uses a 5x5 matrix for an RGBA image and a 6x6 for CMYKA
-% (or RGBA with offsets). The matrix is similar to those used by Adobe Flash
-% except offsets are in column 6 rather than 5 (in support of CMYKA images)
-% and offsets are normalized (divide Flash offset by 255).
-%
-% The format of the MagickRecolorImage method is:
-%
-% MagickBooleanType MagickRecolorImage(MagickWand *wand,
-% const unsigned long order,const double *color_matrix)
-%
-% A description of each parameter follows:
-%
-% o wand: the magick wand.
-%
-% o order: the number of columns and rows in the color matrix.
-%
-% o color_matrix: An array of doubles representing the color matrix.
-%
-*/
-WandExport MagickBooleanType MagickRecolorImage(MagickWand *wand,
- const unsigned long order,const double *color_matrix)
-{
- Image
- *transform_image;
-
- assert(wand != (MagickWand *) NULL);
- assert(wand->signature == WandSignature);
- if (wand->debug != MagickFalse)
- (void) LogMagickEvent(WandEvent,GetMagickModule(),"%s",wand->name);
- if (color_matrix == (const double *) NULL)
- return(MagickFalse);
- if (wand->images == (Image *) NULL)
- ThrowWandException(WandError,"ContainsNoImages",wand->name);
- transform_image=RecolorImage(wand->images,order,color_matrix,
- wand->exception);
- if (transform_image == (Image *) NULL)
- return(MagickFalse);
- ReplaceImageInList(&wand->images,transform_image);
- return(MagickTrue);
-}
-
-/*
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-% %
-% %
-% %
% M a g i c k R e d u c e N o i s e I m a g e %
% %
% %
diff --git a/wand/magick-image.h b/wand/magick-image.h
index c279c7e..833279c 100644
--- a/wand/magick-image.h
+++ b/wand/magick-image.h
@@ -113,6 +113,7 @@
MagickClutImageChannel(MagickWand *,const ChannelType,const MagickWand *),
MagickColorDecisionListImage(MagickWand *,const char *),
MagickColorizeImage(MagickWand *,const PixelWand *,const PixelWand *),
+ MagickColorMatrixImage(MagickWand *,const KernelInfo *),
MagickCommentImage(MagickWand *,const char *),
MagickCompositeImage(MagickWand *,const MagickWand *,const CompositeOperator,
const long,const long),
@@ -259,7 +260,6 @@
MagickReadImage(MagickWand *,const char *),
MagickReadImageBlob(MagickWand *,const void *,const size_t),
MagickReadImageFile(MagickWand *,FILE *),
- MagickRecolorImage(MagickWand *,const unsigned long,const double *),
MagickReduceNoiseImage(MagickWand *,const double),
MagickRemapImage(MagickWand *,const MagickWand *,const DitherMethod),
MagickRemoveImage(MagickWand *),
diff --git a/wand/mogrify.c b/wand/mogrify.c
index 75b45d5..dc498c8 100644
--- a/wand/mogrify.c
+++ b/wand/mogrify.c
@@ -1151,6 +1151,26 @@
*image=colorize_image;
break;
}
+ if (LocaleCompare("color-matrix",option+1) == 0)
+ {
+ Image
+ *color_image;
+
+ KernelInfo
+ *kernel;
+
+ (void) SyncImageSettings(image_info,*image);
+ kernel=AcquireKernelInfo(argv[i+1]);
+ if (kernel == (KernelInfo *) NULL)
+ break;
+ color_image=ColorMatrixImage(*image,kernel,exception);
+ kernel=DestroyKernelInfo(kernel);
+ if (color_image == (Image *) NULL)
+ break;
+ *image=DestroyImage(*image);
+ *image=color_image;
+ break;
+ }
if (LocaleCompare("colors",option+1) == 0)
{
/*
@@ -3686,6 +3706,7 @@
"-clip-mask filename associate a clip mask with the image",
"-clip-path id clip along a named path from the 8BIM profile",
"-colorize value colorize the image with the fill color",
+ "-color-matrix matrix apply color correction to the image",
"-contrast enhance or reduce the image contrast",
"-contrast-stretch geometry",
" improve contrast by `stretching' the intensity range",
@@ -3755,7 +3776,6 @@
"-raise value lighten/darken image edges to create a 3-D effect",
"-random-threshold low,high",
" random threshold the image",
- "-recolor matrix apply color correction to the image",
"-region geometry apply options to a portion of the image",
"-render render vector graphics",
"-repage geometry size and location of an image canvas",
@@ -4461,6 +4481,17 @@
ThrowMogrifyInvalidArgumentException(option,argv[i]);
break;
}
+ if (LocaleCompare("color-matrix",option+1) == 0)
+ {
+ if (*option == '+')
+ break;
+ i++;
+ if (i == (long) (argc-1))
+ ThrowMogrifyException(OptionError,"MissingArgument",option);
+ if (IsGeometry(argv[i]) == MagickFalse)
+ ThrowMogrifyInvalidArgumentException(option,argv[i]);
+ break;
+ }
if (LocaleCompare("colors",option+1) == 0)
{
if (*option == '+')
@@ -5713,6 +5744,17 @@
ThrowMogrifyInvalidArgumentException(option,argv[i]);
break;
}
+ if (LocaleCompare("recolor",option+1) == 0)
+ {
+ if (*option == '+')
+ break;
+ i++;
+ if (i == (long) (argc-1))
+ ThrowMogrifyException(OptionError,"MissingArgument",option);
+ if (IsGeometry(argv[i]) == MagickFalse)
+ ThrowMogrifyInvalidArgumentException(option,argv[i]);
+ break;
+ }
if (LocaleCompare("red-primary",option+1) == 0)
{
if (*option == '+')