From: cristy Date: Fri, 2 Apr 2010 17:31:23 +0000 (+0000) Subject: (no commit message) X-Git-Tag: 7.0.1-0~9709 X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=e636559dfadfdb115cc93f223315052a1ee89238;p=imagemagick --- diff --git a/PerlMagick/Magick.xs b/PerlMagick/Magick.xs index c7ab9c1dd..ef3d2e9af 100644 --- a/PerlMagick/Magick.xs +++ b/PerlMagick/Magick.xs @@ -528,6 +528,7 @@ static struct { "Morphology", { {"kernel", StringReference}, {"channel", MagickChannelOptions}, {"method", MagickMorphologyOptions}, {"iterations", IntegerReference} } }, + { "ColorMatrix", { {"matrix", StringReference} } }, }; static SplayTreeInfo @@ -7182,6 +7183,8 @@ Mogrify(ref,...) BrightnessContrastImage = 264 Morphology = 265 MorphologyImage = 266 + ColorMatrix = 267 + ColorMatrixImage = 268 MogrifyRegion = 666 PPCODE: { @@ -10482,6 +10485,20 @@ Mogrify(ref,...) 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 2b1c19613..66f75a8a9 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 @@ static MagickBooleanType WritePSDImage(const ImageInfo *image_info,Image *image) */ 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 04d45fb07..52df13097 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 @@ MagickExport void ReacquireMemory(void **memory,const size_t size) % % % % % % +% 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 89c44aa24..134a316d4 100644 --- a/magick/deprecate.h +++ b/magick/deprecate.h @@ -128,6 +128,8 @@ extern MagickExport Image *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 5f28131d8..4ac16c7ad 100644 --- a/magick/fx.c +++ b/magick/fx.c @@ -807,6 +807,232 @@ MagickExport Image *ColorizeImage(const Image *image,const char *opacity, % % % % % % +% 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 @@ MagickExport Image *PolaroidImage(const Image *image,const DrawInfo *draw_info, % % % % % % -% 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 1087ba079..68eccbb27 100644 --- a/magick/fx.h +++ b/magick/fx.h @@ -43,13 +43,12 @@ extern MagickExport Image *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 b52f298e7..02118f7b6 100644 --- a/magick/morphology.c +++ b/magick/morphology.c @@ -931,7 +931,7 @@ MagickExport KernelInfo *AcquireKernelBuiltIn(const KernelInfoType type, % 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 26b4a750f..2d8a6ca2f 100644 --- a/magick/option.c +++ b/magick/option.c @@ -238,6 +238,8 @@ static const OptionInfo { "-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 8a72a8086..139e4818d 100644 --- a/utilities/convert.1.in +++ b/utilities/convert.1.in @@ -115,6 +115,7 @@ Image Operators: \-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 @@ Image Operators: \-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 a7ea4555b..300c7aa8f 100644 --- a/utilities/mogrify.1.in +++ b/utilities/mogrify.1.in @@ -119,6 +119,7 @@ Image Operators: \-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 @@ Image Operators: \-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 dc324c0ad..f24d6c298 100644 --- a/wand/convert.c +++ b/wand/convert.c @@ -171,6 +171,7 @@ static MagickBooleanType ConvertUsage(void) "-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 @@ static MagickBooleanType ConvertUsage(void) "-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 @@ WandExport MagickBooleanType ConvertImageCommand(ImageInfo *image_info, 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 @@ WandExport MagickBooleanType ConvertImageCommand(ImageInfo *image_info, * 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 @@ WandExport MagickBooleanType ConvertImageCommand(ImageInfo *image_info, 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 @@ WandExport MagickBooleanType ConvertImageCommand(ImageInfo *image_info, } 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 @@ WandExport MagickBooleanType ConvertImageCommand(ImageInfo *image_info, 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 4bd5f2975..9c2888170 100644 --- a/wand/deprecate.c +++ b/wand/deprecate.c @@ -1231,6 +1231,61 @@ WandExport MagickBooleanType MagickPaintTransparentImage(MagickWand *wand, % % % % % % +% 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 7568f284f..8ad710bc1 100644 --- a/wand/deprecate.h +++ b/wand/deprecate.h @@ -78,6 +78,8 @@ extern WandExport MagickBooleanType 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 5afb72dfb..3851da041 100644 --- a/wand/magick-image.c +++ b/wand/magick-image.c @@ -1613,6 +1613,58 @@ WandExport MagickBooleanType MagickColorizeImage(MagickWand *wand, % % % % % % +% 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 @@ WandExport MagickBooleanType MagickReadImageFile(MagickWand *wand,FILE *file) % % % % % % -% 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 c279c7ee7..833279c29 100644 --- a/wand/magick-image.h +++ b/wand/magick-image.h @@ -113,6 +113,7 @@ extern WandExport MagickBooleanType 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 @@ extern WandExport MagickBooleanType 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 75b45d5fd..dc498c890 100644 --- a/wand/mogrify.c +++ b/wand/mogrify.c @@ -1151,6 +1151,26 @@ WandExport MagickBooleanType MogrifyImage(ImageInfo *image_info,const int argc, *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 @@ static MagickBooleanType MogrifyUsage(void) "-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 @@ static MagickBooleanType MogrifyUsage(void) "-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 @@ WandExport MagickBooleanType MogrifyImageCommand(ImageInfo *image_info, 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 @@ WandExport MagickBooleanType MogrifyImageCommand(ImageInfo *image_info, 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 == '+')